From e2b879d943460893df8bf9eee979773194550e1b Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Tue, 23 Jun 2026 11:03:06 +0330 Subject: [PATCH] Fixed workflow step --- .../claim-request-management.service.ts | 173 +++++++++++++++++- src/helpers/claim-capture-phase.ts | 7 +- ...rt-initiated-blame-v3.mirror.controller.ts | 15 +- 3 files changed, 188 insertions(+), 7 deletions(-) diff --git a/src/claim-request-management/claim-request-management.service.ts b/src/claim-request-management/claim-request-management.service.ts index c22a9c1..902716e 100644 --- a/src/claim-request-management/claim-request-management.service.ts +++ b/src/claim-request-management/claim-request-management.service.ts @@ -6091,8 +6091,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.`, ); } } @@ -8011,6 +8019,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, @@ -8023,7 +8134,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, @@ -8045,8 +8197,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( diff --git a/src/helpers/claim-capture-phase.ts b/src/helpers/claim-capture-phase.ts index a3bffe7..1c458f8 100644 --- a/src/helpers/claim-capture-phase.ts +++ b/src/helpers/claim-capture-phase.ts @@ -72,7 +72,12 @@ export function getClaimCaptureProgress( }).length; const partsTotal = selectedNorm.length; - const partsComplete = partsTotal === 0 || partsCaptured >= partsTotal; + const completedSteps: string[] = claimCase?.workflow?.completedSteps ?? []; + const outerPartsStepDone = completedSteps.includes("SELECT_OUTER_PARTS"); + const partsComplete = + partsTotal > 0 + ? partsCaptured >= partsTotal + : outerPartsStepDone; const anglesTotal = CLAIM_CAR_ANGLE_KEYS.length; const anglesComplete = anglesCaptured >= anglesTotal; diff --git a/src/request-management/expert-initiated-blame-v3.mirror.controller.ts b/src/request-management/expert-initiated-blame-v3.mirror.controller.ts index e0b1cc4..0b9391c 100644 --- a/src/request-management/expert-initiated-blame-v3.mirror.controller.ts +++ b/src/request-management/expert-initiated-blame-v3.mirror.controller.ts @@ -325,7 +325,13 @@ export class ExpertInitiatedBlameV3MirrorController { @Get("capture-requirements/:claimRequestId") @ApiParam({ name: "claimRequestId" }) - @ApiOperation({ summary: "List required claim documents" }) + @ApiOperation({ + summary: "Capture requirements (step-aware for V3)", + description: + "Initial documents phase: only pre-capture docs (no chassis/engine/metal plate). " + + "CAPTURE_PART_DAMAGES: damaged parts + angles via capture-part, then chassis/engine/metal plate via upload-document. " + + "Use `captureSequencePhase` and `captureSequenceHint` to drive the UI.", + }) async getCaptureRequirements( @Param("claimRequestId") claimRequestId: string, @CurrentUser() expert: any, @@ -353,7 +359,12 @@ export class ExpertInitiatedBlameV3MirrorController { }), }), ) - @ApiOperation({ summary: "Upload one required claim document" }) + @ApiOperation({ + summary: "Upload one required claim document", + description: + "Initial phase (UPLOAD_REQUIRED_DOCUMENTS): licenses and car cards only. " + + "Capture phase (CAPTURE_PART_DAMAGES, after parts + angles): chassis, engine, metal plate only.", + }) async uploadDocument( @Param("claimRequestId") claimRequestId: string, @Body() body: UploadRequiredDocumentV2Dto,