forked from Yara724/api
update the fanavaran which accepts unknown person too
This commit is contained in:
252
src/claim-request-management/fanavaran-other-people.ts
Normal file
252
src/claim-request-management/fanavaran-other-people.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
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,
|
||||
),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user