forked from Yara724/api
Merge pull request 'fanavaran driver and owner id (GEN..44 defauts) - culprit type id dynamic' (#343) from s.hajizadeh/yara724api:main into main
Reviewed-on: Yara724/api#343
This commit is contained in:
@@ -272,6 +272,7 @@ import {
|
||||
resolveFanavaranLicenceNo,
|
||||
resolveOwnerFromParty,
|
||||
resolvePolicyholderFromParty,
|
||||
resolveThirdPartyCulpritTypeId,
|
||||
} from "./fanavaran-party-roles";
|
||||
import {
|
||||
buildFanavaranOtherPeoplePayload,
|
||||
@@ -4294,10 +4295,10 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
`[resolveDriverFanavaranId] NO MATCH for nationalCode=${nationalCode} driverIsInsurer=${driverIsInsurer}. ` +
|
||||
`[resolveDriverFanavaranId] NO acceptable RoleId 161/166 for nationalCode=${nationalCode} driverIsInsurer=${driverIsInsurer}. ` +
|
||||
`Available entries: ${asPartyInquiryRows(response)
|
||||
.map((e) => `{Id=${e.Id}, RoleId=${e.RoleId}, Name=${e.Name} ${e.LastName}}`)
|
||||
.join("; ")}`,
|
||||
.join("; ")} — submit will register GEN.44 other-people`,
|
||||
);
|
||||
return null;
|
||||
} catch (error) {
|
||||
@@ -4308,7 +4309,7 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
/** Best-effort OwnerId from parties inquiry (no GEN.44 create). */
|
||||
/** Best-effort OwnerId from parties inquiry (RoleId 161/166 only; GEN.44 on submit). */
|
||||
private async resolveOwnerFanavaranId(
|
||||
clientKey: FanavaranClientKey,
|
||||
nationalCode: string | null | undefined,
|
||||
@@ -4327,7 +4328,20 @@ export class ClaimRequestManagementService {
|
||||
birthDay: parsed.day,
|
||||
},
|
||||
);
|
||||
return selectFanavaranOwnerId(response);
|
||||
const ownerId = selectFanavaranOwnerId(response);
|
||||
if (ownerId != null) {
|
||||
this.logger.log(
|
||||
`[resolveOwnerFanavaranId] MATCH: Id=${ownerId} for nationalCode=${nationalCode}`,
|
||||
);
|
||||
return ownerId;
|
||||
}
|
||||
this.logger.warn(
|
||||
`[resolveOwnerFanavaranId] NO acceptable RoleId 161/166 for nationalCode=${nationalCode}. ` +
|
||||
`Available: ${asPartyInquiryRows(response)
|
||||
.map((e) => `{Id=${e.Id}, RoleId=${e.RoleId}}`)
|
||||
.join("; ")} — submit will register GEN.44 other-people`,
|
||||
);
|
||||
return null;
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`[resolveOwnerFanavaranId] inquiry failed for nationalCode=${nationalCode}: ${
|
||||
@@ -4877,6 +4891,37 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
ownerFanavaranId == null &&
|
||||
input.registerMissingPerson &&
|
||||
ownerIdentity.nationalCode &&
|
||||
ownerIdentity.birthday
|
||||
) {
|
||||
const registeredOwner = await this.registerFanavaranOtherPerson({
|
||||
clientKey: input.clientKey,
|
||||
person: {
|
||||
nationalCode: ownerIdentity.nationalCode,
|
||||
nationalCodeOfDriver: ownerIdentity.nationalCode,
|
||||
birthday: ownerIdentity.birthday,
|
||||
driverBirthday: ownerIdentity.birthday,
|
||||
driverIsInsurer: false,
|
||||
fullName: (damagedParty as any)?.person?.fullName,
|
||||
phoneNumber: (damagedParty as any)?.person?.phoneNumber,
|
||||
userId: (damagedParty as any)?.person?.userId,
|
||||
},
|
||||
claimCaseId: input.claimCase?._id
|
||||
? String(input.claimCase._id)
|
||||
: undefined,
|
||||
});
|
||||
if (registeredOwner != null) {
|
||||
ownerFanavaranId = registeredOwner;
|
||||
if (otherPersonId == null) otherPersonId = registeredOwner;
|
||||
this.logger.log(
|
||||
`[buildFanavaranDamageCasePayload] OwnerId=${ownerFanavaranId} from GEN.44 other-people`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (driverFanavaranId && input.blameCase?._id && damagedParty) {
|
||||
const partyIndex = (input.blameCase.parties ?? []).findIndex(
|
||||
(p: any) => p === damagedParty ||
|
||||
@@ -5726,7 +5771,8 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
|
||||
/**
|
||||
* GEN.44: create the damaged party in Fanavaran when parties inquiry has no row.
|
||||
* GEN.44: create the damaged party in Fanavaran when parties inquiry has no
|
||||
* RoleId 161/166 row (missing entirely, or only e.g. 162 بیمهشده).
|
||||
* Failures stay best-effort — GEN.12 submit continues without DriverId.
|
||||
*/
|
||||
private async registerFanavaranOtherPerson(input: {
|
||||
@@ -5736,7 +5782,8 @@ export class ClaimRequestManagementService {
|
||||
}): Promise<number | null> {
|
||||
const nationalCode = pickPersonNationalCode(input.person);
|
||||
const birthday = pickPersonBirthday(input.person);
|
||||
if (!nationalCode || !parseJalaliDateParts(birthday)) {
|
||||
const parsedBirthday = parseJalaliDateParts(birthday);
|
||||
if (!nationalCode || !parsedBirthday) {
|
||||
this.logger.warn(
|
||||
`[registerFanavaranOtherPerson] SKIP: missing nationalCode or birthday`,
|
||||
);
|
||||
@@ -5765,12 +5812,77 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
/** Seed GEN.44 from parties inquiry when the person exists under a non-driver role. */
|
||||
let inquirySeed: {
|
||||
name?: string;
|
||||
lastName?: string;
|
||||
fatherName?: string;
|
||||
genderId?: number;
|
||||
identityNo?: string;
|
||||
} = {};
|
||||
try {
|
||||
const inquiryRows =
|
||||
await this.fanavaranLookupService.inquiryByUniqueIdentifier(
|
||||
input.clientKey,
|
||||
{
|
||||
nationalCode,
|
||||
birthYear: parsedBirthday.year,
|
||||
birthMonth: parsedBirthday.month,
|
||||
birthDay: parsedBirthday.day,
|
||||
},
|
||||
);
|
||||
const parties = asPartyInquiryRows(inquiryRows);
|
||||
const seedRow =
|
||||
parties.find(
|
||||
(row) =>
|
||||
(typeof row.Name === "string" && row.Name.trim()) ||
|
||||
(typeof row.LastName === "string" && row.LastName.trim()),
|
||||
) ?? parties[0];
|
||||
if (seedRow) {
|
||||
const roleId = Number(seedRow.RoleId);
|
||||
this.logger.log(
|
||||
`[registerFanavaranOtherPerson] inquiry seed Id=${seedRow.Id} RoleId=${roleId} — creating GEN.44 سایر (adds RoleId 166 entry; existing roles stay)`,
|
||||
);
|
||||
inquirySeed = {
|
||||
name:
|
||||
typeof seedRow.Name === "string" ? seedRow.Name : undefined,
|
||||
lastName:
|
||||
typeof seedRow.LastName === "string"
|
||||
? seedRow.LastName
|
||||
: undefined,
|
||||
fatherName:
|
||||
typeof seedRow.FatherName === "string"
|
||||
? seedRow.FatherName
|
||||
: undefined,
|
||||
genderId: (() => {
|
||||
const g = Number(seedRow.GenderId);
|
||||
return Number.isFinite(g) && g > 0 ? g : undefined;
|
||||
})(),
|
||||
identityNo:
|
||||
typeof seedRow.IdentityNo === "string"
|
||||
? seedRow.IdentityNo
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`[registerFanavaranOtherPerson] pre-create inquiry failed (continuing with local data): ${
|
||||
error instanceof Error ? error.message : error
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
const lookups = await this.loadFanavaranOtherPeopleLookups(input.clientKey);
|
||||
const payload = buildFanavaranOtherPeoplePayload(
|
||||
{
|
||||
nationalCode,
|
||||
birthday,
|
||||
fullName: input.person?.fullName ?? user?.fullName,
|
||||
name: inquirySeed.name,
|
||||
lastName: inquirySeed.lastName,
|
||||
fatherName: inquirySeed.fatherName,
|
||||
identityNo: inquirySeed.identityNo,
|
||||
genderId: inquirySeed.genderId,
|
||||
mobile: input.person?.phoneNumber ?? user?.mobile,
|
||||
address: user?.address,
|
||||
cityName: user?.city,
|
||||
@@ -6203,7 +6315,9 @@ export class ClaimRequestManagementService {
|
||||
},
|
||||
});
|
||||
|
||||
// GEN.03 CulpritLicence*: guilty-party DRIVER for THIRD_PARTY, FIRST-party DRIVER for CAR_BODY.
|
||||
// GEN.03 CulpritLicence* + CulpritTypeId: guilty-party DRIVER for THIRD_PARTY,
|
||||
// FIRST-party DRIVER for CAR_BODY. CulpritTypeId uses accident-culprit-type
|
||||
// (337 بیمهگذار / 338 راننده غير از بيمه گذار) — hull remaps separately.
|
||||
{
|
||||
const culpritParty =
|
||||
blameCase.type === BlameRequestType.CAR_BODY
|
||||
@@ -6226,6 +6340,10 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
payload.CulpritLicenceIssuDate =
|
||||
resolveFanavaranLicenceIssuDate(culpritDriver);
|
||||
if (blameCase.type !== BlameRequestType.CAR_BODY) {
|
||||
payload.CulpritTypeId =
|
||||
resolveThirdPartyCulpritTypeId(culpritParty as any);
|
||||
}
|
||||
}
|
||||
|
||||
const carBodyAccidentTime = (
|
||||
@@ -6445,7 +6563,7 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
if (payload.DriverId == null) {
|
||||
warnings.push(
|
||||
"Damaged party is not in Fanavaran yet; submit will register them via other-people (GEN.44).",
|
||||
"Damaged party has no Fanavaran RoleId 161/166 yet; submit will register them via other-people (GEN.44).",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
pickPersonBirthday,
|
||||
pickPersonNationalCode,
|
||||
selectFanavaranDriverId,
|
||||
selectFanavaranOwnerId,
|
||||
} from "./fanavaran-driver-inquiry";
|
||||
|
||||
describe("selectFanavaranDriverId", () => {
|
||||
@@ -21,10 +22,32 @@ describe("selectFanavaranDriverId", () => {
|
||||
expect(selectFanavaranDriverId(rows, false)).toBe(20);
|
||||
});
|
||||
|
||||
it("uses the other role when the preferred role is missing", () => {
|
||||
it("falls back to 166 when preferred 161 is missing", () => {
|
||||
expect(selectFanavaranDriverId([{ Id: 20, RoleId: 166 }], true)).toBe(20);
|
||||
});
|
||||
|
||||
it("returns null for RoleId 162 (بیمهشده) — GEN.44 required", () => {
|
||||
expect(
|
||||
selectFanavaranDriverId(
|
||||
[
|
||||
{
|
||||
Id: 2390312,
|
||||
RoleId: 162,
|
||||
Name: "محمدعلي",
|
||||
LastName: "موسوي",
|
||||
},
|
||||
],
|
||||
false,
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("does not fall back to RoleId 163 for DriverId", () => {
|
||||
expect(
|
||||
selectFanavaranDriverId([{ Id: 99, RoleId: 163 }], false),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("picks 4773521 from a real Fanavaran unique-identifier response", () => {
|
||||
expect(
|
||||
selectFanavaranDriverId(
|
||||
@@ -39,6 +62,19 @@ describe("selectFanavaranDriverId", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("selectFanavaranOwnerId", () => {
|
||||
it("accepts only RoleId 161 or 166", () => {
|
||||
expect(
|
||||
selectFanavaranOwnerId([
|
||||
{ Id: 1, RoleId: 162 },
|
||||
{ Id: 2, RoleId: 163 },
|
||||
]),
|
||||
).toBeNull();
|
||||
expect(selectFanavaranOwnerId([{ Id: 10, RoleId: 161 }])).toBe(10);
|
||||
expect(selectFanavaranOwnerId([{ Id: 20, RoleId: 166 }])).toBe(20);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pickPersonNationalCode / birthday", () => {
|
||||
it("uses insurer national code when driverIsInsurer", () => {
|
||||
expect(
|
||||
|
||||
@@ -10,6 +10,9 @@ export type FanavaranPartyInquiryRow = {
|
||||
NationalCode?: unknown;
|
||||
Name?: unknown;
|
||||
LastName?: unknown;
|
||||
FatherName?: unknown;
|
||||
GenderId?: unknown;
|
||||
IdentityNo?: unknown;
|
||||
};
|
||||
|
||||
function asPositiveId(value: unknown): number | null {
|
||||
@@ -34,9 +37,25 @@ export function asPartyInquiryRows(value: unknown): FanavaranPartyInquiryRow[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** GEN.12 DriverId is only accepted for بیمهگذار (161) or سایر (166). */
|
||||
export const FANAVARAN_DRIVER_ACCEPTED_ROLE_IDS = [
|
||||
FANAVARAN_INSURER_ROLE_ID,
|
||||
FANAVARAN_DRIVER_ROLE_ID,
|
||||
] as const;
|
||||
|
||||
export function isAcceptableFanavaranDriverRole(
|
||||
roleId: unknown,
|
||||
): boolean {
|
||||
const id = asPositiveId(roleId);
|
||||
return (
|
||||
id === FANAVARAN_INSURER_ROLE_ID || id === FANAVARAN_DRIVER_ROLE_ID
|
||||
);
|
||||
}
|
||||
|
||||
function selectFanavaranIdByRoles(
|
||||
rows: unknown,
|
||||
preferredRoles: number[],
|
||||
options?: { allowFallbackToFirst?: boolean },
|
||||
): number | null {
|
||||
const parties = asPartyInquiryRows(rows);
|
||||
if (parties.length === 0) return null;
|
||||
@@ -46,38 +65,38 @@ function selectFanavaranIdByRoles(
|
||||
if (match) return asPositiveId(match.Id);
|
||||
}
|
||||
|
||||
if (options?.allowFallbackToFirst === false) return null;
|
||||
return asPositiveId(parties[0].Id);
|
||||
}
|
||||
|
||||
/**
|
||||
* DriverId for GEN.12 زیاندیده. Prefer insurer (161) or driver (166)
|
||||
* based on driverIsInsurer, then any returned party id.
|
||||
* DriverId for GEN.12 زیاندیده.
|
||||
* Only RoleId 161 (بیمهگذار) or 166 (سایر) are accepted by Fanavaran.
|
||||
* Other roles (e.g. 162 بیمهشده) must go through GEN.44 other-people first
|
||||
* (GEN.44 adds a RoleId-166 entry; it does not replace existing role rows).
|
||||
*/
|
||||
export function selectFanavaranDriverId(
|
||||
rows: unknown,
|
||||
driverIsInsurer: boolean | undefined,
|
||||
): number | 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,
|
||||
];
|
||||
return selectFanavaranIdByRoles(rows, preferredRoles);
|
||||
? [FANAVARAN_INSURER_ROLE_ID, FANAVARAN_DRIVER_ROLE_ID]
|
||||
: [FANAVARAN_DRIVER_ROLE_ID, FANAVARAN_INSURER_ROLE_ID];
|
||||
return selectFanavaranIdByRoles(rows, preferredRoles, {
|
||||
allowFallbackToFirst: false,
|
||||
});
|
||||
}
|
||||
|
||||
/** OwnerId: prefer plaque-owner role (163), then insurer / driver. */
|
||||
/**
|
||||
* OwnerId for GEN.12: same accepted roles as DriverId (161 / 166 only).
|
||||
* Prefer بیمهگذار then سایر. RoleId 162/163/… → null → GEN.44 on submit.
|
||||
*/
|
||||
export function selectFanavaranOwnerId(rows: unknown): number | null {
|
||||
return selectFanavaranIdByRoles(rows, [
|
||||
FANAVARAN_PLAQUE_OWNER_ROLE_ID,
|
||||
FANAVARAN_INSURER_ROLE_ID,
|
||||
FANAVARAN_DRIVER_ROLE_ID,
|
||||
]);
|
||||
return selectFanavaranIdByRoles(
|
||||
rows,
|
||||
[FANAVARAN_INSURER_ROLE_ID, FANAVARAN_DRIVER_ROLE_ID],
|
||||
{ allowFallbackToFirst: false },
|
||||
);
|
||||
}
|
||||
|
||||
export function normalizeNationalCode(value: unknown): string | null {
|
||||
|
||||
@@ -49,6 +49,29 @@ describe("fanavaran other people (GEN.44)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("defaults CityId=9131 and PersonKindId=46 when lookups miss", () => {
|
||||
const payload = buildFanavaranOtherPeoplePayload({
|
||||
nationalCode: "2002166323",
|
||||
birthday: { year: 1353, month: 2, day: 15 },
|
||||
name: "محمدعلي",
|
||||
lastName: "موسوي",
|
||||
fatherName: "حسن",
|
||||
identityNo: "1205",
|
||||
genderId: 26,
|
||||
});
|
||||
|
||||
expect(payload).toMatchObject({
|
||||
NationalCode: "2002166323",
|
||||
CityId: 9131,
|
||||
PersonKindId: 46,
|
||||
GenderId: 26,
|
||||
Name: "محمدعلي",
|
||||
LastName: "موسوي",
|
||||
FatherName: "حسن",
|
||||
IdentityNo: "1205",
|
||||
});
|
||||
});
|
||||
|
||||
it("returns null when national code or birthday is missing", () => {
|
||||
expect(
|
||||
buildFanavaranOtherPeoplePayload({
|
||||
|
||||
@@ -25,6 +25,9 @@ export type FanavaranOtherPeopleSource = {
|
||||
nationalCode?: unknown;
|
||||
birthday?: unknown;
|
||||
fullName?: unknown;
|
||||
/** Prefer these over splitting fullName when inquiry already returned them. */
|
||||
name?: unknown;
|
||||
lastName?: unknown;
|
||||
fatherName?: unknown;
|
||||
mobile?: unknown;
|
||||
tel?: unknown;
|
||||
@@ -33,7 +36,13 @@ export type FanavaranOtherPeopleSource = {
|
||||
jobAddress?: unknown;
|
||||
postalCode?: unknown;
|
||||
cityName?: unknown;
|
||||
/** Direct Fanavaran CityId when known; else lookup / default 9131. */
|
||||
cityId?: unknown;
|
||||
gender?: unknown;
|
||||
/** Direct Fanavaran GenderId from parties inquiry when available. */
|
||||
genderId?: unknown;
|
||||
/** Direct Fanavaran PersonKindId; else lookup / default 46 (حقیقی). */
|
||||
personKindId?: unknown;
|
||||
isIranian?: boolean;
|
||||
naturalizedCode?: unknown;
|
||||
identityNo?: unknown;
|
||||
@@ -82,6 +91,10 @@ const ANS_YES_TEXTS = ["بله", "بلی", "yes", "1"];
|
||||
const NATURAL_PERSON_TEXTS = ["حقیقی", "شخص حقیقی", "طبيعي", "natural"];
|
||||
const IRAN_COUNTRY_TEXTS = ["ایران", "ايران", "iran"];
|
||||
|
||||
/** Proven Parsian GEN.44 defaults when lookup / city name is missing. */
|
||||
export const FANAVARAN_OTHER_PEOPLE_DEFAULT_CITY_ID = 9131;
|
||||
export const FANAVARAN_OTHER_PEOPLE_DEFAULT_PERSON_KIND_ID = 46;
|
||||
|
||||
function asLookupRows(value: unknown): FanavaranLookupRow[] {
|
||||
if (!Array.isArray(value)) return [];
|
||||
return value.filter(
|
||||
@@ -213,8 +226,8 @@ export function buildFanavaranOtherPeoplePayload(
|
||||
|
||||
return {
|
||||
NationalCode: nationalCode,
|
||||
Name: names.name,
|
||||
LastName: names.lastName,
|
||||
Name: emptyToNull(source.name) ?? names.name,
|
||||
LastName: emptyToNull(source.lastName) ?? names.lastName,
|
||||
FatherName: emptyToNull(source.fatherName),
|
||||
BirthYear: birthday.year,
|
||||
BirthMonth: birthday.month,
|
||||
@@ -235,8 +248,13 @@ export function buildFanavaranOtherPeoplePayload(
|
||||
CompanyCode: emptyToNull(source.companyCode),
|
||||
IdentityNo: emptyToNull(source.identityNo),
|
||||
RegisterNo: emptyToNull(source.registerNo),
|
||||
CityId: pickLookupIdByCaption(lookups.cities, [source.cityName]),
|
||||
GenderId: pickLookupIdByCaption(lookups.gender, genderTexts),
|
||||
CityId:
|
||||
asPositiveId(source.cityId) ??
|
||||
pickLookupIdByCaption(lookups.cities, [source.cityName]) ??
|
||||
FANAVARAN_OTHER_PEOPLE_DEFAULT_CITY_ID,
|
||||
GenderId:
|
||||
asPositiveId(source.genderId) ??
|
||||
pickLookupIdByCaption(lookups.gender, genderTexts),
|
||||
MaritalStatus: pickLookupIdByCaption(lookups.maritalStatus, []),
|
||||
IsIranian: isIranian
|
||||
? (pickLookupIdByCaption(lookups.ans, ANS_YES_TEXTS) ?? 1)
|
||||
@@ -244,9 +262,9 @@ export function buildFanavaranOtherPeoplePayload(
|
||||
NationalityId: isIranian
|
||||
? null
|
||||
: pickLookupIdByCaption(lookups.countries, IRAN_COUNTRY_TEXTS),
|
||||
PersonKindId: pickLookupIdByCaption(
|
||||
lookups.personKind,
|
||||
NATURAL_PERSON_TEXTS,
|
||||
),
|
||||
PersonKindId:
|
||||
asPositiveId(source.personKindId) ??
|
||||
pickLookupIdByCaption(lookups.personKind, NATURAL_PERSON_TEXTS) ??
|
||||
FANAVARAN_OTHER_PEOPLE_DEFAULT_PERSON_KIND_ID,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { InquiryParticipantRole } from "src/common/dto/inquiry-participants.dto";
|
||||
import {
|
||||
FANAVARAN_CULPRIT_TYPE_DRIVER_NOT_INSURER,
|
||||
FANAVARAN_CULPRIT_TYPE_INSURER,
|
||||
FANAVARAN_DUMMY_LICENCE_ISSU_DATE,
|
||||
formatFanavaranLicenceIssuDate,
|
||||
resolveDriverFromParty,
|
||||
@@ -8,6 +10,7 @@ import {
|
||||
resolveFanavaranLicenceNo,
|
||||
resolveOwnerFromParty,
|
||||
resolvePolicyholderFromParty,
|
||||
resolveThirdPartyCulpritTypeId,
|
||||
} from "./fanavaran-party-roles";
|
||||
|
||||
describe("fanavaran-party-roles", () => {
|
||||
@@ -105,6 +108,31 @@ describe("fanavaran-party-roles", () => {
|
||||
).toBe("0080086519");
|
||||
});
|
||||
|
||||
it("maps CulpritTypeId 338 when guilty driver ≠ insurer", () => {
|
||||
expect(resolveThirdPartyCulpritTypeId(partyWithDistinctRoles)).toBe(
|
||||
FANAVARAN_CULPRIT_TYPE_DRIVER_NOT_INSURER,
|
||||
);
|
||||
});
|
||||
|
||||
it("maps CulpritTypeId 337 when guilty driver is the insurer", () => {
|
||||
expect(
|
||||
resolveThirdPartyCulpritTypeId({
|
||||
participants: [
|
||||
{
|
||||
participantId: "SAME",
|
||||
nationalCode: "0080086519",
|
||||
birthday: "1364/06/28",
|
||||
},
|
||||
],
|
||||
participantRoles: {
|
||||
driver: "SAME",
|
||||
thirdPartyPolicyholder: "SAME",
|
||||
},
|
||||
person: { driverIsInsurer: true },
|
||||
}),
|
||||
).toBe(FANAVARAN_CULPRIT_TYPE_INSURER);
|
||||
});
|
||||
|
||||
it("formats compact Jalali driverLicenseDate", () => {
|
||||
expect(formatFanavaranLicenceIssuDate(13980601)).toBe("1398/06/01");
|
||||
});
|
||||
|
||||
@@ -201,6 +201,31 @@ export function resolveDriverIsOwner(party: PartyLike | null | undefined): boole
|
||||
return party?.person?.driverIsInsurer === true;
|
||||
}
|
||||
|
||||
/** Lookup: `accident-culprit-type` — بیمهگذار */
|
||||
export const FANAVARAN_CULPRIT_TYPE_INSURER = 337;
|
||||
/** Lookup: `accident-culprit-type` — راننده غير از بيمه گذار */
|
||||
export const FANAVARAN_CULPRIT_TYPE_DRIVER_NOT_INSURER = 338;
|
||||
|
||||
/**
|
||||
* GEN.03 ثالث `CulpritTypeId` from whether the guilty party's driver is the insurer.
|
||||
* Never uses 728 (نا معلوم).
|
||||
*/
|
||||
export function resolveThirdPartyCulpritTypeId(
|
||||
party: PartyLike | null | undefined,
|
||||
): number {
|
||||
const driver = resolveDriverFromParty(party);
|
||||
const insurer = resolvePolicyholderFromParty(party, "third-party");
|
||||
if (driver.nationalCode && insurer.nationalCode) {
|
||||
return driver.nationalCode === insurer.nationalCode
|
||||
? FANAVARAN_CULPRIT_TYPE_INSURER
|
||||
: FANAVARAN_CULPRIT_TYPE_DRIVER_NOT_INSURER;
|
||||
}
|
||||
if (party?.person?.driverIsInsurer === false) {
|
||||
return FANAVARAN_CULPRIT_TYPE_DRIVER_NOT_INSURER;
|
||||
}
|
||||
return FANAVARAN_CULPRIT_TYPE_INSURER;
|
||||
}
|
||||
|
||||
/** Licence number for Fanavaran; never empty — uses `dummy` when user value is missing. */
|
||||
export function resolveFanavaranLicenceNo(
|
||||
identity: Pick<FanavaranRoleIdentity, "licenseNo">,
|
||||
|
||||
Reference in New Issue
Block a user