forked from Yara724/api
YARA-1258
This commit is contained in:
@@ -9,7 +9,12 @@ import {
|
||||
InsurerFileReportSection,
|
||||
InsurerFileReportViewModel,
|
||||
} from "./case-expert-report.types";
|
||||
import { PR, persianFieldPath, persianStatus } from "./persian-report-labels";
|
||||
import {
|
||||
PR,
|
||||
persianAccidentCondition,
|
||||
persianFieldPath,
|
||||
persianStatus,
|
||||
} from "./persian-report-labels";
|
||||
|
||||
const SKIP_FLATTEN_KEYS = new Set([
|
||||
"_id",
|
||||
@@ -65,6 +70,32 @@ function formatDateTime(value: unknown): string | undefined {
|
||||
return `${d} ${t}`;
|
||||
}
|
||||
|
||||
const PERSIAN_NUMBER_FORMATTER = new Intl.NumberFormat("fa-IR", {
|
||||
maximumFractionDigits: 0,
|
||||
});
|
||||
|
||||
function normalizeNumber(value: unknown): number | undefined {
|
||||
if (typeof value === "number") {
|
||||
return Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
if (typeof value !== "string" || !value.trim()) return undefined;
|
||||
|
||||
const normalized = value
|
||||
.trim()
|
||||
.replace(/[۰-۹]/g, (digit) => String("۰۱۲۳۴۵۶۷۸۹".indexOf(digit)))
|
||||
.replace(/[٠-٩]/g, (digit) => String("٠١٢٣٤٥٦٧٨٩".indexOf(digit)))
|
||||
.replace(/[٬,\s]/g, "");
|
||||
const parsed = Number(normalized);
|
||||
return Number.isFinite(parsed) ? parsed : undefined;
|
||||
}
|
||||
|
||||
function formatToman(value: unknown): string | undefined {
|
||||
if (value === undefined || value === null || value === "") return undefined;
|
||||
const amount = normalizeNumber(value);
|
||||
if (amount === undefined) return asString(value);
|
||||
return `${PERSIAN_NUMBER_FORMATTER.format(amount)} تومان`;
|
||||
}
|
||||
|
||||
function firstDefined(...values: unknown[]): string | undefined {
|
||||
for (const value of values) {
|
||||
const str = asString(value);
|
||||
@@ -302,6 +333,23 @@ function resolveEvaluationReply(
|
||||
);
|
||||
}
|
||||
|
||||
function resolveEvaluationSubmittedAt(
|
||||
claim: Record<string, unknown> | null | undefined,
|
||||
reply: Record<string, unknown> | undefined,
|
||||
): unknown {
|
||||
if (reply?.submittedAt != null) return reply.submittedAt;
|
||||
|
||||
const history = Array.isArray(claim?.history) ? claim.history : [];
|
||||
const submittedEvent = [...history]
|
||||
.reverse()
|
||||
.find((event) =>
|
||||
["EXPERT_REPLY_SUBMITTED", "EXPERT_FINAL_REPLY_SUBMITTED"].includes(
|
||||
String((event as Record<string, unknown>)?.type ?? ""),
|
||||
),
|
||||
) as Record<string, unknown> | undefined;
|
||||
return submittedEvent?.timestamp;
|
||||
}
|
||||
|
||||
function insuranceValueFromCandidates(
|
||||
...values: unknown[]
|
||||
): string | undefined {
|
||||
@@ -650,7 +698,7 @@ function buildCaseTimelineSection(
|
||||
},
|
||||
{
|
||||
label: PR.evaluationRegisteredAt,
|
||||
value: formatDateTime(evaluationReply?.submittedAt),
|
||||
value: formatDateTime(resolveEvaluationSubmittedAt(claim, evaluationReply)),
|
||||
},
|
||||
]);
|
||||
}
|
||||
@@ -723,7 +771,7 @@ function buildEvaluationSection(
|
||||
},
|
||||
{
|
||||
label: PR.evaluationSubmittedAt,
|
||||
value: formatDateTime(reply?.submittedAt),
|
||||
value: formatDateTime(resolveEvaluationSubmittedAt(claim, reply)),
|
||||
},
|
||||
{
|
||||
label: PR.evaluationResponse,
|
||||
@@ -732,6 +780,66 @@ function buildEvaluationSection(
|
||||
]);
|
||||
}
|
||||
|
||||
function evaluationPartName(part: ReportRecord): string | undefined {
|
||||
const damage = part.carPartDamage;
|
||||
if (damage && typeof damage === "object" && !Array.isArray(damage)) {
|
||||
const record = damage as ReportRecord;
|
||||
return firstDefined(
|
||||
record.label_fa,
|
||||
record.name,
|
||||
record.part,
|
||||
record.label,
|
||||
part.partId != null ? `${PR.part} ${part.partId}` : undefined,
|
||||
);
|
||||
}
|
||||
return firstDefined(
|
||||
damage,
|
||||
part.partName,
|
||||
part.partId != null ? `${PR.part} ${part.partId}` : undefined,
|
||||
);
|
||||
}
|
||||
|
||||
function evaluationDaghiValue(value: unknown): string | undefined {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return asString(value);
|
||||
}
|
||||
const daghi = value as ReportRecord;
|
||||
const option = asString(daghi.option);
|
||||
const price = formatToman(daghi.price);
|
||||
return [option, price].filter(Boolean).join(" - ") || undefined;
|
||||
}
|
||||
|
||||
function buildEvaluationPartsSection(
|
||||
claim?: Record<string, unknown> | null,
|
||||
): InsurerFileReportSection | undefined {
|
||||
const reply = resolveEvaluationReply(claim);
|
||||
const parts = Array.isArray(reply?.parts)
|
||||
? (reply.parts as ReportRecord[])
|
||||
: [];
|
||||
if (!parts.length) return undefined;
|
||||
|
||||
const fields = parts.flatMap((part, index) => {
|
||||
const prefix = `${PR.part} ${PERSIAN_NUMBER_FORMATTER.format(index + 1)}`;
|
||||
return [
|
||||
{ label: `${prefix} / ${PR.partName}`, value: evaluationPartName(part) },
|
||||
{ label: `${prefix} / ${PR.damageType}`, value: asString(part.typeOfDamage) },
|
||||
{ label: `${prefix} / ${PR.partPrice}`, value: formatToman(part.price) },
|
||||
{ label: `${prefix} / ${PR.repairSalary}`, value: formatToman(part.salary) },
|
||||
{ label: `${prefix} / ${PR.totalPayment}`, value: formatToman(part.totalPayment) },
|
||||
{
|
||||
label: `${prefix} / ${PR.factorNeeded}`,
|
||||
value:
|
||||
typeof part.factorNeeded === "boolean"
|
||||
? persianStatus(part.factorNeeded)
|
||||
: undefined,
|
||||
},
|
||||
{ label: `${prefix} / ${PR.daghi}`, value: evaluationDaghiValue(part.daghi) },
|
||||
];
|
||||
});
|
||||
|
||||
return buildSection(PR.evaluationPartsSection, fields, false);
|
||||
}
|
||||
|
||||
function buildAccidentReportSection(
|
||||
blame?: Record<string, unknown> | null,
|
||||
claim?: Record<string, unknown> | null,
|
||||
@@ -773,21 +881,24 @@ function buildAccidentReportSection(
|
||||
},
|
||||
{
|
||||
label: PR.weather,
|
||||
value:
|
||||
asString(statement?.weatherCondition) ??
|
||||
asString(snapshotAccident?.weatherCondition),
|
||||
value: persianAccidentCondition(
|
||||
"weather",
|
||||
statement?.weatherCondition ?? snapshotAccident?.weatherCondition,
|
||||
),
|
||||
},
|
||||
{
|
||||
label: PR.road,
|
||||
value:
|
||||
asString(statement?.roadCondition) ??
|
||||
asString(snapshotAccident?.roadCondition),
|
||||
value: persianAccidentCondition(
|
||||
"road",
|
||||
statement?.roadCondition ?? snapshotAccident?.roadCondition,
|
||||
),
|
||||
},
|
||||
{
|
||||
label: PR.light,
|
||||
value:
|
||||
asString(statement?.lightCondition) ??
|
||||
asString(snapshotAccident?.lightCondition),
|
||||
value: persianAccidentCondition(
|
||||
"light",
|
||||
statement?.lightCondition ?? snapshotAccident?.lightCondition,
|
||||
),
|
||||
},
|
||||
{
|
||||
label: PR.blameStatus,
|
||||
@@ -910,6 +1021,7 @@ export function buildInsurerFileReport(file: {
|
||||
: undefined,
|
||||
buildFanavaranCodesSection(claim),
|
||||
buildEvaluationSection(claim),
|
||||
buildEvaluationPartsSection(claim),
|
||||
buildAccidentReportSection(blameContext, claim, damagedParty),
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user