forked from Yara724/api
Fixed Bugs: 1) V4 incorrect advancement to file maker approval state, 2) V4 race condition for finishing file maker steps
This commit is contained in:
@@ -8643,31 +8643,10 @@ export class ClaimRequestManagementService {
|
||||
|
||||
if (allDocumentsUploaded) {
|
||||
if (options?.v3InPersonFlow) {
|
||||
// V4 split flow: mark the claim as waiting for the FileReviewer.
|
||||
// The FileReviewer calls accident-fields then select-outer-parts, at
|
||||
// which point advanceV3ClaimToOuterPartsIfReady() moves the claim to
|
||||
// SELECTING_OUTER_PARTS / SELECT_OUTER_PARTS.
|
||||
$set["status"] = ClaimCaseStatus.WAITING_FOR_FILE_REVIEWER;
|
||||
$set["workflow.nextStep"] = ClaimWorkflowStep.SELECT_OUTER_PARTS;
|
||||
|
||||
completedStepsEntries.push(
|
||||
ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
|
||||
);
|
||||
historyEntries.push({
|
||||
type: "STEP_COMPLETED",
|
||||
actor: {
|
||||
actorId: new Types.ObjectId(currentUserId),
|
||||
actorName: claimCase.owner?.fullName || "User",
|
||||
actorType: "user",
|
||||
},
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
stepKey: ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
|
||||
description:
|
||||
"FileMaker documents complete. File sealed — awaiting FileReviewer.",
|
||||
v3InPersonFlow: true,
|
||||
},
|
||||
});
|
||||
// V4/V5 split flow: the status transition to WAITING_FOR_FILE_REVIEWER is
|
||||
// deferred to a post-write re-check (see below) to eliminate the race
|
||||
// condition where two concurrent uploads each see a stale snapshot and
|
||||
// neither fires the transition. We skip adding it to $set here.
|
||||
} else {
|
||||
$set["status"] = ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT;
|
||||
$set["claimStatus"] = ClaimStatus.PENDING;
|
||||
@@ -8734,6 +8713,77 @@ export class ClaimRequestManagementService {
|
||||
updatePayload,
|
||||
);
|
||||
|
||||
// ─── V4/V5 in-person flow: post-write race-safe status transition ──────
|
||||
// After the write we re-read the actual DB state. If all pre-capture
|
||||
// documents are now present but the status has not yet advanced (i.e. a
|
||||
// concurrent request uploaded the last doc a split-second before us and
|
||||
// the stale snapshot we read earlier missed it — or vice-versa), we apply
|
||||
// WAITING_FOR_FILE_REVIEWER atomically using findOneAndUpdate with a status
|
||||
// condition, so exactly one writer wins regardless of concurrency.
|
||||
if (options?.v3InPersonFlow && !isResendUpload && !isCapturePhaseDocUpload) {
|
||||
const afterWrite = await this.claimCaseDbService.findById(claimRequestId);
|
||||
if (afterWrite) {
|
||||
const blameForRecheck = afterWrite.blameRequestId
|
||||
? await this.blameRequestDbService.findById(
|
||||
afterWrite.blameRequestId.toString(),
|
||||
)
|
||||
: null;
|
||||
const isCarBodyRecheck = blameForRecheck?.type === BlameRequestType.CAR_BODY;
|
||||
const allDoneNow =
|
||||
afterWrite.status === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS &&
|
||||
afterWrite.workflow?.currentStep === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS &&
|
||||
this.allV3PreCaptureDocumentsComplete(afterWrite, isCarBodyRecheck);
|
||||
|
||||
if (allDoneNow) {
|
||||
// Atomic conditional update: only succeeds when status is still
|
||||
// UPLOADING_REQUIRED_DOCUMENTS, preventing double-application.
|
||||
const advanced = await this.claimCaseDbService.findOneAndUpdate(
|
||||
{
|
||||
_id: afterWrite._id,
|
||||
status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
status: ClaimCaseStatus.WAITING_FOR_FILE_REVIEWER,
|
||||
"workflow.nextStep": ClaimWorkflowStep.SELECT_OUTER_PARTS,
|
||||
},
|
||||
$push: {
|
||||
"workflow.completedSteps": ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
|
||||
history: {
|
||||
type: "STEP_COMPLETED",
|
||||
actor: {
|
||||
actorId: new Types.ObjectId(currentUserId),
|
||||
actorName: afterWrite.owner?.fullName || "User",
|
||||
actorType: "user",
|
||||
},
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
stepKey: ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
|
||||
description:
|
||||
"FileMaker documents complete. File sealed — awaiting FileReviewer.",
|
||||
v3InPersonFlow: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
if (advanced) {
|
||||
// This request won the race — reflect the final state in the response.
|
||||
allDocumentsUploaded = true;
|
||||
}
|
||||
} else if (
|
||||
afterWrite.status === ClaimCaseStatus.WAITING_FOR_FILE_REVIEWER ||
|
||||
(afterWrite.workflow?.completedSteps ?? []).includes(
|
||||
ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
|
||||
)
|
||||
) {
|
||||
// Another concurrent request already advanced the status — treat
|
||||
// this upload as the completing upload for response purposes.
|
||||
allDocumentsUploaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-submit Fanavaran attachments when all documents are uploaded
|
||||
if (allDocumentsUploaded && !isResendUpload && !options?.v3InPersonFlow) {
|
||||
this.submitFanavaranAttachmentsV2(claimRequestId, resolveFanavaranClientKey()).catch(
|
||||
|
||||
@@ -87,7 +87,9 @@ export class FileMakerBlameV4Controller {
|
||||
) {
|
||||
return this.requestManagementService.createExpertInitiatedBlameV2(
|
||||
fileMaker,
|
||||
{ ...dto, creationMethod: CreationMethod.IN_PERSON },
|
||||
// requiresFileMakerApproval is V5-only; explicitly exclude it from V4 so
|
||||
// a client that accidentally sends the field cannot poison the blame record.
|
||||
{ ...dto, creationMethod: CreationMethod.IN_PERSON, requiresFileMakerApproval: false },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user