forked from Yara724/api
Fixed 3 upload documents for capture part
This commit is contained in:
@@ -120,16 +120,13 @@ import {
|
||||
resolvePartCaptureIndex,
|
||||
} from "src/helpers/outer-damage-parts";
|
||||
|
||||
/** Same `requiredDocuments` keys as in getCaptureRequirementsV2; upload allowed during CAPTURE_PART_DAMAGES. */
|
||||
const CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS = [
|
||||
"damaged_chassis_number",
|
||||
"damaged_engine_photo",
|
||||
"damaged_metal_plate",
|
||||
] as const;
|
||||
|
||||
function isCapturePhaseDamagedPartyDocKey(key: string): boolean {
|
||||
return (CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS as readonly string[]).includes(key);
|
||||
}
|
||||
import {
|
||||
CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS,
|
||||
capturePhaseSequenceMessage,
|
||||
getClaimCaptureProgress,
|
||||
isCapturePhaseDamagedPartyDocKey,
|
||||
isClaimCaptureStepComplete,
|
||||
} from "src/helpers/claim-capture-phase";
|
||||
|
||||
@Injectable()
|
||||
export class ClaimRequestManagementService {
|
||||
@@ -203,12 +200,6 @@ export class ClaimRequestManagementService {
|
||||
return !!doc?.uploaded;
|
||||
}
|
||||
|
||||
private capturePhaseDamagedPartyDocsComplete(claimCase: any): boolean {
|
||||
return CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.every((k) =>
|
||||
this.isRequiredDocumentUploadedOnClaim(claimCase, k),
|
||||
);
|
||||
}
|
||||
|
||||
private allV2OwnerDocumentsComplete(
|
||||
claimCase: any,
|
||||
isCarBody: boolean,
|
||||
@@ -4633,15 +4624,31 @@ export class ClaimRequestManagementService {
|
||||
const anglesCaptured = carAngles.filter(a => a.captured).length;
|
||||
const partsCaptured = damagedParts.filter(p => p.captured).length;
|
||||
|
||||
const totalRemaining =
|
||||
(requiredDocuments.length - documentsUploaded) +
|
||||
(carAngles.length - anglesCaptured) +
|
||||
(damagedParts.length - partsCaptured);
|
||||
const captureProgress = getClaimCaptureProgress(claimCase);
|
||||
const capturePhaseDocsRemaining = captureProgress.capturePhaseDocsRemaining;
|
||||
const partsRemaining = Math.max(
|
||||
0,
|
||||
captureProgress.partsTotal - captureProgress.partsCaptured,
|
||||
);
|
||||
const anglesRemaining = Math.max(
|
||||
0,
|
||||
captureProgress.anglesTotal - captureProgress.anglesCaptured,
|
||||
);
|
||||
const postCaptureDocsRemaining = requiredDocuments.filter(
|
||||
(d) => !d.preferUploadDuringCapture && !d.uploaded,
|
||||
).length;
|
||||
|
||||
const totalRemaining =
|
||||
partsRemaining + anglesRemaining + capturePhaseDocsRemaining;
|
||||
|
||||
return {
|
||||
claimRequestId: claimCase._id.toString(),
|
||||
publicId: claimCase.publicId,
|
||||
currentStep: claimCase.workflow?.currentStep || '',
|
||||
captureSequencePhase: captureProgress.sequencePhase,
|
||||
captureSequenceHint: capturePhaseSequenceMessage(
|
||||
captureProgress.sequencePhase,
|
||||
),
|
||||
requiredDocuments,
|
||||
carAngles,
|
||||
damagedParts,
|
||||
@@ -4653,6 +4660,8 @@ export class ClaimRequestManagementService {
|
||||
anglesTotal: carAngles.length,
|
||||
partsCaptured,
|
||||
partsTotal: damagedParts.length,
|
||||
capturePhaseDocsRemaining,
|
||||
postCaptureDocumentsRemaining: postCaptureDocsRemaining,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -4796,9 +4805,22 @@ export class ClaimRequestManagementService {
|
||||
if (!isResendUpload) {
|
||||
if (step === ClaimWorkflowStep.CAPTURE_PART_DAMAGES && !isCapturePhaseDocUpload) {
|
||||
throw new BadRequestException(
|
||||
`During ${ClaimWorkflowStep.CAPTURE_PART_DAMAGES} only chassis, engine, and damaged metal plate photos may be uploaded here (${CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.join(", ")}).`,
|
||||
`During ${ClaimWorkflowStep.CAPTURE_PART_DAMAGES} only chassis, engine, and damaged metal plate photos may be uploaded here (${CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.join(", ")}), and only after all damaged parts and car angles are captured.`,
|
||||
);
|
||||
}
|
||||
if (isCapturePhaseDocUpload) {
|
||||
const captureProgress = getClaimCaptureProgress(claimCase);
|
||||
if (!captureProgress.partsComplete) {
|
||||
throw new BadRequestException(
|
||||
"Upload photos for all selected damaged parts before uploading chassis, engine, or metal plate photos.",
|
||||
);
|
||||
}
|
||||
if (!captureProgress.anglesComplete) {
|
||||
throw new BadRequestException(
|
||||
"Capture all four car angles (front, back, left, right) before uploading chassis, engine, or metal plate photos.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const allowedInitialUploadStep =
|
||||
step === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS || isCapturePhaseDocUpload;
|
||||
if (!allowedInitialUploadStep) {
|
||||
@@ -4896,31 +4918,14 @@ export class ClaimRequestManagementService {
|
||||
allDocumentsUploaded = false;
|
||||
|
||||
if (remaining === 0) {
|
||||
// After this upload all 3 capture-phase docs will be on the claim.
|
||||
// Check angles + parts captures using the in-memory claim media.
|
||||
const carAnglesData = (claimCase.media as any)?.carAngles;
|
||||
const damagedPartsData = (claimCase.media as any)?.damagedParts;
|
||||
const selectedNorm = normalizeDamageSelectedParts(
|
||||
claimCase.damage?.selectedParts,
|
||||
claimCase.vehicle?.carType as ClaimVehicleTypeV2,
|
||||
(claimCase.damage as any)?.selectedOuterParts,
|
||||
);
|
||||
const anglesKeys = ["front", "back", "left", "right"];
|
||||
const anglesCaptured = anglesKeys.filter((k) =>
|
||||
hasClaimCarAngleCapture(
|
||||
carAnglesData,
|
||||
damagedPartsData,
|
||||
k as ClaimCarAngleKey,
|
||||
),
|
||||
).length;
|
||||
const partsCaptured = selectedNorm.filter((sp) => {
|
||||
const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp);
|
||||
return hasDamagedPartCapture(damagedPartsData, ck, selectedNorm);
|
||||
}).length;
|
||||
const progressAfterDoc = getClaimCaptureProgress(claimCase, {
|
||||
assumeCapturePhaseDocKey: body.documentKey,
|
||||
});
|
||||
|
||||
if (
|
||||
anglesCaptured >= 4 &&
|
||||
partsCaptured >= selectedNorm.length
|
||||
progressAfterDoc.partsComplete &&
|
||||
progressAfterDoc.anglesComplete &&
|
||||
progressAfterDoc.capturePhaseDocsComplete
|
||||
) {
|
||||
captureStepCompletedOnThisUpload = true;
|
||||
updateData["status"] = ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS;
|
||||
@@ -5031,8 +5036,12 @@ export class ClaimRequestManagementService {
|
||||
? captureStepCompletedOnThisUpload
|
||||
? "Capture-phase documents and all damage captures are complete. Please proceed to upload the remaining required documents."
|
||||
: remaining > 0
|
||||
? `Document saved. ${remaining} capture-phase document(s) still required (chassis, engine, metal plate) before you can finish damage capture.`
|
||||
: "Document saved. All capture-phase documents are uploaded; finish car angles and part photos to proceed."
|
||||
? `Document saved. ${remaining} capture-phase document(s) still required (chassis, engine, metal plate).`
|
||||
: capturePhaseSequenceMessage(
|
||||
getClaimCaptureProgress(claimCase, {
|
||||
assumeCapturePhaseDocKey: body.documentKey,
|
||||
}).sequencePhase,
|
||||
)
|
||||
: allDocumentsUploaded
|
||||
? "All documents uploaded successfully. Your claim is now ready for damage expert review."
|
||||
: `Document uploaded successfully. ${remaining} documents remaining.`;
|
||||
@@ -5114,6 +5123,19 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
if (!isResendCapture) {
|
||||
const captureProgressBefore = getClaimCaptureProgress(claimCase);
|
||||
const willBeAngle =
|
||||
body.captureType === "angle" ||
|
||||
(body.captureType === "part" &&
|
||||
canonicalizeClaimCarAngleKey(body.captureKey) !== null);
|
||||
if (willBeAngle && !captureProgressBefore.partsComplete) {
|
||||
throw new BadRequestException(
|
||||
"Upload photos for all selected damaged parts before capturing car angles.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const angleCanon = canonicalizeClaimCarAngleKey(body.captureKey);
|
||||
if (body.captureType === "angle" && !angleCanon) {
|
||||
throw new BadRequestException(
|
||||
@@ -5269,40 +5291,8 @@ export class ClaimRequestManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
const hasCapture = (data: any, key: string) =>
|
||||
data && (data instanceof Map ? data.get(key) : data[key]);
|
||||
|
||||
// Use same logic as getCaptureRequirementsV2 to determine completion
|
||||
const anglesKeys = ["front", "back", "left", "right"];
|
||||
const carAnglesData = updatedClaim?.media?.carAngles as any;
|
||||
const damagedPartsData = updatedClaim?.media?.damagedParts as any;
|
||||
const selectedNormAfter = normalizeDamageSelectedParts(
|
||||
updatedClaim?.damage?.selectedParts,
|
||||
updatedClaim?.vehicle?.carType as ClaimVehicleTypeV2,
|
||||
(updatedClaim?.damage as any)?.selectedOuterParts,
|
||||
);
|
||||
|
||||
const anglesCaptured = anglesKeys.filter((k) =>
|
||||
hasClaimCarAngleCapture(
|
||||
carAnglesData,
|
||||
damagedPartsData,
|
||||
k as ClaimCarAngleKey,
|
||||
),
|
||||
).length;
|
||||
const partsCaptured = selectedNormAfter.filter((sp) => {
|
||||
const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp);
|
||||
return hasDamagedPartCapture(
|
||||
damagedPartsData,
|
||||
ck,
|
||||
selectedNormAfter,
|
||||
);
|
||||
}).length;
|
||||
|
||||
const capturePhaseDocsDone = this.capturePhaseDamagedPartyDocsComplete(updatedClaim);
|
||||
const allCapturesComplete =
|
||||
anglesCaptured >= 4 &&
|
||||
partsCaptured >= selectedNormAfter.length &&
|
||||
capturePhaseDocsDone;
|
||||
const captureProgress = getClaimCaptureProgress(updatedClaim);
|
||||
const allCapturesComplete = isClaimCaptureStepComplete(updatedClaim);
|
||||
|
||||
if (allCapturesComplete) {
|
||||
await this.claimCaseDbService.findByIdAndUpdate(claimRequestId, {
|
||||
@@ -5329,16 +5319,21 @@ export class ClaimRequestManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
const captureDocsRemaining = CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.filter(
|
||||
(k) => !this.isRequiredDocumentUploadedOnClaim(updatedClaim, k),
|
||||
).length;
|
||||
const partsRemaining = Math.max(
|
||||
0,
|
||||
captureProgress.partsTotal - captureProgress.partsCaptured,
|
||||
);
|
||||
const anglesRemaining = Math.max(
|
||||
0,
|
||||
captureProgress.anglesTotal - captureProgress.anglesCaptured,
|
||||
);
|
||||
const remaining =
|
||||
(4 - anglesCaptured) +
|
||||
(selectedNormAfter.length - partsCaptured) +
|
||||
captureDocsRemaining;
|
||||
partsRemaining +
|
||||
anglesRemaining +
|
||||
captureProgress.capturePhaseDocsRemaining;
|
||||
const message = allCapturesComplete
|
||||
? 'All captures complete. Please proceed to upload required documents.'
|
||||
: `${body.captureType === 'angle' ? 'Angle' : 'Part'} captured successfully. ${remaining} items remaining (angles, parts, and capture-phase documents).`;
|
||||
? "All captures complete. Please proceed to upload the remaining required documents."
|
||||
: `${body.captureType === "angle" ? "Angle" : "Part"} captured successfully. ${capturePhaseSequenceMessage(captureProgress.sequencePhase)} (${remaining} item(s) left in this step).`;
|
||||
|
||||
return {
|
||||
claimRequestId: claimCase._id.toString(),
|
||||
@@ -5393,6 +5388,18 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
const captureProgress = getClaimCaptureProgress(claimCase);
|
||||
if (!captureProgress.partsComplete) {
|
||||
throw new BadRequestException(
|
||||
"Upload photos for all selected damaged parts before uploading the walk-around video.",
|
||||
);
|
||||
}
|
||||
if (!captureProgress.anglesComplete) {
|
||||
throw new BadRequestException(
|
||||
"Capture all four car angles (front, back, left, right) before uploading the walk-around video.",
|
||||
);
|
||||
}
|
||||
|
||||
if (claimCase.media?.videoCaptureId) {
|
||||
throw new ConflictException('A video has already been uploaded for this claim.');
|
||||
}
|
||||
|
||||
@@ -649,7 +649,7 @@ Optional: upload car green card file in the same step.
|
||||
|
||||
Returns status of each item (uploaded/captured or not).
|
||||
|
||||
**V2 order:** During \`CAPTURE_PART_DAMAGES\`, complete angles, part photos, walk-around video, and the three \`preferUploadDuringCapture\` documents (same upload-document API). Then complete the remaining documents in \`UPLOAD_REQUIRED_DOCUMENTS\`.
|
||||
**V2 order (enforced by API):** During \`CAPTURE_PART_DAMAGES\`, (1) all damaged-part photos, (2) four car angles, (3) chassis/engine/metal-plate via upload-document, then walk-around video. Remaining documents in \`UPLOAD_REQUIRED_DOCUMENTS\`. Use \`captureSequencePhase\` / \`captureSequenceHint\` in the response.
|
||||
`,
|
||||
})
|
||||
@ApiParam({
|
||||
@@ -828,7 +828,7 @@ Returns status of each item (uploaded/captured or not).
|
||||
1. **angle**: Car angles (front, back, left, right) - 4 required
|
||||
2. **part**: Damaged parts based on selectedParts from Step 2
|
||||
|
||||
**When all captures are complete:** Workflow moves to UPLOAD_REQUIRED_DOCUMENTS (Step 5).
|
||||
**When all captures are complete (parts, angles, capture-phase docs):** Workflow moves to UPLOAD_REQUIRED_DOCUMENTS (Step 5). Angles are blocked until all parts are captured; capture-phase documents are blocked until all angles are captured.
|
||||
|
||||
**Field expert IN_PERSON:** Same endpoint; use with claim created from expert-initiated IN_PERSON blame to capture photos on behalf of the damaged party.
|
||||
`,
|
||||
|
||||
@@ -144,6 +144,20 @@ export class GetCaptureRequirementsV2ResponseDto {
|
||||
})
|
||||
currentStep: string;
|
||||
|
||||
@ApiProperty({
|
||||
description:
|
||||
'Ordered capture phase during CAPTURE_PART_DAMAGES: parts → angles → capture_phase_documents',
|
||||
example: 'angles',
|
||||
enum: ['parts', 'angles', 'capture_phase_documents', 'complete'],
|
||||
})
|
||||
captureSequencePhase: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Human-readable hint for what the user should do next in the capture step',
|
||||
example: 'Capture all four car angles (front, back, left, right) next.',
|
||||
})
|
||||
captureSequenceHint: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'List of required documents to upload',
|
||||
type: [RequiredDocumentItem],
|
||||
@@ -186,5 +200,7 @@ export class GetCaptureRequirementsV2ResponseDto {
|
||||
anglesTotal: number;
|
||||
partsCaptured: number;
|
||||
partsTotal: number;
|
||||
capturePhaseDocsRemaining: number;
|
||||
postCaptureDocumentsRemaining: number;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user