Files
yara724api/src/helpers/claim-capture-phase.ts
2026-05-16 11:16:08 +03:30

128 lines
3.8 KiB
TypeScript

import {
CLAIM_CAR_ANGLE_KEYS,
hasClaimCarAngleCapture,
hasDamagedPartCapture,
} from "src/helpers/claim-car-angle-media";
import {
catalogLikeKeyFromPart,
normalizeDamageSelectedParts,
} from "src/helpers/outer-damage-parts";
import type { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
/** Upload during CAPTURE_PART_DAMAGES (after parts + angles). */
export const CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS = [
"damaged_chassis_number",
"damaged_engine_photo",
"damaged_metal_plate",
] as const;
export type CapturePhaseSequence =
| "parts"
| "angles"
| "capture_phase_documents"
| "complete";
export interface ClaimCaptureProgress {
partsCaptured: number;
partsTotal: number;
partsComplete: boolean;
anglesCaptured: number;
anglesTotal: number;
anglesComplete: boolean;
capturePhaseDocsComplete: boolean;
capturePhaseDocsRemaining: number;
sequencePhase: CapturePhaseSequence;
}
export function isCapturePhaseDamagedPartyDocKey(key: string): boolean {
return (CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS as readonly string[]).includes(
key,
);
}
function isRequiredDocumentUploadedOnClaim(
claimCase: any,
key: string,
): boolean {
const doc =
(claimCase?.requiredDocuments as any)?.get?.(key) ??
claimCase?.requiredDocuments?.[key];
return !!doc?.uploaded;
}
export function getClaimCaptureProgress(
claimCase: any,
options?: { assumeCapturePhaseDocKey?: string },
): ClaimCaptureProgress {
const carType = claimCase?.vehicle?.carType as ClaimVehicleTypeV2 | undefined;
const selectedNorm = normalizeDamageSelectedParts(
claimCase?.damage?.selectedParts,
carType,
claimCase?.damage?.selectedOuterParts,
);
const carAnglesData = claimCase?.media?.carAngles;
const damagedPartsData = claimCase?.media?.damagedParts;
const anglesCaptured = CLAIM_CAR_ANGLE_KEYS.filter((k) =>
hasClaimCarAngleCapture(carAnglesData, damagedPartsData, k),
).length;
const partsCaptured = selectedNorm.filter((sp) => {
const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp);
return hasDamagedPartCapture(damagedPartsData, ck, selectedNorm);
}).length;
const partsTotal = selectedNorm.length;
const partsComplete = partsTotal === 0 || partsCaptured >= partsTotal;
const anglesTotal = CLAIM_CAR_ANGLE_KEYS.length;
const anglesComplete = anglesCaptured >= anglesTotal;
const capturePhaseDocsRemaining = CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.filter(
(k) => {
if (k === options?.assumeCapturePhaseDocKey) return false;
return !isRequiredDocumentUploadedOnClaim(claimCase, k);
},
).length;
const capturePhaseDocsComplete = capturePhaseDocsRemaining === 0;
let sequencePhase: CapturePhaseSequence = "parts";
if (partsComplete && !anglesComplete) {
sequencePhase = "angles";
} else if (partsComplete && anglesComplete && !capturePhaseDocsComplete) {
sequencePhase = "capture_phase_documents";
} else if (partsComplete && anglesComplete && capturePhaseDocsComplete) {
sequencePhase = "complete";
}
return {
partsCaptured,
partsTotal,
partsComplete,
anglesCaptured,
anglesTotal,
anglesComplete,
capturePhaseDocsComplete,
capturePhaseDocsRemaining,
sequencePhase,
};
}
export function isClaimCaptureStepComplete(claimCase: any): boolean {
const p = getClaimCaptureProgress(claimCase);
return (
p.partsComplete && p.anglesComplete && p.capturePhaseDocsComplete
);
}
export function capturePhaseSequenceMessage(phase: CapturePhaseSequence): string {
switch (phase) {
case "parts":
return "Upload photos for all selected damaged parts first.";
case "angles":
return "Capture all four car angles (front, back, left, right) next.";
case "capture_phase_documents":
return "Upload chassis number, engine photo, and damaged metal plate photos last.";
default:
return "Damage capture is complete.";
}
}