Files
yara724-api/src/case-expert-report/case-expert-report.builder.spec.ts
Sepehr Yahyaee 7d1a50db7b fix: harden claim review and inquiry workflows
Preserve damage history and current vehicle price, restore depreciation mapping, normalize inquiry/report output, and support resumable expert review with paginated case retrieval.
2026-09-18 16:04:33 +03:30

590 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { buildInsurerFileReport } from "./case-expert-report.builder";
import { PR } from "./persian-report-labels";
describe("buildInsurerFileReport", () => {
const getFieldValue = (
report: ReturnType<typeof buildInsurerFileReport>,
sectionTitle: string,
fieldLabel: string,
) => {
const section = report.sections.find((item) => item.title === sectionTitle);
expect(section).toBeDefined();
const field = section?.fields.find((item) => item.label === fieldLabel);
expect(field).toBeDefined();
return field?.value;
};
it("separates insurance blocks and exposes Fanavaran/timeline/evaluation data", () => {
const fileCreatedAt = new Date("2026-08-10T09:53:23.588Z");
const evaluationSubmittedAt = new Date("2026-08-10T12:30:45.000Z");
const report = buildInsurerFileReport({
overview: {
publicId: "A00010",
requestNo: "REQ-10",
createdAt: fileCreatedAt,
},
blame: {
type: "THIRD_PARTY",
blameStatus: "AGREED",
createdAt: fileCreatedAt,
parties: [
{
role: "FIRST",
person: {
userId: "guilty-user-id",
fullName: "مقصر نمونه",
phoneNumber: "09120000000",
nationalCodeOfInsurer: "0987654321",
insurerBirthday: 13650115,
clientId: "client-guilty",
},
statement: {
admitsGuilt: true,
acceptsExpertOpinion: true,
description: "توضیحات مقصر",
},
vehicle: {
carName: "206",
carModel: "1401",
plate: {
leftDigits: 98,
centerAlphabet: "ج",
centerDigits: 765,
ir: 22,
},
},
insurance: {
policyNumber: "TP-GUILTY-001",
company: "بیمه ثالث مقصر",
startDate: "1405/01/01",
endDate: "1406/01/01",
financialCeiling: "900000000",
carBodyInsurance: {
policyNumber: "CB-GUILTY-001",
insurerCompany: "بیمه بدنه مقصر",
startDate: "1405/02/01",
endDate: "1406/02/01",
},
},
},
{
role: "SECOND",
participants: [
{
participantId: "DRIVER",
fullName: "راننده نمونه",
nationalCode: "0012345678",
birthday: "1370/01/01",
licenseNumber: "LIC-1",
},
{
participantId: "VEHICLE_OWNER",
fullName: "زیان دیده نمونه",
nationalCode: "1234567890",
birthday: "1370/01/01",
},
],
participantRoles: {
driver: "DRIVER",
vehicleOwner: "VEHICLE_OWNER",
thirdPartyPolicyholder: "VEHICLE_OWNER",
},
person: {
userId: "damaged-user-id",
fullName: "زیان دیده نمونه",
phoneNumber: "09121111111",
nationalCodeOfInsurer: "1234567890",
clientId: "client-damaged",
insurerBirthday: 13700101,
},
statement: {
claimsDamage: true,
acceptsExpertOpinion: false,
description: "توضیحات زیان‌دیده",
accidentDate: "2026-08-10",
accidentTime: "13:23",
},
insurance: {
policyNumber: "TP-DAMAGED-001",
company: "بیمه ثالث زیان‌دیده",
startDate: "1405/03/01",
endDate: "1406/03/01",
financialCeiling: "700000000",
carBodyInsurance: {
policyNumber: "CB-DAMAGED-001",
insurerCompany: "بیمه بدنه زیان‌دیده",
startDate: "1405/04/01",
endDate: "1406/04/01",
coverages: ["سرقت", "آتش‌سوزی"],
},
},
vehicle: {
carName: "207",
carModel: "1402",
plate: {
leftDigits: 12,
centerAlphabet: "ب",
centerDigits: 345,
ir: 11,
},
},
},
],
expert: {
decision: {
guiltyPartyId: "guilty-user-id",
description: "مقصر شناخته شد",
fields: {
accidentWay: { label: "از جلو" },
accidentReason: { label: "عدم رعایت فاصله" },
accidentType: { label: "برخورد" },
},
},
},
},
claim: {
claimStatus: "APPROVED",
claimNo: 111,
claimId: 222,
dmgCaseId: 333,
expertiseId: 444,
owner: { fullName: "زیان دیده نمونه" },
vehicle: {
carName: "207",
carModel: "1402",
carType: "sedan",
},
fanavaranSync: {
baseClaim: {
policyId: 555,
driverId: 666,
vehicleKindId: 777,
insuranceCorpId: 888,
},
},
evaluation: {
damageExpertReplyFinal: {
submittedAt: evaluationSubmittedAt,
description: "نیاز به تعویض سپر جلو",
actorDetail: { actorName: "کارشناس خسارت نمونه" },
parts: [
{
partId: 12,
carPartDamage: { label_fa: "سپر جلو" },
typeOfDamage: "تعویض",
price: 2_500_000,
salary: 500_000,
totalPayment: 3_000_000,
factorNeeded: false,
daghi: { option: "تحویل داغی" },
},
],
},
},
},
});
expect(getFieldValue(report, PR.ownerSection, PR.name)).toBe(
"زیان دیده نمونه",
);
expect(
getFieldValue(report, PR.damagedParticipantsSection, PR.driverRole),
).toContain("راننده نمونه");
expect(
getFieldValue(
report,
PR.damagedParticipantsSection,
PR.thirdPartyPolicyholderRole,
),
).toContain("1234567890");
expect(getFieldValue(report, PR.guiltyOwnerSection, PR.name)).toBe(
"مقصر نمونه",
);
expect(getFieldValue(report, PR.guiltyOwnerSection, PR.phone)).toBe(
"09120000000",
);
expect(getFieldValue(report, PR.guiltyOwnerSection, PR.nationalCode)).toBe(
"0987654321",
);
expect(
getFieldValue(
report,
PR.damagedThirdPartyInsuranceSection,
PR.policyNumber,
),
).toBe("TP-DAMAGED-001");
expect(
getFieldValue(
report,
PR.guiltyThirdPartyInsuranceSection,
PR.policyNumber,
),
).toBe("TP-GUILTY-001");
expect(
getFieldValue(report, PR.damagedCarBodyInsuranceSection, PR.policyNumber),
).toBe("CB-DAMAGED-001");
expect(
getFieldValue(report, PR.guiltyCarBodyInsuranceSection, PR.policyNumber),
).toBe("CB-GUILTY-001");
expect(
getFieldValue(report, PR.damagedVehicleSection, "خودرو / نام خودرو"),
).toBe("207");
expect(
getFieldValue(report, PR.guiltyVehicleSection, "خودرو / نام خودرو"),
).toBe("206");
expect(
getFieldValue(report, PR.damagedStatementSection, PR.partyDescription),
).toBe("توضیحات زیان‌دیده");
expect(
getFieldValue(report, PR.damagedStatementSection, PR.claimsDamage),
).toBe("بله");
expect(
getFieldValue(
report,
PR.damagedStatementSection,
PR.acceptsExpertOpinion,
),
).toBe("خیر");
expect(
getFieldValue(report, PR.guiltyStatementSection, PR.partyDescription),
).toBe("توضیحات مقصر");
expect(
getFieldValue(report, PR.guiltyStatementSection, PR.admitsGuilt),
).toBe("بله");
expect(
getFieldValue(report, PR.guiltyStatementSection, PR.acceptsExpertOpinion),
).toBe("بله");
expect(
getFieldValue(report, PR.fanavaranSection, PR.fanavaranClaimNo),
).toBe("111");
expect(
getFieldValue(report, PR.fanavaranSection, PR.fanavaranExpertiseId),
).toBe("444");
expect(
getFieldValue(report, PR.fanavaranSection, PR.fanavaranPolicyId),
).toBe("555");
expect(getFieldValue(report, PR.timelineSection, PR.fileRegisteredAt)).toBe(
"1405/05/19 13:23",
);
expect(
getFieldValue(report, PR.timelineSection, PR.evaluationRegisteredAt),
).toBe("1405/05/19 16:00");
expect(
getFieldValue(report, PR.evaluationSection, PR.evaluationResult),
).toBe("تأیید شده");
expect(
getFieldValue(report, PR.evaluationSection, PR.evaluationExpert),
).toBe("کارشناس خسارت نمونه");
expect(
getFieldValue(report, PR.evaluationSection, PR.evaluationResponse),
).toBe("نیاز به تعویض سپر جلو");
expect(getFieldValue(report, "قیمت قطعات", "قطعه ۱ / نام قطعه")).toBe(
"سپر جلو",
);
expect(getFieldValue(report, "قیمت قطعات", "قطعه ۱ / قیمت قطعه")).toBe(
"۲٬۵۰۰٬۰۰۰ تومان",
);
expect(getFieldValue(report, "قیمت قطعات", "قطعه ۱ / مبلغ کل")).toBe(
"۳٬۰۰۰٬۰۰۰ تومان",
);
});
it("localizes legacy English car-body environmental conditions", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00012" },
blame: {
type: "CAR_BODY",
parties: [
{
role: "FIRST",
person: { userId: "damaged", fullName: "بیمه‌گذار" },
statement: {
weatherCondition: "CLEAR",
roadCondition: "wet",
lightCondition: "LOW_LIGHT",
},
},
],
},
});
expect(getFieldValue(report, PR.accidentSection, PR.weather)).toBe("صاف");
expect(getFieldValue(report, PR.accidentSection, PR.road)).toBe("مرطوب");
expect(getFieldValue(report, PR.accidentSection, PR.light)).toBe("کم‌نور");
});
it("exposes the damage expert part-price result as a separate section", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00013" },
claim: {
claimStatus: "APPROVED",
evaluation: {
damageExpertReply: {
description: "تعویض قطعه ضروری است",
parts: [
{
carPartDamage: { label_fa: "چراغ جلو" },
price: 4_000_000,
totalPayment: 4_000_000,
},
],
},
},
},
});
expect(getFieldValue(report, "قیمت قطعات", "قطعه ۱ / نام قطعه")).toBe(
"چراغ جلو",
);
expect(getFieldValue(report, "قیمت قطعات", "قطعه ۱ / قیمت قطعه")).toBe(
"۴٬۰۰۰٬۰۰۰ تومان",
);
});
it("falls back to claim history for the evaluation submission time", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00014" },
claim: {
evaluation: {
damageExpertReply: { description: "ارزیابی ثبت شد" },
},
history: [
{
type: "EXPERT_REPLY_SUBMITTED",
timestamp: "2026-08-10T12:30:45.000Z",
},
],
},
});
expect(
getFieldValue(report, PR.timelineSection, PR.evaluationRegisteredAt),
).toBe("1405/05/19 16:00");
expect(
getFieldValue(report, PR.evaluationSection, PR.evaluationSubmittedAt),
).toBe("1405/05/19 16:00");
});
it("localizes every boolean value", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00015" },
blame: {
type: "CAR_BODY",
parties: [
{
role: "FIRST",
person: { userId: "damaged", fullName: "بیمه‌گذار" },
vehicle: {
isNew: true,
hasEndorsement: false,
source: "ESG_CAR_BODY_INQUIRY",
inquiry: { source: "TEJARAT_BLOCK_INQUIRY" },
},
},
],
},
});
const fields = report.sections.flatMap((section) => section.fields);
expect(
fields.find((field) => field.label === "خودرو / خودرو نو")?.value,
).toBe("بله");
expect(fields.some((field) => field.value === "خیر")).toBe(true);
expect(fields.some((field) => field.value === "true")).toBe(false);
expect(fields.some((field) => field.value === "false")).toBe(false);
});
it("hides ESG and TEJARAT inquiry source details", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00016" },
blame: {
type: "CAR_BODY",
parties: [
{
role: "FIRST",
person: { userId: "damaged", fullName: "بیمه‌گذار" },
vehicle: {
source: "ESG_CAR_BODY_INQUIRY",
inquiry: { source: "TEJARAT_BLOCK_INQUIRY" },
},
},
],
},
});
const fields = report.sections.flatMap((section) => section.fields);
expect(fields.some((field) => String(field.value).includes("ESG"))).toBe(
false,
);
expect(
fields.some((field) => String(field.value).includes("TEJARAT")),
).toBe(false);
expect(fields.some((field) => field.label.includes("منبع"))).toBe(false);
});
it("uses the stored V4 licence type for a driver who differs from the policyholder", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00011" },
blame: {
type: "THIRD_PARTY",
parties: [
{
role: "FIRST",
person: { userId: "guilty", fullName: "مقصر" },
},
{
role: "SECOND",
person: {
userId: "damaged",
fullName: "بیمه‌گذار زیان‌دیده",
driverIsInsurer: false,
nationalCodeOfDriver: "0123456789",
driverLicense: "L-123",
licenseType: "پایه یک",
},
},
],
expert: { decision: { guiltyPartyId: "guilty" } },
},
});
expect(getFieldValue(report, PR.driverSection, PR.nationalCode)).toBe(
"0123456789",
);
expect(getFieldValue(report, PR.driverSection, PR.licenseType)).toBe(
"پایه یک",
);
});
it("localizes participant and recent-transfer inquiry data", () => {
const report = buildInsurerFileReport({
overview: { publicId: "A00017" },
blame: {
type: "THIRD_PARTY",
parties: [
{
role: "FIRST",
person: { userId: "guilty", fullName: "مقصر" },
},
{
role: "SECOND",
person: { userId: "damaged", fullName: "زیان‌دیده" },
participants: [
{
participantId: "DRIVER",
fullName: "راننده",
nationalCode: "0012345678",
birthday: "1370/01/01",
hasDrivingLicense: true,
licenseNumber: "123456789",
licenseType: "BASE_2",
},
],
participantRoles: {
driver: "DRIVER",
vehicleOwner: "DRIVER",
thirdPartyPolicyholder: "DRIVER",
},
vehicle: {
registrationState: "RECENTLY_TRANSFERRED",
previousPlateId: "55ج222ایران33",
previousPolicyholderNationalCode: "0098765432",
currentPlate: {
leftDigits: "44",
centerAlphabet: "ب",
centerDigits: "111",
ir: "22",
},
inquiry: {
plateKind: "PREVIOUS",
attempts: [
{
plateKind: "CURRENT",
plate: {
leftDigits: "44",
centerAlphabet: "ب",
centerDigits: "111",
ir: "22",
},
succeeded: false,
error: "not found",
},
{
plateKind: "PREVIOUS",
succeeded: true,
usable: true,
},
],
},
},
},
],
expert: { decision: { guiltyPartyId: "guilty" } },
},
claim: {
vehicle: { carType: "SEDAN" },
},
});
expect(
getFieldValue(
report,
PR.damagedVehicleSection,
"خودرو / وضعیت پلاک و مالکیت",
),
).toBe("انتقال مالکیت اخیر");
expect(
getFieldValue(report, PR.damagedVehicleSection, "خودرو / نوع خودرو"),
).toBe("سواری");
expect(
getFieldValue(report, PR.damagedVehicleSection, "خودرو / پلاک قبلی"),
).toBe("55ج222ایران33");
expect(
getFieldValue(
report,
PR.damagedVehicleSection,
"خودرو / پلاک فعلی / دو رقم چپ پلاک",
),
).toBe("44");
const driver = getFieldValue(
report,
PR.damagedParticipantsSection,
PR.driverRole,
);
expect(driver).toContain("گواهینامه دارد: بله");
expect(driver).toContain("نوع گواهینامه: پایه دو");
expect(
getFieldValue(
report,
PR.damagedVehicleSection,
"خودرو / سوابق تلاش استعلام / تلاش ۱ / نوع پلاک استعلام‌شده",
),
).toBe("پلاک فعلی");
expect(
getFieldValue(
report,
PR.damagedVehicleSection,
"خودرو / سوابق تلاش استعلام / تلاش ۱ / خطا",
),
).toBe("موردی یافت نشد");
const renderedText = report.sections
.flatMap((section) => [
section.title,
...section.fields.flatMap((field) => [field.label, field.value]),
])
.join(" ");
expect(renderedText).not.toMatch(
/RECENTLY_TRANSFERRED|BASE_2|registrationState|previousPlateId|plateKind|not found|CURRENT|PREVIOUS/,
);
});
});