forked from Yara724/api
Fixed 3 upload documents for capture part
This commit is contained in:
95
src/helpers/claim-capture-phase.spec.ts
Normal file
95
src/helpers/claim-capture-phase.spec.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
getClaimCaptureProgress,
|
||||
isClaimCaptureStepComplete,
|
||||
} from "./claim-capture-phase";
|
||||
|
||||
describe("claim-capture-phase", () => {
|
||||
const baseClaim = {
|
||||
vehicle: { carType: "sedan" },
|
||||
damage: {
|
||||
selectedParts: [{ name: "hood", side: "front", label_fa: "کاپوت" }],
|
||||
},
|
||||
media: { carAngles: {}, damagedParts: [] },
|
||||
requiredDocuments: {},
|
||||
};
|
||||
|
||||
it("starts in parts phase", () => {
|
||||
const p = getClaimCaptureProgress(baseClaim);
|
||||
expect(p.sequencePhase).toBe("parts");
|
||||
expect(p.partsComplete).toBe(false);
|
||||
});
|
||||
|
||||
it("moves to angles after all parts", () => {
|
||||
const claim = {
|
||||
...baseClaim,
|
||||
media: {
|
||||
carAngles: {},
|
||||
damagedParts: [
|
||||
{
|
||||
name: "hood",
|
||||
side: "front",
|
||||
label_fa: "کاپوت",
|
||||
path: "/x.jpg",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const p = getClaimCaptureProgress(claim);
|
||||
expect(p.sequencePhase).toBe("angles");
|
||||
expect(p.partsComplete).toBe(true);
|
||||
expect(p.anglesComplete).toBe(false);
|
||||
});
|
||||
|
||||
it("does not complete capture step with only capture-phase docs uploaded", () => {
|
||||
const claim = {
|
||||
...baseClaim,
|
||||
media: {
|
||||
carAngles: {},
|
||||
damagedParts: [
|
||||
{
|
||||
name: "hood",
|
||||
side: "front",
|
||||
label_fa: "کاپوت",
|
||||
path: "/x.jpg",
|
||||
},
|
||||
],
|
||||
},
|
||||
requiredDocuments: {
|
||||
damaged_chassis_number: { uploaded: true },
|
||||
damaged_engine_photo: { uploaded: true },
|
||||
damaged_metal_plate: { uploaded: true },
|
||||
},
|
||||
};
|
||||
expect(isClaimCaptureStepComplete(claim)).toBe(false);
|
||||
expect(getClaimCaptureProgress(claim).sequencePhase).toBe("angles");
|
||||
});
|
||||
|
||||
it("is complete only when parts, angles, and capture-phase docs are done", () => {
|
||||
const claim = {
|
||||
...baseClaim,
|
||||
media: {
|
||||
carAngles: {
|
||||
front: { path: "/f.jpg" },
|
||||
back: { path: "/b.jpg" },
|
||||
left: { path: "/l.jpg" },
|
||||
right: { path: "/r.jpg" },
|
||||
},
|
||||
damagedParts: [
|
||||
{
|
||||
name: "hood",
|
||||
side: "front",
|
||||
label_fa: "کاپوت",
|
||||
path: "/x.jpg",
|
||||
},
|
||||
],
|
||||
},
|
||||
requiredDocuments: {
|
||||
damaged_chassis_number: { uploaded: true },
|
||||
damaged_engine_photo: { uploaded: true },
|
||||
damaged_metal_plate: { uploaded: true },
|
||||
},
|
||||
};
|
||||
expect(isClaimCaptureStepComplete(claim)).toBe(true);
|
||||
expect(getClaimCaptureProgress(claim).sequencePhase).toBe("complete");
|
||||
});
|
||||
});
|
||||
127
src/helpers/claim-capture-phase.ts
Normal file
127
src/helpers/claim-capture-phase.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
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.";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user