forked from Yara724/api
253 lines
7.8 KiB
TypeScript
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,
|
|
),
|
|
};
|
|
}
|