Compare commits

...

3 Commits

Author SHA1 Message Date
7d10c00ce5 merge upstream 2026-06-23 13:17:44 +03:30
f00cb226a7 Merge pull request 'Fixed workflow step' (#149) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#149
2026-06-23 11:04:03 +03:30
SepehrYahyaee
e2b879d943 Fixed workflow step 2026-06-23 11:03:06 +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(

View File

@@ -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;

View File

@@ -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,