forked from Yara724/api
166 lines
5.6 KiB
TypeScript
166 lines
5.6 KiB
TypeScript
import { toEnglishDigits } from "src/lookups/fanavaran-last-car-policy";
|
|
|
|
export const FANAVARAN_INSURER_ROLE_ID = 161;
|
|
export const FANAVARAN_PLAQUE_OWNER_ROLE_ID = 163;
|
|
export const FANAVARAN_DRIVER_ROLE_ID = 166;
|
|
|
|
export type FanavaranPartyInquiryRow = {
|
|
Id?: unknown;
|
|
RoleId?: unknown;
|
|
NationalCode?: unknown;
|
|
Name?: unknown;
|
|
LastName?: unknown;
|
|
};
|
|
|
|
function asPositiveId(value: unknown): number | null {
|
|
if (value === null || value === undefined) return null;
|
|
const id = Number(value);
|
|
return Number.isFinite(id) && id > 0 ? id : null;
|
|
}
|
|
|
|
export function asPartyInquiryRows(value: unknown): FanavaranPartyInquiryRow[] {
|
|
if (Array.isArray(value)) {
|
|
return value.filter(
|
|
(row): row is FanavaranPartyInquiryRow =>
|
|
!!row && typeof row === "object" && !Array.isArray(row),
|
|
);
|
|
}
|
|
if (!value || typeof value !== "object") return [];
|
|
const record = value as Record<string, unknown>;
|
|
for (const key of ["value", "Value", "items", "Items", "data", "Data"]) {
|
|
const nested = record[key];
|
|
if (Array.isArray(nested)) return asPartyInquiryRows(nested);
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* DriverId for GEN.12 زیاندیده. Prefer insurer (161) or driver (166)
|
|
* based on driverIsInsurer, then any returned party id.
|
|
*/
|
|
export function selectFanavaranDriverId(
|
|
rows: unknown,
|
|
driverIsInsurer: boolean | undefined,
|
|
): number | null {
|
|
const parties = asPartyInquiryRows(rows);
|
|
if (parties.length === 0) return null;
|
|
|
|
const preferredRoles = driverIsInsurer
|
|
? [FANAVARAN_INSURER_ROLE_ID, FANAVARAN_DRIVER_ROLE_ID, FANAVARAN_PLAQUE_OWNER_ROLE_ID]
|
|
: [FANAVARAN_DRIVER_ROLE_ID, FANAVARAN_INSURER_ROLE_ID, FANAVARAN_PLAQUE_OWNER_ROLE_ID];
|
|
|
|
for (const roleId of preferredRoles) {
|
|
const match = parties.find((row) => asPositiveId(row.RoleId) === roleId);
|
|
if (match) return asPositiveId(match.Id);
|
|
}
|
|
|
|
return asPositiveId(parties[0].Id);
|
|
}
|
|
|
|
export function normalizeNationalCode(value: unknown): string | null {
|
|
const digits = toEnglishDigits(value).replace(/\D/g, "");
|
|
if (digits.length === 10) return digits;
|
|
if (digits.length === 8 || digits.length === 9) return digits.padStart(10, "0");
|
|
return digits.length > 0 ? digits : null;
|
|
}
|
|
|
|
export function pickPersonNationalCode(person: {
|
|
driverIsInsurer?: boolean;
|
|
nationalCodeOfDriver?: unknown;
|
|
nationalCodeOfInsurer?: unknown;
|
|
nationalCode?: unknown;
|
|
} | null | undefined): string | null {
|
|
if (!person) return null;
|
|
const driver = normalizeNationalCode(person.nationalCodeOfDriver);
|
|
const insurer = normalizeNationalCode(person.nationalCodeOfInsurer);
|
|
const generic = normalizeNationalCode(person.nationalCode);
|
|
if (person.driverIsInsurer) {
|
|
return insurer || driver || generic;
|
|
}
|
|
return driver || insurer || generic;
|
|
}
|
|
|
|
export function pickPersonBirthday(person: {
|
|
driverIsInsurer?: boolean;
|
|
driverBirthday?: unknown;
|
|
birthday?: unknown;
|
|
insurerBirthday?: unknown;
|
|
} | null | undefined): string | number | null {
|
|
if (!person) return null;
|
|
const ordered = person.driverIsInsurer
|
|
? [person.insurerBirthday, person.birthday, person.driverBirthday]
|
|
: [person.driverBirthday, person.birthday, person.insurerBirthday];
|
|
for (const value of ordered) {
|
|
if (value == null || String(value).trim() === "") continue;
|
|
if (parseJalaliDateParts(value)) return value as string | number;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function collectPersonNationalCodes(
|
|
person: {
|
|
nationalCodeOfDriver?: unknown;
|
|
nationalCodeOfInsurer?: unknown;
|
|
nationalCode?: unknown;
|
|
} | null | undefined,
|
|
): string[] {
|
|
const codes = [
|
|
normalizeNationalCode(person?.nationalCodeOfDriver),
|
|
normalizeNationalCode(person?.nationalCodeOfInsurer),
|
|
normalizeNationalCode(person?.nationalCode),
|
|
].filter((value): value is string => !!value);
|
|
return [...new Set(codes)];
|
|
}
|
|
|
|
export function collectPersonBirthdays(person: {
|
|
driverBirthday?: unknown;
|
|
birthday?: unknown;
|
|
insurerBirthday?: unknown;
|
|
} | null | undefined): Array<string | number> {
|
|
const values = [
|
|
person?.insurerBirthday,
|
|
person?.birthday,
|
|
person?.driverBirthday,
|
|
].filter((value) => value != null && String(value).trim() !== "");
|
|
const unique: Array<string | number> = [];
|
|
const seen = new Set<string>();
|
|
for (const value of values) {
|
|
const parsed = parseJalaliDateParts(value);
|
|
const key = parsed
|
|
? `${parsed.year}-${parsed.month}-${parsed.day}`
|
|
: String(value);
|
|
if (seen.has(key)) continue;
|
|
seen.add(key);
|
|
unique.push(value as string | number);
|
|
}
|
|
return unique;
|
|
}
|
|
|
|
export function parseJalaliDateParts(
|
|
birthday: unknown,
|
|
): { year: number; month: number; day: number } | null {
|
|
if (birthday == null) return null;
|
|
if (typeof birthday === "object") {
|
|
const year = Number(toEnglishDigits((birthday as any).year ?? (birthday as any).BirthYear));
|
|
const month = Number(toEnglishDigits((birthday as any).month ?? (birthday as any).BirthMonth));
|
|
const day = Number(toEnglishDigits((birthday as any).day ?? (birthday as any).BirthDay));
|
|
if (year > 0 && month > 0 && day > 0) return { year, month, day };
|
|
return null;
|
|
}
|
|
const str = toEnglishDigits(birthday).trim();
|
|
if (/^\d{8}$/.test(str)) {
|
|
const year = parseInt(str.slice(0, 4), 10);
|
|
const month = parseInt(str.slice(4, 6), 10);
|
|
const day = parseInt(str.slice(6, 8), 10);
|
|
if (!year || !month || !day) return null;
|
|
return { year, month, day };
|
|
}
|
|
const parts = str.split(/[/\-.]/);
|
|
if (parts.length < 3) return null;
|
|
const year = parseInt(parts[0], 10);
|
|
const month = parseInt(parts[1], 10);
|
|
const day = parseInt(parts[2], 10);
|
|
if (!year || !month || !day) return null;
|
|
return { year, month, day };
|
|
}
|