merge upstream

This commit is contained in:
2026-06-23 13:17:44 +03:30
3 changed files with 188 additions and 7 deletions

View File

@@ -6124,8 +6124,16 @@ export class ClaimRequestManagementService {
step === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS &&
isCapturePhaseDamagedPartyDocKey(body.documentKey)
) {
const capturePartDone = (
claimCase.workflow?.completedSteps ?? []
).includes(ClaimWorkflowStep.CAPTURE_PART_DAMAGES);
if (!capturePartDone) {
throw new BadRequestException(
`Complete outer/other part selection and capture-part (damaged parts + car angles) before uploading chassis, engine, and metal plate photos (${CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.join(", ")}).`,
);
}
throw new BadRequestException(
`Chassis, engine, and metal plate photos must be uploaded during capture (after parts and angles), not in the initial documents step (${CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.join(", ")}).`,
`Chassis, engine, and metal plate photos must be uploaded during ${ClaimWorkflowStep.CAPTURE_PART_DAMAGES} after parts and angles are captured.`,
);
}
}
@@ -8044,6 +8052,109 @@ export class ClaimRequestManagementService {
return blame;
}
private isV3InitialDocumentsPhase(claimCase: any): boolean {
const step = claimCase.workflow?.currentStep;
const capturePartDone = this.claimV3StepCompleted(
claimCase,
ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
);
return (
step === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS && !capturePartDone
);
}
private shapeCaptureRequirementsForV3(
claimCase: any,
_blame: any,
base: GetCaptureRequirementsV2ResponseDto,
): GetCaptureRequirementsV2ResponseDto {
const step = claimCase.workflow?.currentStep;
const capturePartDone = this.claimV3StepCompleted(
claimCase,
ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
);
if (this.isV3InitialDocumentsPhase(claimCase)) {
const preCaptureDocs = base.requiredDocuments.filter(
(d) =>
!d.preferUploadDuringCapture &&
d.key !== ClaimRequiredDocumentType.CAR_GREEN_CARD,
);
const remaining = preCaptureDocs.filter((d) => !d.uploaded).length;
return {
...base,
requiredDocuments: preCaptureDocs,
captureSequencePhase: "parts",
captureSequenceHint:
"Upload initial required documents (licenses and car cards). Chassis, engine, and metal plate photos come after part selection, damaged-part photos, and car angles.",
damagedParts: [],
carAngles: base.carAngles.map((a) => ({ ...a, captured: false })),
totalRemaining: remaining,
progress: {
...base.progress,
documentsTotal: preCaptureDocs.length,
documentsUploaded: preCaptureDocs.filter((d) => d.uploaded).length,
partsCaptured: 0,
partsTotal: 0,
anglesCaptured: 0,
capturePhaseDocsRemaining: 0,
postCaptureDocumentsRemaining: remaining,
},
};
}
if (step === ClaimWorkflowStep.SELECT_OUTER_PARTS) {
return {
...base,
requiredDocuments: base.requiredDocuments.filter(
(d) => !d.preferUploadDuringCapture,
),
captureSequencePhase: "parts",
captureSequenceHint: "Select outer damaged parts before capture.",
totalRemaining: base.damagedParts.filter((p) => !p.captured).length,
};
}
if (step === ClaimWorkflowStep.SELECT_OTHER_PARTS) {
return {
...base,
requiredDocuments: base.requiredDocuments.filter(
(d) => !d.preferUploadDuringCapture,
),
captureSequencePhase: "parts",
captureSequenceHint:
"Select other damaged parts (and car green card when required) before capture.",
};
}
if (step === ClaimWorkflowStep.CAPTURE_PART_DAMAGES) {
const capturePhaseDocs = base.requiredDocuments.filter(
(d) => d.preferUploadDuringCapture,
);
return {
...base,
requiredDocuments: capturePhaseDocs,
totalRemaining: base.progress.capturePhaseDocsRemaining,
};
}
if (
step === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS &&
capturePartDone
) {
return {
...base,
requiredDocuments: [],
captureSequencePhase: "complete",
captureSequenceHint:
"Upload the walk-around car video (car-capture), then the blame accident video.",
totalRemaining: claimCase.media?.videoCaptureId ? 0 : 1,
};
}
return base;
}
async uploadRequiredDocumentV3(
claimRequestId: string,
body: UploadRequiredDocumentV2Dto,
@@ -8056,7 +8167,48 @@ export class ClaimRequestManagementService {
throw new NotFoundException(`Claim case with ID ${claimRequestId} not found`);
}
const blame = await this.assertV3InPersonClaim(claimCase);
this.assertV3ClaimDocumentsPhase(blame);
if (body.documentKey === ClaimRequiredDocumentType.CAR_GREEN_CARD) {
throw new BadRequestException(
"Car green card must be uploaded during other-parts selection, not here.",
);
}
const isCaptureDoc = isCapturePhaseDamagedPartyDocKey(body.documentKey);
if (isCaptureDoc) {
this.assertV3ClaimPartsPhase(blame);
this.assertV3ClaimWorkflowStep(
claimCase,
ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
"Upload chassis, engine, and metal plate photos during capture after damaged-part photos and car angles.",
);
if (
!this.claimV3StepCompleted(claimCase, ClaimWorkflowStep.SELECT_OTHER_PARTS)
) {
throw new BadRequestException(
"Complete outer and other part selection before capture-phase vehicle documents.",
);
}
const captureProgress = getClaimCaptureProgress(claimCase);
if (!captureProgress.partsComplete) {
throw new BadRequestException(
"Upload photos for all selected damaged parts before chassis, engine, or metal plate photos.",
);
}
if (!captureProgress.anglesComplete) {
throw new BadRequestException(
"Capture all four car angles before chassis, engine, or metal plate photos.",
);
}
} else {
this.assertV3ClaimDocumentsPhase(blame);
if (!this.isV3InitialDocumentsPhase(claimCase)) {
throw new BadRequestException(
`Upload initial required documents during ${ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS} before part selection. Current step: ${claimCase.workflow?.currentStep}`,
);
}
}
return this.uploadRequiredDocumentV2(
claimRequestId,
@@ -8078,8 +8230,21 @@ export class ClaimRequestManagementService {
throw new NotFoundException(`Claim case with ID ${claimRequestId} not found`);
}
const blame = await this.assertV3InPersonClaim(claimCase);
this.assertV3ClaimDocumentsPhase(blame);
return this.getCaptureRequirementsV2(claimRequestId, currentUserId, actor);
if (this.isV3InitialDocumentsPhase(claimCase)) {
this.assertV3ClaimDocumentsPhase(blame);
} else if (
claimCase.workflow?.currentStep === ClaimWorkflowStep.CAPTURE_PART_DAMAGES
) {
this.assertV3ClaimPartsPhase(blame);
}
const base = await this.getCaptureRequirementsV2(
claimRequestId,
currentUserId,
actor,
);
return this.shapeCaptureRequirementsForV3(claimCase, blame, base);
}
async selectOuterPartsV3(