Compare commits

...

20 Commits

Author SHA1 Message Date
49fe548215 Merge pull request 'Fixed v5 file maker approval field' (#213) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#213
2026-07-25 10:25:10 +03:30
SepehrYahyaee
777eae1028 Fixed v5 file maker approval field 2026-07-25 10:24:34 +03:30
b67dd733cd Merge pull request 'Fixed upload documents counting for v4' (#212) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#212
2026-07-25 09:53:07 +03:30
SepehrYahyaee
4818f73252 Fixed upload documents counting for v4 2026-07-25 09:52:42 +03:30
cc8a5354c7 Merge pull request 'v4 bug fixed' (#211) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#211
2026-07-25 09:29:42 +03:30
SepehrYahyaee
2d5ade33d2 v4 bug fixed 2026-07-25 09:29:12 +03:30
b73c92c21f Merge pull request 'Fixed Bugs: 1) V4 incorrect advancement to file maker approval state, 2) V4 race condition for finishing file maker steps' (#210) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#210
2026-07-23 13:44:05 +03:30
f9f462d47b Fixed Bugs: 1) V4 incorrect advancement to file maker approval state, 2) V4 race condition for finishing file maker steps 2026-07-23 13:43:37 +03:30
c3eb36dc41 Merge pull request 'Fixed v4 sign' (#209) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#209
2026-07-22 17:37:00 +03:30
SepehrYahyaee
f75ecf5c2c Fixed v4 sign 2026-07-22 17:36:29 +03:30
75c4cb6a05 Merge pull request 'Fixed v4/v5 flow' (#208) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#208
2026-07-22 17:22:55 +03:30
SepehrYahyaee
7a4277f8b2 Fixed v4/v5 flow 2026-07-22 17:22:27 +03:30
e50bc78344 Merge pull request 'Fixed sign' (#207) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#207
2026-07-22 15:47:02 +03:30
SepehrYahyaee
2c1cd93dd0 Fixed sign 2026-07-22 15:46:33 +03:30
ffd44df718 Merge pull request 'Fix v2 flow sign of second party' (#206) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#206
2026-07-22 15:35:53 +03:30
SepehrYahyaee
64865b70f2 Fix v2 flow sign of second party 2026-07-22 15:35:14 +03:30
c207c30be9 Merge pull request 'Fixed v2 flow' (#205) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#205
2026-07-22 15:10:00 +03:30
SepehrYahyaee
fcb169e9ac Fixed v2 flow 2026-07-22 15:09:34 +03:30
1867292499 Merge pull request 'Fixed v2 flow' (#204) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#204
2026-07-22 14:53:33 +03:30
SepehrYahyaee
2cc96f6132 Fixed v2 flow 2026-07-22 14:52:51 +03:30
7 changed files with 235 additions and 87 deletions

View File

@@ -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,27 +6335,41 @@ 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) {
await this.claimCaseDbService.findByIdAndUpdate(claimCaseId, {
$set: { status: ClaimCaseStatus.WAITING_FOR_FILE_MAKER_APPROVAL },
$push: {
history: {
type: "V5_HELD_FOR_FILE_MAKER_APPROVAL",
actor: { actorType: "system" },
timestamp: new Date(),
metadata: { claimCaseId },
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: {
history: {
type: "V5_HELD_FOR_FILE_MAKER_APPROVAL",
actor: { actorType: "system" },
timestamp: new Date(),
metadata: { claimCaseId },
},
},
},
});
return {
attempted: false,
submitted: false,
skipped: true,
skipReason:
"V5 flow: FileMaker approval required before Fanavaran submission. " +
"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: "" },
});
return {
attempted: false,
submitted: false,
skipped: true,
skipReason:
"V5 flow: FileMaker approval required before Fanavaran submission. " +
"Claim is now in WAITING_FOR_FILE_MAKER_APPROVAL.",
};
}
const skipReason = await this.getFanavaranAutoSubmitSkipReason(claimCase);
@@ -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(

View File

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

View File

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

View 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")

View File

@@ -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 },
);
}

View File

@@ -88,7 +88,7 @@ export class FileMakerBlameV5Controller {
) {
return this.requestManagementService.createExpertInitiatedBlameV2(
fileMaker,
{ ...dto, creationMethod: CreationMethod.IN_PERSON },
{ ...dto, creationMethod: CreationMethod.IN_PERSON, requiresFileMakerApproval: true },
);
}

View File

@@ -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 postfield-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();
}