forked from Yara724/api
Merge upstream API changes and resolve Fanavaran role mapping
This commit is contained in:
@@ -170,6 +170,7 @@ import { RoleEnum } from "src/Types&Enums/role.enum";
|
||||
import { PartyRole } from "src/request-management/entities/schema/partyRole.enum";
|
||||
import { InquiryParticipantRole } from "src/common/dto/inquiry-participants.dto";
|
||||
import { participantForStoredPartyRole } from "src/request-management/inquiry-participant-resolver";
|
||||
import type { InquiryParticipantRoleAssignments } from "src/request-management/inquiry-participant-resolver";
|
||||
import { UserRatingDto } from "./dto/user-rating.dto";
|
||||
import {
|
||||
canFinalizeExpertResend,
|
||||
@@ -262,7 +263,16 @@ import {
|
||||
pickPersonBirthday,
|
||||
pickPersonNationalCode,
|
||||
selectFanavaranDriverId,
|
||||
selectFanavaranOwnerId,
|
||||
} from "./fanavaran-driver-inquiry";
|
||||
import {
|
||||
resolveDriverFromParty,
|
||||
resolveDriverIsOwner,
|
||||
resolveFanavaranLicenceIssuDate,
|
||||
resolveFanavaranLicenceNo,
|
||||
resolveOwnerFromParty,
|
||||
resolvePolicyholderFromParty,
|
||||
} from "./fanavaran-party-roles";
|
||||
import {
|
||||
buildFanavaranOtherPeoplePayload,
|
||||
pickFanavaranRecordId,
|
||||
@@ -3676,23 +3686,23 @@ export class ClaimRequestManagementService {
|
||||
/**
|
||||
* Resolve licence number to send to Fanavaran.
|
||||
* Preference order:
|
||||
* - use the first non-empty value from DB (driverLicense/insurerLicense)
|
||||
* - else use the configured 10-digit dummy
|
||||
* - driver participant / person.driverLicense (and insurerLicense as legacy)
|
||||
* - else the configured 10-digit dummy
|
||||
*/
|
||||
private resolveFanavaranLicenceNoFromParty(input: {
|
||||
driverIsInsurer?: boolean;
|
||||
driverLicense?: unknown;
|
||||
insurerLicense?: unknown;
|
||||
/** Optional already-resolved digits from participants. */
|
||||
resolvedLicenseNo?: string | null;
|
||||
}): string {
|
||||
const { driverIsInsurer, driverLicense, insurerLicense } = input;
|
||||
const fromResolved = this.extractNonEmptyLicenceDigits(
|
||||
input.resolvedLicenseNo,
|
||||
);
|
||||
if (fromResolved) return fromResolved;
|
||||
|
||||
// When driverIsInsurer === true, UI usually mirrors insurer/driver values,
|
||||
// but DB can still miss one of the two fields — prefer both.
|
||||
const candidates = driverIsInsurer
|
||||
? [driverLicense, insurerLicense]
|
||||
: [driverLicense, insurerLicense];
|
||||
|
||||
for (const c of candidates) {
|
||||
const { driverLicense, insurerLicense } = input;
|
||||
for (const c of [driverLicense, insurerLicense]) {
|
||||
const digits = this.extractNonEmptyLicenceDigits(c);
|
||||
if (digits) return digits;
|
||||
}
|
||||
@@ -4298,6 +4308,36 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
/** Best-effort OwnerId from parties inquiry (no GEN.44 create). */
|
||||
private async resolveOwnerFanavaranId(
|
||||
clientKey: FanavaranClientKey,
|
||||
nationalCode: string | null | undefined,
|
||||
birthday: string | number | null | undefined,
|
||||
): Promise<number | null> {
|
||||
if (!nationalCode) return null;
|
||||
const parsed = this.parseJalaliBirthday(birthday);
|
||||
if (!parsed) return null;
|
||||
try {
|
||||
const response = await this.fanavaranLookupService.inquiryByUniqueIdentifier(
|
||||
clientKey,
|
||||
{
|
||||
nationalCode,
|
||||
birthYear: parsed.year,
|
||||
birthMonth: parsed.month,
|
||||
birthDay: parsed.day,
|
||||
},
|
||||
);
|
||||
return selectFanavaranOwnerId(response);
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`[resolveOwnerFanavaranId] inquiry failed for nationalCode=${nationalCode}: ${
|
||||
error instanceof Error ? error.message : error
|
||||
}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** GEN.03 hull: TotalPremium + parties inquiry (AccidentCulpritId) before hull field whitelist. */
|
||||
private async enrichCarBodyHullBaseClaimPayload(input: {
|
||||
clientKey: FanavaranClientKey;
|
||||
@@ -4357,13 +4397,14 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
| undefined;
|
||||
|
||||
const driverIdentity = resolveDriverFromParty(input.firstParty as any);
|
||||
const nationalCode =
|
||||
driverIdentity.nationalCode ??
|
||||
pickPersonNationalCode(person) ??
|
||||
pickCarBodyPolicyNationalCode(
|
||||
input.blameCase as { parties?: unknown[] },
|
||||
);
|
||||
const birthday = pickPersonBirthday(person);
|
||||
const driverIsInsurer = person?.driverIsInsurer ?? true;
|
||||
const birthday = driverIdentity.birthday ?? pickPersonBirthday(person);
|
||||
|
||||
let accidentCulpritId: number | null = null;
|
||||
if (nationalCode && birthday) {
|
||||
@@ -4371,7 +4412,7 @@ export class ClaimRequestManagementService {
|
||||
input.clientKey,
|
||||
nationalCode,
|
||||
birthday,
|
||||
driverIsInsurer,
|
||||
false,
|
||||
);
|
||||
}
|
||||
if (accidentCulpritId == null) {
|
||||
@@ -4386,6 +4427,13 @@ export class ClaimRequestManagementService {
|
||||
input.payload.AccidentCulpritId = accidentCulpritId;
|
||||
}
|
||||
|
||||
input.payload.CulpritLicenceNo = resolveFanavaranLicenceNo(
|
||||
driverIdentity,
|
||||
FANAVARAN_DUMMY_LICENCE_NO,
|
||||
);
|
||||
input.payload.CulpritLicenceIssuDate =
|
||||
resolveFanavaranLicenceIssuDate(driverIdentity);
|
||||
|
||||
input.payload.CustomerFaultPercent =
|
||||
FANAVARAN_DEFAULT_HULL_CUSTOMER_FAULT_PERCENT;
|
||||
|
||||
@@ -4619,6 +4667,9 @@ export class ClaimRequestManagementService {
|
||||
const person = damagedParty?.person ?? {};
|
||||
const vehicle = damagedParty?.vehicle ?? {};
|
||||
const insurance = damagedParty?.insurance ?? {};
|
||||
const driverIdentity = resolveDriverFromParty(damagedParty);
|
||||
const ownerIdentity = resolveOwnerFromParty(damagedParty);
|
||||
const driverIsOwner = resolveDriverIsOwner(damagedParty);
|
||||
const product = fanavaranClaimProductFromBlameType(input.blameCase?.type);
|
||||
const { mapped: inquiryMapped, raw: inquiryRawPayload } =
|
||||
fanavaranPartyInquirySources(product, damagedParty);
|
||||
@@ -4630,12 +4681,14 @@ export class ClaimRequestManagementService {
|
||||
|
||||
this.logger.log(
|
||||
`[buildFanavaranDamageCasePayload] damagedParty resolved: userId=${damagedParty?.person?.userId ?? "NONE"}, ` +
|
||||
`nationalCode=${pickPersonNationalCode(person) ?? "MISSING"}, ` +
|
||||
`driverNationalCode=${driverIdentity.nationalCode ?? "MISSING"}, ` +
|
||||
`ownerNationalCode=${ownerIdentity.nationalCode ?? "MISSING"}, ` +
|
||||
`nationalCodeOfDriver=${person.nationalCodeOfDriver ?? "MISSING"}, ` +
|
||||
`nationalCodeOfInsurer=${person.nationalCodeOfInsurer ?? "MISSING"}, ` +
|
||||
`driverBirthday=${pickPersonBirthday(person) ?? "MISSING"}, ` +
|
||||
`driverIsInsurer=${person.driverIsInsurer ?? "MISSING"}, ` +
|
||||
`driverLicense=${person.driverLicense ?? "MISSING"}`,
|
||||
`driverBirthday=${driverIdentity.birthday ?? "MISSING"}, ` +
|
||||
`driverIsOwner=${driverIsOwner}, ` +
|
||||
`driverLicense=${driverIdentity.licenseNo ?? person.driverLicense ?? "MISSING"}, ` +
|
||||
`driverLicenseDate=${driverIdentity.licenseIssuDate ?? "MISSING"}`,
|
||||
);
|
||||
if (!damagedParty) {
|
||||
this.logger.warn(
|
||||
@@ -4761,12 +4814,23 @@ export class ClaimRequestManagementService {
|
||||
if (vehicleKindId != null) vehicleKindSource = "car-type-lookup";
|
||||
}
|
||||
|
||||
let driverFanavaranId = await this.resolveDriverFanavaranIdFromBlameCase(
|
||||
input.clientKey,
|
||||
input.blameCase?.parties ?? [],
|
||||
person,
|
||||
input.claimCase,
|
||||
);
|
||||
let driverFanavaranId: number | null = null;
|
||||
if (driverIdentity.nationalCode && driverIdentity.birthday) {
|
||||
driverFanavaranId = await this.resolveDriverFanavaranId(
|
||||
input.clientKey,
|
||||
driverIdentity.nationalCode,
|
||||
driverIdentity.birthday,
|
||||
false,
|
||||
);
|
||||
}
|
||||
if (driverFanavaranId == null) {
|
||||
driverFanavaranId = await this.resolveDriverFanavaranIdFromBlameCase(
|
||||
input.clientKey,
|
||||
input.blameCase?.parties ?? [],
|
||||
person,
|
||||
input.claimCase,
|
||||
);
|
||||
}
|
||||
let otherPersonId = this.firstPositiveFanavaranId(cachedDamage.otherPersonId);
|
||||
|
||||
if (driverFanavaranId) {
|
||||
@@ -4781,7 +4845,13 @@ export class ClaimRequestManagementService {
|
||||
} else if (input.registerMissingPerson) {
|
||||
const registered = await this.registerFanavaranOtherPerson({
|
||||
clientKey: input.clientKey,
|
||||
person,
|
||||
person: {
|
||||
...person,
|
||||
nationalCodeOfDriver:
|
||||
driverIdentity.nationalCode ?? person.nationalCodeOfDriver,
|
||||
driverBirthday: driverIdentity.birthday ?? person.driverBirthday,
|
||||
driverIsInsurer: false,
|
||||
},
|
||||
claimCaseId: input.claimCase?._id
|
||||
? String(input.claimCase._id)
|
||||
: undefined,
|
||||
@@ -4792,6 +4862,21 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
let ownerFanavaranId: number | null = null;
|
||||
if (
|
||||
ownerIdentity.nationalCode &&
|
||||
ownerIdentity.nationalCode === driverIdentity.nationalCode &&
|
||||
driverFanavaranId != null
|
||||
) {
|
||||
ownerFanavaranId = driverFanavaranId;
|
||||
} else if (ownerIdentity.nationalCode && ownerIdentity.birthday) {
|
||||
ownerFanavaranId = await this.resolveOwnerFanavaranId(
|
||||
input.clientKey,
|
||||
ownerIdentity.nationalCode,
|
||||
ownerIdentity.birthday,
|
||||
);
|
||||
}
|
||||
|
||||
if (driverFanavaranId && input.blameCase?._id && damagedParty) {
|
||||
const partyIndex = (input.blameCase.parties ?? []).findIndex(
|
||||
(p: any) => p === damagedParty ||
|
||||
@@ -4844,7 +4929,7 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`[buildFanavaranDamageCasePayload] Final DriverId=${driverFanavaranId ?? "NULL"} for nationalCode=${pickPersonNationalCode(person) ?? "MISSING"}, ` +
|
||||
`[buildFanavaranDamageCasePayload] Final DriverId=${driverFanavaranId ?? "NULL"} OwnerId=${ownerFanavaranId ?? "NULL"} for driverNationalCode=${driverIdentity.nationalCode ?? "MISSING"}, ` +
|
||||
`PolicyNo=${policyNo ?? "NULL"}, PolicyCINumber=${policyCINumber ?? "NULL"}`,
|
||||
);
|
||||
|
||||
@@ -4866,17 +4951,17 @@ export class ClaimRequestManagementService {
|
||||
EstimateAmount: FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT,
|
||||
FaultPercent: input.defaults.FaultPercent,
|
||||
InsuranceCorpId: insuranceCorpId,
|
||||
DriverIsOwner: person.driverIsInsurer ? 1 : input.defaults.DriverIsOwner,
|
||||
DriverIsOwner: driverIsOwner ? 1 : 0,
|
||||
LicenceCityId: null,
|
||||
LicenceCountryId: null,
|
||||
LicenceForeignCityName: null,
|
||||
LicenceIssuDate:
|
||||
person.driverLicenseDate ?? person.driverBirthday ?? "1394/10/13",
|
||||
LicenceIssuDate: resolveFanavaranLicenceIssuDate(driverIdentity),
|
||||
// Must never be empty/null; prefer stored DB value, else use dummy.
|
||||
LicenceNo: this.resolveFanavaranLicenceNoFromParty({
|
||||
driverIsInsurer: person.driverIsInsurer,
|
||||
driverLicense: person.driverLicense,
|
||||
insurerLicense: person.insurerLicense,
|
||||
resolvedLicenseNo: driverIdentity.licenseNo,
|
||||
}),
|
||||
LicenceTypeId: input.defaults.CulpritLicenceTypeId,
|
||||
MotorNo:
|
||||
@@ -4885,7 +4970,7 @@ export class ClaimRequestManagementService {
|
||||
"EngineNumberField",
|
||||
"mtrnum",
|
||||
]) ?? (typeof apiVehicle?.MotorNo === "string" ? apiVehicle.MotorNo : null),
|
||||
OwnerId: null,
|
||||
OwnerId: ownerFanavaranId,
|
||||
PlaqueCityId: apiPlaque.cityId,
|
||||
PlaqueKindId: plaqueKindId,
|
||||
PlaqueLeftNo:
|
||||
@@ -5820,6 +5905,8 @@ export class ClaimRequestManagementService {
|
||||
parties: Array<{
|
||||
role?: PartyRole;
|
||||
person?: { userId?: Types.ObjectId; nationalCodeOfInsurer?: string };
|
||||
participants?: Array<Record<string, any>>;
|
||||
participantRoles?: Partial<InquiryParticipantRoleAssignments>;
|
||||
statement?: { admitsGuilt?: boolean };
|
||||
}>,
|
||||
guiltyPartyId?: Types.ObjectId | string | null,
|
||||
@@ -5831,8 +5918,13 @@ export class ClaimRequestManagementService {
|
||||
const guiltyParty = parties.find(
|
||||
(party) => party.person?.userId?.toString() === guiltyPartyId.toString(),
|
||||
);
|
||||
if (!guiltyParty) return null;
|
||||
|
||||
return guiltyParty?.person?.nationalCodeOfInsurer ?? null;
|
||||
return (
|
||||
resolvePolicyholderFromParty(guiltyParty, "third-party").nationalCode ??
|
||||
guiltyParty.person?.nationalCodeOfInsurer ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private resolveGuiltyPartyIdV2(
|
||||
@@ -6111,6 +6203,31 @@ export class ClaimRequestManagementService {
|
||||
},
|
||||
});
|
||||
|
||||
// GEN.03 CulpritLicence*: guilty-party DRIVER for THIRD_PARTY, FIRST-party DRIVER for CAR_BODY.
|
||||
{
|
||||
const culpritParty =
|
||||
blameCase.type === BlameRequestType.CAR_BODY
|
||||
? firstParty
|
||||
: (() => {
|
||||
const guiltyPartyId = this.resolveGuiltyPartyIdV2(
|
||||
blameCase.parties ?? [],
|
||||
expertDecision?.guiltyPartyId,
|
||||
);
|
||||
return (blameCase.parties ?? []).find(
|
||||
(party: any) =>
|
||||
String(party?.person?.userId ?? "") ===
|
||||
String(guiltyPartyId ?? ""),
|
||||
);
|
||||
})();
|
||||
const culpritDriver = resolveDriverFromParty(culpritParty as any);
|
||||
payload.CulpritLicenceNo = resolveFanavaranLicenceNo(
|
||||
culpritDriver,
|
||||
FANAVARAN_DUMMY_LICENCE_NO,
|
||||
);
|
||||
payload.CulpritLicenceIssuDate =
|
||||
resolveFanavaranLicenceIssuDate(culpritDriver);
|
||||
}
|
||||
|
||||
const carBodyAccidentTime = (
|
||||
firstParty as { statement?: { accidentTime?: string } } | undefined
|
||||
)?.statement?.accidentTime;
|
||||
|
||||
Reference in New Issue
Block a user