forked from Yara724/api
Merge pull request 'Rollback uploadDocument resume, added carPrice' (#324) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#324
This commit is contained in:
@@ -36,6 +36,9 @@ export class ClaimVehicleSnapshot {
|
|||||||
|
|
||||||
@Prop({ type: ClaimPlateSchema })
|
@Prop({ type: ClaimPlateSchema })
|
||||||
plate?: ClaimPlate;
|
plate?: ClaimPlate;
|
||||||
|
|
||||||
|
@Prop({ type: String })
|
||||||
|
price?: string;
|
||||||
}
|
}
|
||||||
export const ClaimVehicleSnapshotSchema =
|
export const ClaimVehicleSnapshotSchema =
|
||||||
SchemaFactory.createForClass(ClaimVehicleSnapshot);
|
SchemaFactory.createForClass(ClaimVehicleSnapshot);
|
||||||
|
|||||||
@@ -121,6 +121,14 @@ export class SubmitExpertReplyV2Dto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
example: '1_000_000_000',
|
||||||
|
description: "Today's car price",
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsMoneyAmountString()
|
||||||
|
carPrice?: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
type: [PartPricingV2Dto],
|
type: [PartPricingV2Dto],
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -3263,6 +3263,7 @@ export class ExpertClaimService {
|
|||||||
) {
|
) {
|
||||||
if (actor.role !== RoleEnum.FIELD_EXPERT) requireActorClientKey(actor);
|
if (actor.role !== RoleEnum.FIELD_EXPERT) requireActorClientKey(actor);
|
||||||
const claim = await this.claimCaseDbService.findById(claimRequestId);
|
const claim = await this.claimCaseDbService.findById(claimRequestId);
|
||||||
|
const blame = await this.blameRequestDbService.findById(claim.blameRequestId);
|
||||||
|
|
||||||
if (!claim) {
|
if (!claim) {
|
||||||
throw new NotFoundException(
|
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(
|
const pricingValidationError = getExpertReplyPricingValidationError(
|
||||||
reply.parts,
|
reply.parts,
|
||||||
{ locale: "fa", enforceAmountBounds: true },
|
{ locale: "fa", enforceAmountBounds: true },
|
||||||
@@ -3531,6 +3540,7 @@ export class ExpertClaimService {
|
|||||||
"evaluation.ownerInsurerApproval": "",
|
"evaluation.ownerInsurerApproval": "",
|
||||||
"evaluation.ownerPricedPartsApproval": "",
|
"evaluation.ownerPricedPartsApproval": "",
|
||||||
},
|
},
|
||||||
|
"vehicle.price": reply.carPrice,
|
||||||
"workflow.currentStep": currentStep,
|
"workflow.currentStep": currentStep,
|
||||||
"workflow.nextStep": nextWorkflowStep,
|
"workflow.nextStep": nextWorkflowStep,
|
||||||
[`evaluation.${replyField}`]: replyPayload,
|
[`evaluation.${replyField}`]: replyPayload,
|
||||||
|
|||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -12733,25 +12733,25 @@ export class RequestManagementService {
|
|||||||
return { ...workflow, completedSteps };
|
return { ...workflow, completedSteps };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* V4/V5 dirty bridge: FileMaker FE resumes from blame `status`, but pre-capture
|
// * V4/V5 dirty bridge: FileMaker FE resumes from blame `status`, but pre-capture
|
||||||
* document upload lives on the claim (`UPLOADING_REQUIRED_DOCUMENTS`) while blame
|
// * document upload lives on the claim (`UPLOADING_REQUIRED_DOCUMENTS`) while blame
|
||||||
* is still at FIRST/SECOND_COMPLETED. Mirror claim status into `status` only for
|
// * 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
|
// * that phase so leave/re-enter can continue; keep real blame status as
|
||||||
* `blameCaseStatus`. Remove once FE keys off `claimStatus` / a unified resume pointer.
|
// * `blameCaseStatus`. Remove once FE keys off `claimStatus` / a unified resume pointer.
|
||||||
*/
|
// */
|
||||||
private fileMakerStatusForResume(
|
// private fileMakerStatusForResume(
|
||||||
blameStatus: unknown,
|
// blameStatus: unknown,
|
||||||
claimStatus: unknown,
|
// claimStatus: unknown,
|
||||||
): { status: unknown; blameCaseStatus?: unknown } {
|
// ): { status: unknown; blameCaseStatus?: unknown } {
|
||||||
if (claimStatus === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS) {
|
// if (claimStatus === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS) {
|
||||||
return {
|
// return {
|
||||||
status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS,
|
// status: ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS,
|
||||||
blameCaseStatus: blameStatus,
|
// blameCaseStatus: blameStatus,
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
return { status: blameStatus };
|
// return { status: blameStatus };
|
||||||
}
|
// }
|
||||||
|
|
||||||
async getMyFileMakerFiles(fileMaker: any): Promise<any[]> {
|
async getMyFileMakerFiles(fileMaker: any): Promise<any[]> {
|
||||||
if (fileMaker?.role !== RoleEnum.FILE_MAKER) {
|
if (fileMaker?.role !== RoleEnum.FILE_MAKER) {
|
||||||
@@ -12762,35 +12762,32 @@ export class RequestManagementService {
|
|||||||
isMadeByFileMaker: true,
|
isMadeByFileMaker: true,
|
||||||
initiatedByFieldExpertId: makerId,
|
initiatedByFieldExpertId: makerId,
|
||||||
});
|
});
|
||||||
const blameIds = (files || []).map((f: any) => f._id).filter(Boolean);
|
// const blameIds = (files || []).map((f: any) => f._id).filter(Boolean);
|
||||||
const claims =
|
// const claims =
|
||||||
blameIds.length > 0
|
// blameIds.length > 0
|
||||||
? await this.claimCaseDbService.find(
|
// ? await this.claimCaseDbService.find(
|
||||||
{ blameRequestId: { $in: blameIds } },
|
// { blameRequestId: { $in: blameIds } },
|
||||||
{ lean: true, select: "blameRequestId status" },
|
// { lean: true, select: "blameRequestId status" },
|
||||||
)
|
// )
|
||||||
: [];
|
// : [];
|
||||||
const claimStatusByBlameId = new Map<string, unknown>();
|
// const claimStatusByBlameId = new Map<string, unknown>();
|
||||||
for (const c of claims as any[]) {
|
// for (const c of claims as any[]) {
|
||||||
const blameId = c?.blameRequestId != null ? String(c.blameRequestId) : "";
|
// const blameId = c?.blameRequestId != null ? String(c.blameRequestId) : "";
|
||||||
if (blameId) claimStatusByBlameId.set(blameId, c.status);
|
// if (blameId) claimStatusByBlameId.set(blameId, c.status);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return (files || []).map((f: any) => {
|
return (files || []).map((f: any) => {
|
||||||
const workflow = this.fileMakerWorkflowProjection(f);
|
const workflow = this.fileMakerWorkflowProjection(f);
|
||||||
const resume = this.fileMakerStatusForResume(
|
// const resume = this.fileMakerStatusForResume(
|
||||||
f.status,
|
// f.status,
|
||||||
claimStatusByBlameId.get(String(f._id)),
|
// claimStatusByBlameId.get(String(f._id)),
|
||||||
);
|
// );
|
||||||
return {
|
return {
|
||||||
_id: f._id,
|
_id: f._id,
|
||||||
publicId: f.publicId,
|
publicId: f.publicId,
|
||||||
requestNo: f.requestNo,
|
requestNo: f.requestNo,
|
||||||
type: f.type,
|
type: f.type,
|
||||||
status: resume.status,
|
status: f.status,
|
||||||
...(resume.blameCaseStatus !== undefined
|
|
||||||
? { blameCaseStatus: resume.blameCaseStatus }
|
|
||||||
: {}),
|
|
||||||
blameStatus: f.blameStatus,
|
blameStatus: f.blameStatus,
|
||||||
workflow: {
|
workflow: {
|
||||||
currentStep: workflow.currentStep,
|
currentStep: workflow.currentStep,
|
||||||
@@ -12835,20 +12832,12 @@ export class RequestManagementService {
|
|||||||
: claim
|
: claim
|
||||||
? { ...(claim as any) }
|
? { ...(claim as any) }
|
||||||
: null;
|
: null;
|
||||||
const resume = this.fileMakerStatusForResume(
|
|
||||||
plain.status,
|
|
||||||
claimPlain?.status,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_id: plain._id,
|
_id: plain._id,
|
||||||
publicId: plain.publicId,
|
publicId: plain.publicId,
|
||||||
requestNo: plain.requestNo,
|
requestNo: plain.requestNo,
|
||||||
type: plain.type,
|
type: plain.type,
|
||||||
status: resume.status,
|
status: plain.status,
|
||||||
...(resume.blameCaseStatus !== undefined
|
|
||||||
? { blameCaseStatus: resume.blameCaseStatus }
|
|
||||||
: {}),
|
|
||||||
blameStatus: plain.blameStatus,
|
blameStatus: plain.blameStatus,
|
||||||
workflow: this.fileMakerWorkflowProjection(plain),
|
workflow: this.fileMakerWorkflowProjection(plain),
|
||||||
requiresFileMakerApproval: plain.requiresFileMakerApproval,
|
requiresFileMakerApproval: plain.requiresFileMakerApproval,
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ export function mapEsgCarBodyPolicyToInquiry(
|
|||||||
|
|
||||||
// Provider responses do not currently include an insurer company identity.
|
// Provider responses do not currently include an insurer company identity.
|
||||||
companyId: policy.CompanyId ?? null,
|
companyId: policy.CompanyId ?? null,
|
||||||
CompanyCode: policy.CompanyId ?? null,
|
CompanyCode: policy.CompanyId ?? "8",
|
||||||
CompanyName: policy.CompanyName ?? null,
|
CompanyName: policy.CompanyName ?? "بیمه پارسیان",
|
||||||
|
|
||||||
// The lookup's customer is the policyholder/owner, not the insurer.
|
// The lookup's customer is the policyholder/owner, not the insurer.
|
||||||
insurerName: null,
|
insurerName: null,
|
||||||
|
|||||||
Reference in New Issue
Block a user