forked from Yara724/api
207 lines
6.5 KiB
TypeScript
207 lines
6.5 KiB
TypeScript
import { parseFanavaranId } from "src/lookups/fanavaran-last-car-policy";
|
|
import {
|
|
fanavaranPartyInquirySources,
|
|
type FanavaranClaimProduct,
|
|
} from "./fanavaran-claim-product";
|
|
|
|
export type FanavaranHullVehicleIdentity = {
|
|
motorNo: string | null;
|
|
chassisNo: string | null;
|
|
vin: string | null;
|
|
plaqueNo: string | null;
|
|
plaqueSerial: string | null;
|
|
builtYear: number | null;
|
|
};
|
|
|
|
export function mergeHullVehicleIdentityFromFanavaranVehicle(
|
|
base: FanavaranHullVehicleIdentity,
|
|
vehicle: Record<string, unknown> | null | undefined,
|
|
): FanavaranHullVehicleIdentity {
|
|
if (!vehicle) return base;
|
|
const readText = (key: string, fallback: string | null) => {
|
|
const raw = vehicle[key];
|
|
if (raw == null || String(raw).trim() === "") return fallback;
|
|
return String(raw).trim();
|
|
};
|
|
return {
|
|
motorNo: readText("MotorNo", base.motorNo),
|
|
chassisNo: readText("ChassisNo", base.chassisNo),
|
|
vin: readText("VIN", base.vin),
|
|
plaqueNo: readText("PlaqueNo", base.plaqueNo),
|
|
plaqueSerial: readText("PlaqueSerial", base.plaqueSerial),
|
|
builtYear:
|
|
parseFanavaranId(vehicle.BuiltYear) ??
|
|
parseFanavaranId(vehicle.builtYear) ??
|
|
base.builtYear,
|
|
};
|
|
}
|
|
|
|
export function pickHullVehicleIdentity(
|
|
blame?: { parties?: unknown[] } | null,
|
|
): FanavaranHullVehicleIdentity {
|
|
const party = (blame?.parties ?? [])[0] as
|
|
| Parameters<typeof fanavaranPartyInquirySources>[1]
|
|
| undefined;
|
|
const first =
|
|
(blame?.parties ?? []).find(
|
|
(row) => (row as { role?: string })?.role === "FIRST",
|
|
) ?? party;
|
|
const { mapped } = fanavaranPartyInquirySources(
|
|
"car-body",
|
|
first as Parameters<typeof fanavaranPartyInquirySources>[1],
|
|
);
|
|
const left = text(mapped.plk1 ?? mapped.Plk1);
|
|
const letter = text(mapped.plk2 ?? mapped.Plk2);
|
|
const right = text(mapped.plk3 ?? mapped.Plk3);
|
|
const serial = text(mapped.plksrl ?? mapped.PlkSrl);
|
|
const plaqueNo = [left, letter, right].filter(Boolean).join("") || null;
|
|
return {
|
|
motorNo: text(mapped.MtrNum),
|
|
chassisNo: text(mapped.ShsNum),
|
|
vin: text(mapped.VIN),
|
|
plaqueNo,
|
|
plaqueSerial: serial,
|
|
builtYear: parseFanavaranId(mapped.PrdDte),
|
|
};
|
|
}
|
|
|
|
function text(value: unknown): string | null {
|
|
if (value == null) return null;
|
|
const next = String(value).trim();
|
|
return next ? next : null;
|
|
}
|
|
|
|
export {
|
|
FANAVARAN_DEFAULT_HULL_DMG_COST_KIND_ID,
|
|
FANAVARAN_DEFAULT_HULL_DMG_KIND_ID,
|
|
FANAVARAN_HULL_DMG_COST_KIND_CAPTION,
|
|
FANAVARAN_HULL_DMG_KIND_CAPTION,
|
|
} from "./fanavaran-hull-expertise-lookups";
|
|
|
|
/** GEN.06 VehicleCurrentValue from GET car/vehicle-hull-policies/{PolicyId} → VehicleValue. */
|
|
export function vehicleCurrentValueFromHullPolicyRecord(
|
|
policy: Record<string, unknown> | null | undefined,
|
|
): number | null {
|
|
if (!policy) return null;
|
|
const raw =
|
|
policy.VehicleValue ?? policy.vehicleValue ?? policy.VehicleCurrentValue;
|
|
const n = typeof raw === "number" ? raw : Number(raw);
|
|
return Number.isFinite(n) && n > 0 ? n : null;
|
|
}
|
|
|
|
export function toFanavaranHullExpertisePayload(input: {
|
|
claimExpertId: number;
|
|
dmgAssessmentDate: string;
|
|
inspectionTime: string;
|
|
wage: number;
|
|
componentReplacementCost: number;
|
|
wasteValue: number;
|
|
dropAmount: number;
|
|
vehicleCurrentValue: number | null;
|
|
vehicle: FanavaranHullVehicleIdentity;
|
|
colorId?: number | null;
|
|
repairDuration?: number | null;
|
|
dmgSections: Record<string, unknown>[];
|
|
}): Record<string, unknown> {
|
|
return {
|
|
ClaimExpertId: input.claimExpertId,
|
|
DmgAssessmentDate: input.dmgAssessmentDate,
|
|
InspectionTime: input.inspectionTime,
|
|
MotorNo: input.vehicle.motorNo,
|
|
ChassisNo: input.vehicle.chassisNo,
|
|
BuiltYear: input.vehicle.builtYear,
|
|
VIN: input.vehicle.vin,
|
|
PlaqueNo: input.vehicle.plaqueNo,
|
|
PlaqueSerial: input.vehicle.plaqueSerial,
|
|
Wage: input.wage,
|
|
ComponentReplacementCost: input.componentReplacementCost,
|
|
WasteValue: input.wasteValue,
|
|
CarryAndRescueCost: null,
|
|
RepairDuration: input.repairDuration ?? null,
|
|
VehicleCurrentValue: input.vehicleCurrentValue,
|
|
WreckHighestValue: null,
|
|
InspectionDeduction: null,
|
|
DmgAndWasteDesc: null,
|
|
WentDistanceByExpert: null,
|
|
IsDestruction: null,
|
|
DropAmount: input.dropAmount,
|
|
ColorId: input.colorId ?? null,
|
|
PlaqueDesignId: null,
|
|
PlaqueCityId: null,
|
|
AccidentPercent: null,
|
|
TheftCases: [],
|
|
DmgSections: input.dmgSections,
|
|
};
|
|
}
|
|
|
|
export function toFanavaranHullExpertiseDmgSection(input: {
|
|
partId?: unknown;
|
|
desc: string;
|
|
wasteValue: number;
|
|
amount: number;
|
|
dmgKindId: number;
|
|
dmgCostKindId: number;
|
|
vehicleHullAccessoryId: number | null;
|
|
}): Record<string, unknown> {
|
|
return {
|
|
Count: 1,
|
|
Desc: input.desc,
|
|
WasteValue: input.wasteValue,
|
|
AccessoryKindId: parseFanavaranId(input.partId),
|
|
DmgKindId: input.dmgKindId,
|
|
VehicleHullAccessoryId: input.vehicleHullAccessoryId,
|
|
DmgSectionCosts: [
|
|
{
|
|
Caption: input.desc,
|
|
Amount: input.amount,
|
|
DmgCostKindId: input.dmgCostKindId,
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function hullExpertiseAssertFields(
|
|
product: FanavaranClaimProduct,
|
|
): { requireDmgCaseId: boolean; requireThirdPartyLookups: boolean } {
|
|
if (product === "car-body") {
|
|
return { requireDmgCaseId: false, requireThirdPartyLookups: false };
|
|
}
|
|
return { requireDmgCaseId: true, requireThirdPartyLookups: true };
|
|
}
|
|
|
|
export function collectFanavaranExpertiseReadinessWarnings(
|
|
payload: Record<string, unknown>,
|
|
options?: { requireDmgCaseId?: boolean; requireThirdPartyLookups?: boolean },
|
|
): string[] {
|
|
const warnings: string[] = [];
|
|
const sections = Array.isArray(payload.DmgSections)
|
|
? payload.DmgSections
|
|
: [];
|
|
const thirdPartyLookups = options?.requireThirdPartyLookups !== false;
|
|
if (options?.requireDmgCaseId !== false && !payload.DmgCaseId) {
|
|
warnings.push("DmgCaseId is required.");
|
|
}
|
|
if (thirdPartyLookups) {
|
|
if (!payload.InspectionPlaceId) {
|
|
warnings.push("InspectionPlaceId is required.");
|
|
}
|
|
if (!payload.DropAmountStatus) {
|
|
warnings.push("DropAmountStatus is required.");
|
|
}
|
|
}
|
|
if (!sections.length) {
|
|
warnings.push("At least one DmgSections row is required.");
|
|
}
|
|
for (const [index, section] of sections.entries()) {
|
|
const row = section as Record<string, unknown>;
|
|
if (!thirdPartyLookups) continue;
|
|
if (!row.DmgSectionId) {
|
|
warnings.push(`DmgSections[${index}].DmgSectionId is required.`);
|
|
}
|
|
if (!row.AccidentLevel) {
|
|
warnings.push(`DmgSections[${index}].AccidentLevel is required.`);
|
|
}
|
|
}
|
|
return Array.from(new Set(warnings));
|
|
}
|