Files
yara724api/src/claim-request-management/fanavaran-other-people.ts

253 lines
7.8 KiB
TypeScript

import { toEnglishDigits } from "src/lookups/fanavaran-last-car-policy";
import {
parseJalaliDateParts,
pickPersonBirthday,
pickPersonNationalCode,
} from "./fanavaran-driver-inquiry";
export type FanavaranLookupRow = {
Id?: unknown;
Caption?: unknown;
Name?: unknown;
IsActive?: unknown;
};
export type FanavaranOtherPeopleLookups = {
cities?: unknown;
gender?: unknown;
maritalStatus?: unknown;
ans?: unknown;
countries?: unknown;
personKind?: unknown;
};
export type FanavaranOtherPeopleSource = {
nationalCode?: unknown;
birthday?: unknown;
fullName?: unknown;
fatherName?: unknown;
mobile?: unknown;
tel?: unknown;
email?: unknown;
address?: unknown;
jobAddress?: unknown;
postalCode?: unknown;
cityName?: unknown;
gender?: unknown;
isIranian?: boolean;
naturalizedCode?: unknown;
identityNo?: unknown;
identityNoIssuPlace?: unknown;
passportNo?: unknown;
companyCode?: unknown;
economicCode?: unknown;
registerNo?: unknown;
};
export type FanavaranOtherPeoplePayload = {
NationalCode: string | null;
Name: string | null;
LastName: string | null;
FatherName: string | null;
BirthYear: number | null;
BirthMonth: number | null;
BirthDay: number | null;
ADBirthYear: null;
ADBirthMonth: null;
ADBirthDay: null;
IdentityNoIssuPlace: string | null;
PassportNo: string | null;
Address: string | null;
PostalCode: string | null;
Tel: string | null;
Mobile: string | null;
Email: string | null;
JobAddress: string | null;
EconomicCode: string | null;
NaturalizedCode: string | null;
CompanyCode: string | null;
IdentityNo: string | null;
RegisterNo: string | null;
CityId: number | null;
GenderId: number | null;
MaritalStatus: number | null;
IsIranian: number | string | null;
NationalityId: number | null;
PersonKindId: number | null;
};
const GENDER_MALE_TEXTS = ["مرد", "آقا", "male", "m"];
const GENDER_FEMALE_TEXTS = ["زن", "خانم", "female", "f"];
const ANS_YES_TEXTS = ["بله", "بلی", "yes", "1"];
const NATURAL_PERSON_TEXTS = ["حقیقی", "شخص حقیقی", "طبيعي", "natural"];
const IRAN_COUNTRY_TEXTS = ["ایران", "ايران", "iran"];
function asLookupRows(value: unknown): FanavaranLookupRow[] {
if (!Array.isArray(value)) return [];
return value.filter(
(row): row is FanavaranLookupRow =>
!!row && typeof row === "object" && !Array.isArray(row),
);
}
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;
}
function normalizeLookupText(value: unknown): string {
return toEnglishDigits(value)
.toLowerCase()
.replace(/[ي]/g, "ی")
.replace(/[ك]/g, "ک")
.replace(/[\u200c\s_\-\/]+/g, "")
.replace(/[^\p{L}\p{N}]/gu, "");
}
function lookupRowId(row: FanavaranLookupRow): number | null {
return asPositiveId(row.Id);
}
function lookupRowTexts(row: FanavaranLookupRow): string[] {
return [row.Caption, row.Name]
.filter((value): value is string => typeof value === "string")
.filter(Boolean);
}
export function pickLookupIdByCaption(
rows: unknown,
texts: unknown[],
): number | null {
const wanted = texts
.map((text) => normalizeLookupText(text))
.filter(Boolean);
if (!wanted.length) return null;
for (const row of asLookupRows(rows)) {
if (row.IsActive === 0) continue;
const rowTexts = lookupRowTexts(row).map(normalizeLookupText);
const matched = rowTexts.some((rowText) =>
wanted.some(
(want) =>
rowText === want || rowText.includes(want) || want.includes(rowText),
),
);
if (matched) return lookupRowId(row);
}
return null;
}
export function splitPersianFullName(
fullName: unknown,
): { name: string | null; lastName: string | null } {
const trimmed = String(fullName ?? "").trim().replace(/\s+/g, " ");
if (!trimmed) return { name: null, lastName: null };
const parts = trimmed.split(" ");
if (parts.length === 1) return { name: parts[0], lastName: null };
return { name: parts[0], lastName: parts.slice(1).join(" ") };
}
export function normalizeIranMobile(value: unknown): string | null {
const digits = toEnglishDigits(value).replace(/\D/g, "");
if (!digits) return null;
if (digits.length === 10 && digits.startsWith("9")) return `0${digits}`;
if (digits.length === 11 && digits.startsWith("09")) return digits;
if (digits.length === 12 && digits.startsWith("989")) {
return `0${digits.slice(2)}`;
}
return digits.length >= 8 ? digits : null;
}
export function pickFanavaranRecordId(value: unknown): number | null {
if (value == null) return null;
if (typeof value === "number" || typeof value === "string") {
return asPositiveId(value);
}
if (Array.isArray(value)) {
for (const item of value) {
const id = pickFanavaranRecordId(item);
if (id != null) return id;
}
return null;
}
if (typeof value !== "object") return null;
const record = value as Record<string, unknown>;
const direct = asPositiveId(record.Id ?? record.id);
if (direct != null) return direct;
for (const key of ["value", "Value", "data", "Data", "item", "Item"]) {
const nested = pickFanavaranRecordId(record[key]);
if (nested != null) return nested;
}
return null;
}
function emptyToNull(value: unknown): string | null {
if (value == null) return null;
const text = String(value).trim();
return text ? text : null;
}
export function buildFanavaranOtherPeoplePayload(
source: FanavaranOtherPeopleSource,
lookups: FanavaranOtherPeopleLookups = {},
): FanavaranOtherPeoplePayload | null {
const nationalCode = pickPersonNationalCode({
nationalCode: source.nationalCode,
nationalCodeOfDriver: source.nationalCode,
});
const birthday = parseJalaliDateParts(
source.birthday ?? pickPersonBirthday({ birthday: source.birthday }),
);
if (!nationalCode || !birthday) return null;
const isIranian =
source.isIranian !== false && !emptyToNull(source.naturalizedCode);
const names = splitPersianFullName(source.fullName);
const genderTexts =
source.gender === "male" || source.gender === "m"
? GENDER_MALE_TEXTS
: source.gender === "female" || source.gender === "f"
? GENDER_FEMALE_TEXTS
: [source.gender];
return {
NationalCode: nationalCode,
Name: names.name,
LastName: names.lastName,
FatherName: emptyToNull(source.fatherName),
BirthYear: birthday.year,
BirthMonth: birthday.month,
BirthDay: birthday.day,
ADBirthYear: null,
ADBirthMonth: null,
ADBirthDay: null,
IdentityNoIssuPlace: emptyToNull(source.identityNoIssuPlace),
PassportNo: emptyToNull(source.passportNo),
Address: emptyToNull(source.address),
PostalCode: emptyToNull(source.postalCode),
Tel: normalizeIranMobile(source.tel) ?? emptyToNull(source.tel),
Mobile: normalizeIranMobile(source.mobile),
Email: emptyToNull(source.email),
JobAddress: emptyToNull(source.jobAddress),
EconomicCode: emptyToNull(source.economicCode),
NaturalizedCode: emptyToNull(source.naturalizedCode),
CompanyCode: emptyToNull(source.companyCode),
IdentityNo: emptyToNull(source.identityNo),
RegisterNo: emptyToNull(source.registerNo),
CityId: pickLookupIdByCaption(lookups.cities, [source.cityName]),
GenderId: pickLookupIdByCaption(lookups.gender, genderTexts),
MaritalStatus: pickLookupIdByCaption(lookups.maritalStatus, []),
IsIranian: isIranian
? (pickLookupIdByCaption(lookups.ans, ANS_YES_TEXTS) ?? 1)
: (pickLookupIdByCaption(lookups.ans, ["خیر", "no", "0"]) ?? 0),
NationalityId: isIranian
? null
: pickLookupIdByCaption(lookups.countries, IRAN_COUNTRY_TEXTS),
PersonKindId: pickLookupIdByCaption(
lookups.personKind,
NATURAL_PERSON_TEXTS,
),
};
}