Files
yara724api/src/helpers/unified-file-status.ts
Sepehr Yahyaee e9c02811f7 V4: add WAITING_FOR_FILE_REVIEWER claim status; fix select-outer-parts for split flow
- Add ClaimCaseStatus.WAITING_FOR_FILE_REVIEWER (V4 split flow only)
- Set claim status to WAITING_FOR_FILE_REVIEWER when FileMaker uploads
  the last required document (v3InPersonFlow path), replacing the old
  behaviour that incorrectly auto-advanced to SELECT_OUTER_PARTS
- advanceV3ClaimToOuterPartsIfReady: also allow canAdvance when
  claimCase.status === WAITING_FOR_FILE_REVIEWER so the FileReviewer
  can call select-outer-parts after submitting accident fields
- Add WAITING_FOR_FILE_REVIEWER to CLAIM_USER_PHASE (unified-file-status)
  so the file still resolves to IN_PROGRESS in the unified status report
- Add WAITING_FOR_FILE_REVIEWER to CLAIM_IN_PROGRESS_STATUSES
  (expert-panel-status-report) for the expert report bucket
- Add WAITING_FOR_FILE_REVIEWER to claimInHandling set
  (expert-insurer.service) so insurer stats count these correctly
2026-07-05 15:13:19 +03:30

224 lines
6.9 KiB
TypeScript

import { CaseStatus } from "src/Types&Enums/blame-request-management/caseStatus.enum";
import { ClaimCaseStatus } from "src/Types&Enums/claim-request-management/claim-case-status.enum";
/** Calculated lifecycle status for a publicId (blame + claim combined). */
export const UNIFIED_FILE_STATUS_KEYS = [
"IN_PROGRESS",
"WAITING_FOR_SECOND_PARTY",
"WAITING_FOR_BLAME_EXPERT",
"WAITING_FOR_SIGNATURES",
"WAITING_FOR_DOCUMENT_RESEND",
"WAITING_FOR_DAMAGE_EXPERT",
"EXPERT_REVIEWING",
"EXPERT_VALIDATING_FACTORS",
"INSURER_REVIEW",
"COMPLETED",
"CANCELLED",
"REJECTED",
"STOPPED",
] as const;
export type UnifiedFileStatusKey = (typeof UNIFIED_FILE_STATUS_KEYS)[number];
export type UnifiedFileStatusInput = {
blameStatus?: string | null;
claimStatus?: string | null;
};
const CLAIM_USER_PHASE = new Set<string>([
ClaimCaseStatus.CREATED,
ClaimCaseStatus.SELECTING_OUTER_PARTS,
ClaimCaseStatus.SELECTING_OTHER_PARTS,
ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS,
ClaimCaseStatus.CAPTURING_PART_DAMAGES,
// V4 split flow: FileMaker sealed the file; FileReviewer hasn't picked it up yet.
ClaimCaseStatus.WAITING_FOR_FILE_REVIEWER,
]);
const INSURER_REVIEW_CLAIM_STATUSES = new Set<string>([
ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL,
ClaimCaseStatus.INSURER_REVIEW_AWAITING_OWNER_SIGN,
ClaimCaseStatus.INSURER_REVIEW_MIXED_FACTORS_PENDING,
ClaimCaseStatus.OWNER_REPAIR_FACTOR_UPLOAD_PENDING,
]);
export type UnifiedFileStatusDefinition = {
key: UnifiedFileStatusKey;
labelEn: string;
labelFa: string;
description: string;
};
export const UNIFIED_FILE_STATUS_CATALOG: UnifiedFileStatusDefinition[] = [
{
key: "IN_PROGRESS",
labelEn: "In progress (user)",
labelFa: "در حال تکمیل توسط کاربر",
description:
"Parties are still filling blame steps and/or the damaged party is completing the claim (parts, documents, capture).",
},
{
key: "WAITING_FOR_SECOND_PARTY",
labelEn: "Waiting for second party",
labelFa: "در انتظار طرف دوم",
description: "Blame file is waiting for the second party to join or complete steps.",
},
{
key: "WAITING_FOR_BLAME_EXPERT",
labelEn: "Waiting for blame expert",
labelFa: "در انتظار کارشناس مقصر",
description: "Blame case is in the expert disagreement / guilt-decision queue.",
},
{
key: "WAITING_FOR_SIGNATURES",
labelEn: "Waiting for signatures",
labelFa: "در انتظار امضا",
description: "Blame file is waiting for party signatures on the expert decision.",
},
{
key: "WAITING_FOR_DOCUMENT_RESEND",
labelEn: "Waiting for document resend",
labelFa: "در انتظار ارسال مجدد مدارک",
description:
"Blame or claim is waiting for the user to resubmit documents or photos requested by an expert.",
},
{
key: "WAITING_FOR_DAMAGE_EXPERT",
labelEn: "Waiting for damage expert",
labelFa: "در انتظار کارشناس خسارت",
description: "Claim is in the damage-expert review queue (not yet locked).",
},
{
key: "EXPERT_REVIEWING",
labelEn: "Damage expert reviewing",
labelFa: "در حال بررسی کارشناس خسارت",
description: "A damage expert has locked the claim and is assessing damage.",
},
{
key: "EXPERT_VALIDATING_FACTORS",
labelEn: "Validating repair factors",
labelFa: "اعتبارسنجی فاکتور تعمیر",
description: "Damage expert is validating uploaded repair-factor documents.",
},
{
key: "INSURER_REVIEW",
labelEn: "Insurer / owner review",
labelFa: "بررسی بیمه‌گر / مالک",
description:
"Expert pricing is done; owner signature, factor upload, or insurer approval is pending.",
},
{
key: "COMPLETED",
labelEn: "Completed",
labelFa: "تکمیل شده",
description: "Claim (and blame when present) is finished successfully.",
},
{
key: "CANCELLED",
labelEn: "Cancelled",
labelFa: "لغو شده",
description: "File was cancelled or auto-closed.",
},
{
key: "REJECTED",
labelEn: "Rejected",
labelFa: "رد شده",
description: "Claim was rejected.",
},
{
key: "STOPPED",
labelEn: "Stopped",
labelFa: "متوقف شده",
description: "Blame file was stopped.",
},
];
export function initialUnifiedFileStatusCounts(): Record<
UnifiedFileStatusKey | "all",
number
> {
const out: Record<string, number> = { all: 0 };
for (const key of UNIFIED_FILE_STATUS_KEYS) {
out[key] = 0;
}
return out as Record<UnifiedFileStatusKey | "all", number>;
}
/**
* Single calculatable status for a shared publicId from raw blame + claim statuses.
* Claim pipeline takes precedence once a claim exists and has left the user-only phase.
*/
export function resolveUnifiedFileStatus(
input: UnifiedFileStatusInput,
): UnifiedFileStatusKey {
const blame = input.blameStatus?.trim() || undefined;
const claim = input.claimStatus?.trim() || undefined;
if (claim === ClaimCaseStatus.COMPLETED) return "COMPLETED";
if (claim === ClaimCaseStatus.REJECTED) return "REJECTED";
if (
claim === ClaimCaseStatus.CANCELLED ||
blame === CaseStatus.CANCELLED ||
blame === CaseStatus.AUTO_CLOSED
) {
return "CANCELLED";
}
if (blame === CaseStatus.STOPPED) return "STOPPED";
if (
blame === CaseStatus.WAITING_FOR_DOCUMENT_RESEND ||
claim === ClaimCaseStatus.WAITING_FOR_USER_RESEND
) {
return "WAITING_FOR_DOCUMENT_RESEND";
}
if (claim === ClaimCaseStatus.EXPERT_REVIEWING) return "EXPERT_REVIEWING";
if (claim === ClaimCaseStatus.EXPERT_VALIDATING_REPAIR_FACTORS) {
return "EXPERT_VALIDATING_FACTORS";
}
if (claim && INSURER_REVIEW_CLAIM_STATUSES.has(claim)) {
return "INSURER_REVIEW";
}
if (claim === ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT) {
return "WAITING_FOR_DAMAGE_EXPERT";
}
if (blame === CaseStatus.WAITING_FOR_EXPERT) return "WAITING_FOR_BLAME_EXPERT";
if (blame === CaseStatus.WAITING_FOR_SIGNATURES) {
return "WAITING_FOR_SIGNATURES";
}
if (blame === CaseStatus.WAITING_FOR_SECOND_PARTY) {
return "WAITING_FOR_SECOND_PARTY";
}
if (blame === CaseStatus.COMPLETED && !claim) return "COMPLETED";
if (
blame === CaseStatus.OPEN ||
(claim && CLAIM_USER_PHASE.has(claim)) ||
(blame === CaseStatus.COMPLETED && claim && CLAIM_USER_PHASE.has(claim))
) {
return "IN_PROGRESS";
}
if (claim) return "IN_PROGRESS";
if (blame) return "IN_PROGRESS";
return "IN_PROGRESS";
}
export function countUnifiedFileStatuses(
entries: UnifiedFileStatusInput[],
): Record<UnifiedFileStatusKey | "all", number> {
const buckets = initialUnifiedFileStatusCounts();
for (const entry of entries) {
const key = resolveUnifiedFileStatus(entry);
buckets.all++;
buckets[key]++;
}
return buckets;
}
export function getUnifiedFileStatusCatalog(): UnifiedFileStatusDefinition[] {
return UNIFIED_FILE_STATUS_CATALOG;
}