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.
This commit is contained in:
2026-09-18 16:04:33 +03:30
parent a84d83a135
commit 7d1a50db7b
38 changed files with 2345 additions and 370 deletions

View File

@@ -14,6 +14,7 @@ import {
PR,
persianAccidentCondition,
persianFieldPath,
persianReportValue,
persianStatus,
} from "./persian-report-labels";
@@ -110,10 +111,13 @@ function firstDefined(...values: unknown[]): string | undefined {
return undefined;
}
function normalizeListValue(value: unknown): string | undefined {
function normalizeListValue(value: unknown, path = ""): string | undefined {
if (!Array.isArray(value) || !value.length) return undefined;
const items = value
.map((item) => asString(item) ?? JSON.stringify(item))
.map(
(item) =>
asString(persianReportValue(path, item)) ?? JSON.stringify(item),
)
.filter(Boolean);
return items.length ? items.join("، ") : undefined;
}
@@ -124,18 +128,31 @@ function flattenObject(
depth = 0,
): InsurerFileReportField[] {
if (obj == null) return [];
if (depth > 4) {
return [{ label: persianFieldPath(prefix), value: asString(obj) }];
if (depth > 6) {
return [
{
label: persianFieldPath(prefix),
value: asString(persianReportValue(prefix, obj)),
},
];
}
if (Array.isArray(obj)) {
const value = normalizeListValue(obj);
if (obj.some((item) => item && typeof item === "object")) {
return obj.flatMap((item, index) =>
flattenObject(item, `${prefix}.${index + 1}`, depth + 1),
);
}
const value = normalizeListValue(obj, prefix);
return value ? [{ label: persianFieldPath(prefix || "items"), value }] : [];
}
if (typeof obj !== "object") {
return [
{ label: persianFieldPath(prefix || "value"), value: asString(obj) },
{
label: persianFieldPath(prefix || "value"),
value: asString(persianReportValue(prefix || "value", obj)),
},
];
}
@@ -150,14 +167,13 @@ function flattenObject(
if (value === undefined || value === null || value === "") continue;
const path = prefix ? `${prefix}.${key}` : key;
if (
typeof value === "object" &&
!Array.isArray(value) &&
!(value instanceof Date)
) {
if (typeof value === "object" && !(value instanceof Date)) {
rows.push(...flattenObject(value, path, depth + 1));
} else {
rows.push({ label: persianFieldPath(path), value: asString(value) });
rows.push({
label: persianFieldPath(path),
value: asString(persianReportValue(path, value)),
});
}
}
@@ -638,6 +654,17 @@ function buildParticipantRolesSection(
participant?.licenseNumber
? `${PR.licenseNumber}: ${asString(participant.licenseNumber)}`
: undefined,
participant?.hasDrivingLicense != null
? `${PR.hasDrivingLicense}: ${persianStatus(participant.hasDrivingLicense)}`
: undefined,
participant?.licenseType
? `${PR.licenseType}: ${asString(
persianReportValue(
"participant.licenseType",
participant.licenseType,
),
)}`
: undefined,
]
.filter(Boolean)
.join("، ");
@@ -695,8 +722,12 @@ function buildDriverSection(
{
label: PR.licenseType,
value:
licenseType ??
asString(person.licenseType) ??
asString(
persianReportValue(
"participant.licenseType",
licenseType ?? person.licenseType,
),
) ??
(person.driverLicense ? PR.driverLicense : undefined),
},
{
@@ -895,7 +926,7 @@ function evaluationDaghiValue(value: unknown): string | undefined {
return asString(value);
}
const daghi = value as ReportRecord;
const option = asString(daghi.option);
const option = asString(persianReportValue("daghi.option", daghi.option));
const price = formatToman(daghi.price);
return [option, price].filter(Boolean).join(" - ") || undefined;
}
@@ -915,7 +946,9 @@ function buildEvaluationPartsSection(
{ label: `${prefix} / ${PR.partName}`, value: evaluationPartName(part) },
{
label: `${prefix} / ${PR.damageType}`,
value: asString(part.typeOfDamage),
value: asString(
persianReportValue("evaluation.part.typeOfDamage", part.typeOfDamage),
),
},
{ label: `${prefix} / ${PR.partPrice}`, value: formatToman(part.price) },
{