forked from Yara724/api
Compare commits
20 Commits
4d5b91d4fe
...
49fe548215
| Author | SHA1 | Date | |
|---|---|---|---|
| 49fe548215 | |||
|
|
777eae1028 | ||
| b67dd733cd | |||
|
|
4818f73252 | ||
| cc8a5354c7 | |||
|
|
2d5ade33d2 | ||
| b73c92c21f | |||
| f9f462d47b | |||
| c3eb36dc41 | |||
|
|
f75ecf5c2c | ||
| 75c4cb6a05 | |||
|
|
7a4277f8b2 | ||
| e50bc78344 | |||
|
|
2c1cd93dd0 | ||
| ffd44df718 | |||
|
|
64865b70f2 | ||
| c207c30be9 | |||
|
|
fcb169e9ac | ||
| 1867292499 | |||
|
|
2cc96f6132 |
@@ -419,8 +419,10 @@ export class ClaimRequestManagementService {
|
||||
claimCase: any,
|
||||
isCarBody: boolean,
|
||||
assumeUploadedKey?: string,
|
||||
skipMetalPlate?: boolean,
|
||||
): boolean {
|
||||
for (const k of this.v3PreCaptureDocumentKeys(isCarBody)) {
|
||||
if (skipMetalPlate && OPTIONAL_CAPTURE_PHASE_DOC_KEYS_V4V5.includes(k as any)) continue;
|
||||
const ok =
|
||||
k === assumeUploadedKey
|
||||
? true
|
||||
@@ -442,9 +444,11 @@ export class ClaimRequestManagementService {
|
||||
claimCase: any,
|
||||
isCarBody: boolean,
|
||||
assumeUploadedKey?: string,
|
||||
skipMetalPlate?: boolean,
|
||||
): number {
|
||||
let n = 0;
|
||||
for (const k of this.v3PreCaptureDocumentKeys(isCarBody)) {
|
||||
if (skipMetalPlate && OPTIONAL_CAPTURE_PHASE_DOC_KEYS_V4V5.includes(k as any)) continue;
|
||||
const ok =
|
||||
k === assumeUploadedKey
|
||||
? true
|
||||
@@ -6331,8 +6335,17 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
|
||||
// V5 flow: FileMaker approval required before fanavaran.
|
||||
// Instead of submitting, hold the claim at WAITING_FOR_FILE_MAKER_APPROVAL.
|
||||
// Cross-check the blame record — only V5 blame files carry requiresFileMakerApproval.
|
||||
// V4 claims may have the flag set from an old bug; we ignore it if the blame
|
||||
// itself does not carry the flag.
|
||||
if ((claimCase as any).requiresFileMakerApproval) {
|
||||
const blameId = (claimCase as any).blameRequestId;
|
||||
const blame = blameId
|
||||
? await this.blameRequestDbService.findById(String(blameId))
|
||||
: null;
|
||||
const isV5 = !!(blame as any)?.requiresFileMakerApproval;
|
||||
|
||||
if (isV5) {
|
||||
await this.claimCaseDbService.findByIdAndUpdate(claimCaseId, {
|
||||
$set: { status: ClaimCaseStatus.WAITING_FOR_FILE_MAKER_APPROVAL },
|
||||
$push: {
|
||||
@@ -6353,6 +6366,11 @@ export class ClaimRequestManagementService {
|
||||
"Claim is now in WAITING_FOR_FILE_MAKER_APPROVAL.",
|
||||
};
|
||||
}
|
||||
// V4 claim with stale flag — clear it so this path is not hit again.
|
||||
await this.claimCaseDbService.findByIdAndUpdate(claimCaseId, {
|
||||
$unset: { requiresFileMakerApproval: "" },
|
||||
});
|
||||
}
|
||||
|
||||
const skipReason = await this.getFanavaranAutoSubmitSkipReason(claimCase);
|
||||
if (skipReason) {
|
||||
@@ -8606,6 +8624,7 @@ export class ClaimRequestManagementService {
|
||||
claimCase,
|
||||
isCarBodyUpload,
|
||||
body.documentKey,
|
||||
options?.skipMetalPlate,
|
||||
);
|
||||
|
||||
allDocumentsUploaded = options?.v3InPersonFlow
|
||||
@@ -8620,6 +8639,7 @@ export class ClaimRequestManagementService {
|
||||
claimCase,
|
||||
isCarBodyUpload,
|
||||
body.documentKey,
|
||||
options?.skipMetalPlate,
|
||||
)
|
||||
: this.countRemainingV2OwnerDocuments(
|
||||
claimCase,
|
||||
@@ -8629,31 +8649,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;
|
||||
@@ -8720,6 +8719,88 @@ 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 skipMetalPlateRecheck = !!(blameForRecheck as any)?.isMadeByFileMaker;
|
||||
const allDoneNow =
|
||||
afterWrite.status === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS &&
|
||||
afterWrite.workflow?.currentStep === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS &&
|
||||
this.allV3PreCaptureDocumentsComplete(afterWrite, isCarBodyRecheck, undefined, skipMetalPlateRecheck);
|
||||
|
||||
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;
|
||||
// Now that the FileMaker's document phase is complete, promote the
|
||||
// blame file to WAITING_FOR_FILE_REVIEWER so the frontend shows the
|
||||
// correct sealed state when the FileMaker returns.
|
||||
const blameId = (afterWrite as any).blameRequestId;
|
||||
if (blameId) {
|
||||
await this.blameRequestDbService.findByIdAndUpdate(
|
||||
String(blameId),
|
||||
{ $set: { status: BlameCaseStatus.WAITING_FOR_FILE_REVIEWER } },
|
||||
);
|
||||
}
|
||||
}
|
||||
} 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(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsEnum, IsOptional, IsString } from "class-validator";
|
||||
import { IsBoolean, IsEnum, IsOptional } from "class-validator";
|
||||
import { CreationMethod } from "../entities/schema/request-management.schema";
|
||||
|
||||
export class CreateExpertInitiatedFileDto {
|
||||
@@ -18,4 +18,17 @@ export class CreateExpertInitiatedFileDto {
|
||||
})
|
||||
@IsEnum(CreationMethod)
|
||||
creationMethod: CreationMethod;
|
||||
|
||||
/**
|
||||
* V5 only. When true the resulting claim will require FileMaker approval
|
||||
* before fanavaran submission. V4 files must leave this unset (or false).
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"V5 only — when true the claim requires FileMaker approval before fanavaran submission.",
|
||||
example: false,
|
||||
})
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
requiresFileMakerApproval?: boolean;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,14 @@ export class BlameRequest {
|
||||
@Prop({ default: false })
|
||||
isMadeByFileMaker?: boolean;
|
||||
|
||||
/**
|
||||
* V5 only. When true the resulting claim requires FileMaker approval before
|
||||
* fanavaran submission. V4 files never set this; it is written at creation
|
||||
* time by the V5 controller and propagated to the linked claim.
|
||||
*/
|
||||
@Prop({ default: false })
|
||||
requiresFileMakerApproval?: boolean;
|
||||
|
||||
/**
|
||||
* The FileReviewer who claimed this file for completion (V4 flow only).
|
||||
* Set when a FileReviewer calls assign on this file; enforces one-reviewer-per-file.
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
LocationDto,
|
||||
} from "./dto/create-request-management.dto";
|
||||
import { CreateExpertInitiatedFileDto } from "./dto/expert-initiated.dto";
|
||||
import { CreationMethod } from "./entities/schema/request-management.schema";
|
||||
import { SendPartyOtpsDto } from "./dto/send-party-otps.dto";
|
||||
import { VerifyPartyOtpsDto } from "./dto/verify-party-otps.dto";
|
||||
import { SendPartyOtpDto, VerifyPartyOtpDto } from "./dto/party-otp.dto";
|
||||
@@ -75,17 +76,17 @@ export class ExpertInitiatedBlameMirrorController {
|
||||
@ApiOperation({
|
||||
summary: "[Expert mirror] Create expert-initiated blame file",
|
||||
description:
|
||||
"Use creationMethod=IN_PERSON for the on-site flow. Creates a BlameRequest owned by the parties but filled by the expert.",
|
||||
"Creates an IN_PERSON blame file filled by the expert on behalf of both parties. creationMethod is always forced to IN_PERSON regardless of what is sent.",
|
||||
})
|
||||
@ApiBody({ type: CreateExpertInitiatedFileDto })
|
||||
async create(
|
||||
@CurrentUser() expert: any,
|
||||
@Body() dto: CreateExpertInitiatedFileDto,
|
||||
) {
|
||||
return this.requestManagementService.createExpertInitiatedBlameV2(
|
||||
expert,
|
||||
dto,
|
||||
);
|
||||
return this.requestManagementService.createExpertInitiatedBlameV2(expert, {
|
||||
...dto,
|
||||
creationMethod: CreationMethod.IN_PERSON,
|
||||
});
|
||||
}
|
||||
|
||||
@Post("send-link/:requestId")
|
||||
|
||||
@@ -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 },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ export class FileMakerBlameV5Controller {
|
||||
) {
|
||||
return this.requestManagementService.createExpertInitiatedBlameV2(
|
||||
fileMaker,
|
||||
{ ...dto, creationMethod: CreationMethod.IN_PERSON },
|
||||
{ ...dto, creationMethod: CreationMethod.IN_PERSON, requiresFileMakerApproval: true },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,32 @@ export class RequestManagementService {
|
||||
return;
|
||||
}
|
||||
|
||||
// IN_PERSON THIRD_PARTY (expert/registrar-initiated): after first-party description
|
||||
// the expert collects the first party's signature before moving to the second party.
|
||||
// Skip FIRST_INVITE_SECOND and hold at WAITING_FOR_SIGNATURES so the sign endpoint
|
||||
// can be called for the first party. The workflow advances to FIRST_INVITE_SECOND
|
||||
// only after expertUploadPartySignatureV2/V3 records the first-party confirmation.
|
||||
if (
|
||||
req.type === BlameRequestType.THIRD_PARTY &&
|
||||
req.creationMethod === CreationMethod.IN_PERSON &&
|
||||
(req.expertInitiated || req.registrarInitiated) &&
|
||||
submittedStepKey === WorkflowStep.FIRST_DESCRIPTION
|
||||
) {
|
||||
const completed = Array.isArray(req.workflow.completedSteps)
|
||||
? req.workflow.completedSteps
|
||||
: [];
|
||||
if (!completed.includes(submittedStepKey))
|
||||
completed.push(submittedStepKey);
|
||||
req.workflow.completedSteps = completed;
|
||||
req.workflow.currentStep = WorkflowStep.WAITING_FOR_SIGNATURES;
|
||||
req.workflow.nextStep = undefined;
|
||||
req.status = CaseStatus.WAITING_FOR_SIGNATURES;
|
||||
this.logger.debug(
|
||||
"[WORKFLOW] IN_PERSON THIRD_PARTY: advanced to WAITING_FOR_SIGNATURES after FIRST_DESCRIPTION (first-party sign before second-party invite)",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// IN_PERSON THIRD_PARTY: guilt is decided on-site by the expert — there is
|
||||
// no waiting-for-field-expert phase. Replace WAITING_FOR_GUILT_DECISION
|
||||
// with WAITING_FOR_SIGNATURES wherever it would surface as current/next step.
|
||||
@@ -2087,13 +2113,9 @@ export class RequestManagementService {
|
||||
? req.workflow.completedSteps
|
||||
: [];
|
||||
if (!completed.includes(stepKey)) completed.push(stepKey);
|
||||
// Same as post–field-expert reply: guilt phase is satisfied without an expert; parties must still sign.
|
||||
if (!completed.includes(WorkflowStep.WAITING_FOR_GUILT_DECISION)) {
|
||||
completed.push(WorkflowStep.WAITING_FOR_GUILT_DECISION);
|
||||
}
|
||||
req.workflow.completedSteps = completed;
|
||||
req.workflow.currentStep = WorkflowStep.WAITING_FOR_SIGNATURES;
|
||||
req.workflow.nextStep = undefined;
|
||||
req.workflow.nextStep = WorkflowStep.WAITING_FOR_SIGNATURES;
|
||||
req.status = CaseStatus.WAITING_FOR_SIGNATURES;
|
||||
closedByMutualAgreement = true;
|
||||
|
||||
@@ -2174,12 +2196,9 @@ export class RequestManagementService {
|
||||
? req.workflow.completedSteps
|
||||
: [];
|
||||
if (!completed.includes(stepKey)) completed.push(stepKey);
|
||||
if (!completed.includes(WorkflowStep.WAITING_FOR_GUILT_DECISION)) {
|
||||
completed.push(WorkflowStep.WAITING_FOR_GUILT_DECISION);
|
||||
}
|
||||
req.workflow.completedSteps = completed;
|
||||
req.workflow.currentStep = WorkflowStep.WAITING_FOR_SIGNATURES;
|
||||
req.workflow.nextStep = undefined;
|
||||
req.workflow.nextStep = WorkflowStep.WAITING_FOR_SIGNATURES;
|
||||
req.status = CaseStatus.WAITING_FOR_SIGNATURES;
|
||||
} else if (!closedByMutualAgreement) {
|
||||
if (stepKey === WorkflowStep.SECOND_DESCRIPTION) {
|
||||
@@ -4816,6 +4835,9 @@ export class RequestManagementService {
|
||||
? FilledBy.EXPERT
|
||||
: FilledBy.CUSTOMER,
|
||||
...(isFileMakerRole ? { isMadeByFileMaker: true } : {}),
|
||||
// V5 only: flag that causes the resulting claim to require FileMaker
|
||||
// approval before fanavaran submission. V4 files never set this.
|
||||
...(dto.requiresFileMakerApproval ? { requiresFileMakerApproval: true } : {}),
|
||||
});
|
||||
|
||||
const requestId = String((created as any)._id);
|
||||
@@ -6637,11 +6659,11 @@ export class RequestManagementService {
|
||||
);
|
||||
}
|
||||
await this.verifyExpertAccessForBlameV2(req, expert);
|
||||
// if (req.status !== CaseStatus.WAITING_FOR_SIGNATURES) {
|
||||
// throw new BadRequestException(
|
||||
// "Request is not waiting for signatures. Current status: " + req.status,
|
||||
// );
|
||||
// }
|
||||
if (req.status !== CaseStatus.WAITING_FOR_SIGNATURES) {
|
||||
throw new BadRequestException(
|
||||
"Request is not waiting for signatures. Current status: " + req.status,
|
||||
);
|
||||
}
|
||||
const partyIndex = this.getPartyIndex(req, partyRole);
|
||||
if (partyIndex === -1) {
|
||||
throw new BadRequestException(
|
||||
@@ -6728,6 +6750,23 @@ export class RequestManagementService {
|
||||
},
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
// THIRD_PARTY IN_PERSON: first party just signed — advance workflow to
|
||||
// FIRST_INVITE_SECOND so the frontend knows to proceed to the second-party
|
||||
// registration step. Status stays WAITING_FOR_SIGNATURES.
|
||||
req.type === BlameRequestType.THIRD_PARTY &&
|
||||
req.creationMethod === CreationMethod.IN_PERSON &&
|
||||
(req.expertInitiated || req.registrarInitiated) &&
|
||||
partyRole === PartyRole.FIRST
|
||||
) {
|
||||
await this.blameRequestDbService.findByIdAndUpdate(requestId, {
|
||||
$set: {
|
||||
"workflow.currentStep": WorkflowStep.FIRST_INVITE_SECOND as any,
|
||||
"workflow.nextStep": WorkflowStep.SECOND_INITIAL_FORM as any,
|
||||
},
|
||||
});
|
||||
message =
|
||||
"First party signature recorded. Proceed to register the second party.";
|
||||
}
|
||||
return {
|
||||
requestId: String(req._id),
|
||||
@@ -6753,6 +6792,18 @@ export class RequestManagementService {
|
||||
);
|
||||
}
|
||||
await this.verifyExpertAccessForBlameV2(req, expert);
|
||||
// In the V2 IN_PERSON mirror flow guilt is resolved automatically after both
|
||||
// parties complete their narrative steps (addDescriptionV2). The sign step for
|
||||
// both parties must happen BEFORE accident-fields is called — calling it earlier
|
||||
// would overwrite the workflow and cause the frontend to skip the sign page.
|
||||
if (
|
||||
req.creationMethod === CreationMethod.IN_PERSON &&
|
||||
req.status !== CaseStatus.COMPLETED
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`accident-fields can only be submitted after both parties have signed (current status: ${req.status}). Complete both signatures first.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!req.expert) req.expert = {} as any;
|
||||
if (!req.expert.decision) req.expert.decision = {} as any;
|
||||
@@ -6781,29 +6832,24 @@ export class RequestManagementService {
|
||||
},
|
||||
};
|
||||
|
||||
// For IN_PERSON expert files: after accident fields are filled, guilt is
|
||||
// decided and we can go straight to signatures (no separate review needed).
|
||||
// IN_PERSON V2 mirror: accident-fields is a post-sign supplemental step called
|
||||
// only after COMPLETED (both parties have signed). Record WAITING_FOR_GUILT_DECISION
|
||||
// in completedSteps here — it was intentionally omitted from description so the
|
||||
// frontend does not route to this page before signatures are collected.
|
||||
if (req.creationMethod === CreationMethod.IN_PERSON) {
|
||||
const completed = Array.isArray(req.workflow?.completedSteps)
|
||||
? req.workflow.completedSteps
|
||||
: [];
|
||||
const currentStep = req.workflow?.currentStep as WorkflowStep | undefined;
|
||||
if (currentStep && !completed.includes(currentStep)) {
|
||||
completed.push(currentStep);
|
||||
}
|
||||
if (!completed.includes(WorkflowStep.WAITING_FOR_GUILT_DECISION)) {
|
||||
completed.push(WorkflowStep.WAITING_FOR_GUILT_DECISION);
|
||||
}
|
||||
if (req.workflow) {
|
||||
req.workflow.completedSteps = completed;
|
||||
req.workflow.currentStep = WorkflowStep.WAITING_FOR_SIGNATURES;
|
||||
req.workflow.nextStep = undefined;
|
||||
}
|
||||
req.status = CaseStatus.WAITING_FOR_SIGNATURES;
|
||||
|
||||
if (!Array.isArray(req.history)) req.history = [];
|
||||
req.history.push({
|
||||
type: "ACCIDENT_FIELDS_SAVED_ADVANCED_TO_SIGNATURES",
|
||||
type: "ACCIDENT_FIELDS_SAVED",
|
||||
actor: {
|
||||
actorId: new Types.ObjectId(String(expert.sub)),
|
||||
actorName:
|
||||
@@ -6812,7 +6858,6 @@ export class RequestManagementService {
|
||||
},
|
||||
metadata: {
|
||||
accidentWay: fields.accidentWay,
|
||||
advancedTo: WorkflowStep.WAITING_FOR_SIGNATURES,
|
||||
},
|
||||
} as any);
|
||||
}
|
||||
@@ -8834,9 +8879,10 @@ export class RequestManagementService {
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
// V5 (isMadeByFileMaker): mark approval gate at claim creation so the flag
|
||||
// is always present regardless of whether upload-video is called.
|
||||
...((req as any).isMadeByFileMaker
|
||||
// V5 only: propagate the approval gate from the blame record to the claim.
|
||||
// isMadeByFileMaker is true for both V4 and V5; only V5 blame records also
|
||||
// carry requiresFileMakerApproval=true (set at create time by the V5 controller).
|
||||
...((req as any).requiresFileMakerApproval
|
||||
? {
|
||||
requiresFileMakerApproval: true,
|
||||
fileMakerApprovalActorId: new Types.ObjectId(actor.sub),
|
||||
@@ -9242,12 +9288,11 @@ export class RequestManagementService {
|
||||
fresh.workflow.currentStep = WorkflowStep.FIRST_INVITE_SECOND;
|
||||
fresh.workflow.nextStep = WorkflowStep.SECOND_INITIAL_FORM;
|
||||
} else {
|
||||
// CAR_BODY: FileMaker is done — seal the file for FileReviewer pickup
|
||||
// CAR_BODY: FileMaker's narrative is done — move to document-upload step.
|
||||
// blame.status transitions to WAITING_FOR_FILE_REVIEWER only after the
|
||||
// FileMaker completes all document uploads, not here at sign time.
|
||||
fresh.workflow.currentStep = WorkflowStep.FIRST_COMPLETED;
|
||||
fresh.workflow.nextStep = WorkflowStep.WAITING_FOR_GUILT_DECISION;
|
||||
if (isFileMakerActor) {
|
||||
fresh.status = CaseStatus.WAITING_FOR_FILE_REVIEWER;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.pushWorkflowSteps(fresh, [
|
||||
@@ -9259,10 +9304,8 @@ export class RequestManagementService {
|
||||
]);
|
||||
fresh.workflow.currentStep = WorkflowStep.SECOND_COMPLETED;
|
||||
fresh.workflow.nextStep = WorkflowStep.WAITING_FOR_GUILT_DECISION;
|
||||
// THIRD_PARTY: second party sign is FileMaker's last step — seal for FileReviewer
|
||||
if (isFileMakerActor) {
|
||||
fresh.status = CaseStatus.WAITING_FOR_FILE_REVIEWER;
|
||||
}
|
||||
// blame.status transitions to WAITING_FOR_FILE_REVIEWER only after the
|
||||
// FileMaker completes all document uploads, not here at sign time.
|
||||
}
|
||||
await (fresh as any).save();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user