From c9e273fc4e9320e642edec887451abbca9d602c2 Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Wed, 16 Sep 2026 15:37:27 +0330 Subject: [PATCH] Rollback uploadDocument step resume --- .../schema/claim-case.identity.schema.ts | 3 + src/expert-claim/dto/expert-claim-v2.dto.ts | 8 ++ src/expert-claim/expert-claim.service.ts | 10 ++ .../file-maker-status-resume.spec.ts | 112 ------------------ .../request-management.service.ts | 87 ++++++-------- 5 files changed, 59 insertions(+), 161 deletions(-) delete mode 100644 src/request-management/file-maker-status-resume.spec.ts diff --git a/src/claim-request-management/entites/schema/claim-case.identity.schema.ts b/src/claim-request-management/entites/schema/claim-case.identity.schema.ts index d01912b..3daf41b 100644 --- a/src/claim-request-management/entites/schema/claim-case.identity.schema.ts +++ b/src/claim-request-management/entites/schema/claim-case.identity.schema.ts @@ -36,6 +36,9 @@ export class ClaimVehicleSnapshot { @Prop({ type: ClaimPlateSchema }) plate?: ClaimPlate; + + @Prop({ type: String }) + price?: string; } export const ClaimVehicleSnapshotSchema = SchemaFactory.createForClass(ClaimVehicleSnapshot); diff --git a/src/expert-claim/dto/expert-claim-v2.dto.ts b/src/expert-claim/dto/expert-claim-v2.dto.ts index 23df75e..e8057ca 100644 --- a/src/expert-claim/dto/expert-claim-v2.dto.ts +++ b/src/expert-claim/dto/expert-claim-v2.dto.ts @@ -121,6 +121,14 @@ export class SubmitExpertReplyV2Dto { @IsString() description?: string; + @ApiPropertyOptional({ + example: '1_000_000_000', + description: "Today's car price", + }) + @IsOptional() + @IsMoneyAmountString() + carPrice?: string; + @ApiProperty({ type: [PartPricingV2Dto], description: diff --git a/src/expert-claim/expert-claim.service.ts b/src/expert-claim/expert-claim.service.ts index b5b5681..4252548 100644 --- a/src/expert-claim/expert-claim.service.ts +++ b/src/expert-claim/expert-claim.service.ts @@ -3263,6 +3263,7 @@ export class ExpertClaimService { ) { if (actor.role !== RoleEnum.FIELD_EXPERT) requireActorClientKey(actor); const claim = await this.claimCaseDbService.findById(claimRequestId); + const blame = await this.blameRequestDbService.findById(claim.blameRequestId); if (!claim) { throw new NotFoundException( @@ -3303,6 +3304,14 @@ export class ExpertClaimService { ); } + if (reply.carPrice && blame.type !== BlameRequestType.CAR_BODY) { + throw new ForbiddenException("قیمت روز خودرو فقط در پرونده های بدنه باید بررسی شود") + } + + if (blame.type === BlameRequestType.THIRD_PARTY && reply.carPrice) { + throw new ForbiddenException("قیمت روز خودرو فقط در پرونده های بدنه باید بررسی شود") + } + const pricingValidationError = getExpertReplyPricingValidationError( reply.parts, { locale: "fa", enforceAmountBounds: true }, @@ -3531,6 +3540,7 @@ export class ExpertClaimService { "evaluation.ownerInsurerApproval": "", "evaluation.ownerPricedPartsApproval": "", }, + "vehicle.price": reply.carPrice, "workflow.currentStep": currentStep, "workflow.nextStep": nextWorkflowStep, [`evaluation.${replyField}`]: replyPayload, diff --git a/src/request-management/file-maker-status-resume.spec.ts b/src/request-management/file-maker-status-resume.spec.ts deleted file mode 100644 index 9f9c459..0000000 --- a/src/request-management/file-maker-status-resume.spec.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { Types } from "mongoose"; -import { CaseStatus } from "src/Types&Enums/blame-request-management/caseStatus.enum"; -import { ClaimCaseStatus } from "src/Types&Enums/claim-request-management/claim-case-status.enum"; -import { RoleEnum } from "src/Types&Enums/role.enum"; -import { RequestManagementService } from "./request-management.service"; - -describe("FileMaker V4/V5 status resume bridge", () => { - const makerId = new Types.ObjectId(); - const blameId = new Types.ObjectId(); - - const blameFile = { - _id: blameId, - publicId: "BL-FM-001", - requestNo: "R-1", - type: "THIRD_PARTY", - status: CaseStatus.OPEN, - blameStatus: "IN_PROGRESS", - isMadeByFileMaker: true, - initiatedByFieldExpertId: makerId, - requiresFileMakerApproval: false, - parties: [], - workflow: { - currentStep: "SECOND_COMPLETED", - nextStep: "WAITING_FOR_GUILT_DECISION", - completedSteps: ["SECOND_COMPLETED"], - }, - createdAt: new Date(), - updatedAt: new Date(), - }; - - it("overlays claim UPLOADING_REQUIRED_DOCUMENTS onto detail status", async () => { - const service = - new (RequestManagementService as any)() as RequestManagementService; - (service as any).blameRequestDbService = { - findById: jest.fn().mockResolvedValue(blameFile), - }; - (service as any).claimCaseDbService = { - findOne: jest.fn().mockResolvedValue({ - _id: new Types.ObjectId(), - blameRequestId: blameId, - status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS, - workflow: { - currentStep: "UPLOAD_REQUIRED_DOCUMENTS", - nextStep: "SELECT_OUTER_PARTS", - }, - }), - }; - - const detail = await service.getMyFileMakerFileDetail( - { sub: String(makerId), role: RoleEnum.FILE_MAKER }, - String(blameId), - ); - - expect(detail.status).toBe(ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS); - expect(detail.blameCaseStatus).toBe(CaseStatus.OPEN); - expect(detail.claimStatus).toBe( - ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS, - ); - }); - - it("does not overlay status when claim docs phase is finished", async () => { - const service = - new (RequestManagementService as any)() as RequestManagementService; - (service as any).blameRequestDbService = { - findById: jest.fn().mockResolvedValue({ - ...blameFile, - status: CaseStatus.WAITING_FOR_FILE_REVIEWER, - }), - }; - (service as any).claimCaseDbService = { - findOne: jest.fn().mockResolvedValue({ - _id: new Types.ObjectId(), - blameRequestId: blameId, - status: ClaimCaseStatus.WAITING_FOR_FILE_REVIEWER, - workflow: { currentStep: "SELECT_OUTER_PARTS" }, - }), - }; - - const detail = await service.getMyFileMakerFileDetail( - { sub: String(makerId), role: RoleEnum.FILE_MAKER }, - String(blameId), - ); - - expect(detail.status).toBe(CaseStatus.WAITING_FOR_FILE_REVIEWER); - expect(detail.blameCaseStatus).toBeUndefined(); - }); - - it("overlays the same bridge on my-files list rows", async () => { - const service = - new (RequestManagementService as any)() as RequestManagementService; - (service as any).blameRequestDbService = { - find: jest.fn().mockResolvedValue([blameFile]), - }; - (service as any).claimCaseDbService = { - find: jest.fn().mockResolvedValue([ - { - blameRequestId: blameId, - status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS, - }, - ]), - }; - - const rows = await service.getMyFileMakerFiles({ - sub: String(makerId), - role: RoleEnum.FILE_MAKER, - }); - - expect(rows).toHaveLength(1); - expect(rows[0].status).toBe(ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS); - expect(rows[0].blameCaseStatus).toBe(CaseStatus.OPEN); - }); -}); diff --git a/src/request-management/request-management.service.ts b/src/request-management/request-management.service.ts index 3ca48eb..2020b59 100644 --- a/src/request-management/request-management.service.ts +++ b/src/request-management/request-management.service.ts @@ -12733,25 +12733,25 @@ export class RequestManagementService { return { ...workflow, completedSteps }; } - /** - * V4/V5 dirty bridge: FileMaker FE resumes from blame `status`, but pre-capture - * document upload lives on the claim (`UPLOADING_REQUIRED_DOCUMENTS`) while blame - * is still at FIRST/SECOND_COMPLETED. Mirror claim status into `status` only for - * that phase so leave/re-enter can continue; keep real blame status as - * `blameCaseStatus`. Remove once FE keys off `claimStatus` / a unified resume pointer. - */ - private fileMakerStatusForResume( - blameStatus: unknown, - claimStatus: unknown, - ): { status: unknown; blameCaseStatus?: unknown } { - if (claimStatus === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS) { - return { - status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS, - blameCaseStatus: blameStatus, - }; - } - return { status: blameStatus }; - } + // /** + // * V4/V5 dirty bridge: FileMaker FE resumes from blame `status`, but pre-capture + // * document upload lives on the claim (`UPLOADING_REQUIRED_DOCUMENTS`) while blame + // * is still at FIRST/SECOND_COMPLETED. Mirror claim status into `status` only for + // * that phase so leave/re-enter can continue; keep real blame status as + // * `blameCaseStatus`. Remove once FE keys off `claimStatus` / a unified resume pointer. + // */ + // private fileMakerStatusForResume( + // blameStatus: unknown, + // claimStatus: unknown, + // ): { status: unknown; blameCaseStatus?: unknown } { + // if (claimStatus === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS) { + // return { + // status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS, + // blameCaseStatus: blameStatus, + // }; + // } + // return { status: blameStatus }; + // } async getMyFileMakerFiles(fileMaker: any): Promise { if (fileMaker?.role !== RoleEnum.FILE_MAKER) { @@ -12762,35 +12762,32 @@ export class RequestManagementService { isMadeByFileMaker: true, initiatedByFieldExpertId: makerId, }); - const blameIds = (files || []).map((f: any) => f._id).filter(Boolean); - const claims = - blameIds.length > 0 - ? await this.claimCaseDbService.find( - { blameRequestId: { $in: blameIds } }, - { lean: true, select: "blameRequestId status" }, - ) - : []; - const claimStatusByBlameId = new Map(); - for (const c of claims as any[]) { - const blameId = c?.blameRequestId != null ? String(c.blameRequestId) : ""; - if (blameId) claimStatusByBlameId.set(blameId, c.status); - } + // const blameIds = (files || []).map((f: any) => f._id).filter(Boolean); + // const claims = + // blameIds.length > 0 + // ? await this.claimCaseDbService.find( + // { blameRequestId: { $in: blameIds } }, + // { lean: true, select: "blameRequestId status" }, + // ) + // : []; + // const claimStatusByBlameId = new Map(); + // for (const c of claims as any[]) { + // const blameId = c?.blameRequestId != null ? String(c.blameRequestId) : ""; + // if (blameId) claimStatusByBlameId.set(blameId, c.status); + // } return (files || []).map((f: any) => { const workflow = this.fileMakerWorkflowProjection(f); - const resume = this.fileMakerStatusForResume( - f.status, - claimStatusByBlameId.get(String(f._id)), - ); + // const resume = this.fileMakerStatusForResume( + // f.status, + // claimStatusByBlameId.get(String(f._id)), + // ); return { _id: f._id, publicId: f.publicId, requestNo: f.requestNo, type: f.type, - status: resume.status, - ...(resume.blameCaseStatus !== undefined - ? { blameCaseStatus: resume.blameCaseStatus } - : {}), + status: f.status, blameStatus: f.blameStatus, workflow: { currentStep: workflow.currentStep, @@ -12835,20 +12832,12 @@ export class RequestManagementService { : claim ? { ...(claim as any) } : null; - const resume = this.fileMakerStatusForResume( - plain.status, - claimPlain?.status, - ); - return { _id: plain._id, publicId: plain.publicId, requestNo: plain.requestNo, type: plain.type, - status: resume.status, - ...(resume.blameCaseStatus !== undefined - ? { blameCaseStatus: resume.blameCaseStatus } - : {}), + status: plain.status, blameStatus: plain.blameStatus, workflow: this.fileMakerWorkflowProjection(plain), requiresFileMakerApproval: plain.requiresFileMakerApproval,