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 | 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[1] | undefined; const first = (blame?.parties ?? []).find( (row) => (row as { role?: string })?.role === "FIRST", ) ?? party; const { mapped } = fanavaranPartyInquirySources( "car-body", first as Parameters[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 | 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[]; }): Record { 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 { 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, 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; 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)); }