Merge pull request 'mapping problems fixed' (#237) from s.hajizadeh/yara724api:main into main

Reviewed-on: Yara724/api#237
This commit is contained in:
2026-08-01 17:57:41 +03:30
5 changed files with 283 additions and 78 deletions

View File

@@ -809,7 +809,12 @@ export class ClaimRequestManagementService {
throw er; throw er;
} }
if (er.code === 11000) { if (
typeof er === "object" &&
er !== null &&
"code" in er &&
er.code === 11000
) {
throw new HttpException( throw new HttpException(
"Duplicate claim file reference.", "Duplicate claim file reference.",
HttpStatus.CONFLICT, HttpStatus.CONFLICT,
@@ -1413,8 +1418,8 @@ export class ClaimRequestManagementService {
return new ClaimPartUploadDetail([updatedClaim]); return new ClaimPartUploadDetail([updatedClaim]);
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
`Error in selectCarOtherPartDamage: ${error.message}`, `Error in selectCarOtherPartDamage: ${error instanceof Error ? error.message : String(error)}`,
error.stack, error instanceof Error ? error.stack : undefined,
); );
// Re-throw the specific error from the validation steps or a generic one. // Re-throw the specific error from the validation steps or a generic one.
throw error; throw error;
@@ -1516,7 +1521,7 @@ export class ClaimRequestManagementService {
} }
} catch (fileError) { } catch (fileError) {
this.logger.warn( this.logger.warn(
`Failed to delete file ${existingDoc.path}: ${fileError.message}`, `Failed to delete file ${existingDoc.path}: ${fileError instanceof Error ? fileError.message : String(fileError)}`,
); );
// Continue even if file deletion fails // Continue even if file deletion fails
} }
@@ -1612,8 +1617,8 @@ export class ClaimRequestManagementService {
}; };
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
`Error in uploadRequiredDocument: ${error.message}`, `Error in uploadRequiredDocument: ${error instanceof Error ? error.message : String(error)}`,
error.stack, error instanceof Error ? error.stack : undefined,
); );
throw error; throw error;
} }
@@ -1658,8 +1663,8 @@ export class ClaimRequestManagementService {
}; };
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
`Error in getRequiredDocumentsStatus: ${error.message}`, `Error in getRequiredDocumentsStatus: ${error instanceof Error ? error.message : String(error)}`,
error.stack, error instanceof Error ? error.stack : undefined,
); );
throw error; throw error;
} }
@@ -1922,8 +1927,8 @@ export class ClaimRequestManagementService {
); );
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
`[BACKGROUND AI] Failed to process AI requests for part ${partId}, request ${requestId}: ${error.message}`, `[BACKGROUND AI] Failed to process AI requests for part ${partId}, request ${requestId}: ${error instanceof Error ? error.message : String(error)}`,
error.stack, error instanceof Error ? error.stack : undefined,
); );
// Don't throw - we're in background processing // Don't throw - we're in background processing
} }
@@ -2013,11 +2018,15 @@ export class ClaimRequestManagementService {
`[SUCCESS] Successfully updated AI report and image for part ${partId}`, `[SUCCESS] Successfully updated AI report and image for part ${partId}`,
); );
} catch (dbError) { } catch (dbError) {
const dbErrorMessage =
dbError instanceof Error ? dbError.message : String(dbError);
this.logger.error(`[ERROR] Database update error for part ${partId}:`); this.logger.error(`[ERROR] Database update error for part ${partId}:`);
this.logger.error(`[ERROR] ${dbError.message}`); this.logger.error(`[ERROR] ${dbErrorMessage}`);
this.logger.error(`[ERROR] Stack: ${dbError.stack}`); this.logger.error(
`[ERROR] Stack: ${dbError instanceof Error ? dbError.stack : undefined}`,
);
throw new HttpException( throw new HttpException(
`Database update failed: ${dbError.message}`, `Database update failed: ${dbErrorMessage}`,
HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR,
); );
} }
@@ -2053,7 +2062,8 @@ export class ClaimRequestManagementService {
); );
} catch (error) { } catch (error) {
// Extract error source from error message if available // Extract error source from error message if available
const errorMessage = error.message || String(error); const errorMessage =
error instanceof Error ? error.message : String(error);
const errorSource = errorMessage.includes("[ERROR]") const errorSource = errorMessage.includes("[ERROR]")
? errorMessage.split("[ERROR]")[1]?.split("]")[0] || "UNKNOWN" ? errorMessage.split("[ERROR]")[1]?.split("]")[0] || "UNKNOWN"
: "UNKNOWN"; : "UNKNOWN";
@@ -2089,7 +2099,7 @@ export class ClaimRequestManagementService {
this.logger.error(`🔴 [FINAL FAILURE] File path: ${newImageDoc.path}`); this.logger.error(`🔴 [FINAL FAILURE] File path: ${newImageDoc.path}`);
this.logger.error(`🔴 [FINAL FAILURE] Error source: ${errorSource}`); this.logger.error(`🔴 [FINAL FAILURE] Error source: ${errorSource}`);
this.logger.error(`🔴 [FINAL FAILURE] Final error: ${errorMessage}`); this.logger.error(`🔴 [FINAL FAILURE] Final error: ${errorMessage}`);
if (error.stack) { if (error instanceof Error && error.stack) {
this.logger.error(`🔴 [FINAL FAILURE] Stack trace: ${error.stack}`); this.logger.error(`🔴 [FINAL FAILURE] Stack trace: ${error.stack}`);
} }
// Optional: Update the claim status to indicate an AI failure. // Optional: Update the claim status to indicate an AI failure.
@@ -2856,7 +2866,7 @@ export class ClaimRequestManagementService {
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
`Error during factor upload for claim ${claimId}:`, `Error during factor upload for claim ${claimId}:`,
error.stack, error instanceof Error ? error.stack : String(error),
); );
if (error instanceof HttpException) { if (error instanceof HttpException) {
@@ -3155,7 +3165,12 @@ export class ClaimRequestManagementService {
}; };
} catch (err) { } catch (err) {
this.logger.error(err); this.logger.error(err);
return new HttpException(err.message, err.status); return new HttpException(
err instanceof HttpException ? err.message : String(err),
err instanceof HttpException
? err.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR,
);
} }
} }
@@ -3214,7 +3229,12 @@ export class ClaimRequestManagementService {
}; };
} catch (err) { } catch (err) {
this.logger.error(err); this.logger.error(err);
return new HttpException(err.message, err.status); return new HttpException(
err instanceof HttpException ? err.message : String(err),
err instanceof HttpException
? err.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR,
);
} }
} }
@@ -3609,6 +3629,53 @@ export class ClaimRequestManagementService {
return `${plate.centerDigits}${plate.centerAlphabet}${plate.leftDigits}`; return `${plate.centerDigits}${plate.centerAlphabet}${plate.leftDigits}`;
} }
/** First non-empty string from party vehicle.inquiry mapped/raw (ESG + Tejarat aliases). */
private pickPartyInquiryField(
mapped: Record<string, any> | null | undefined,
raw: Record<string, any> | null | undefined,
keys: string[],
): string | null {
for (const key of keys) {
const value = mapped?.[key] ?? raw?.[key];
if (value == null) continue;
const text = String(value).trim();
if (text) return text;
}
return null;
}
private resolvePlateFromPartyInquiry(
mapped: Record<string, any> | null | undefined,
raw: Record<string, any> | null | undefined,
): {
leftDigits: number;
centerAlphabet: string;
centerDigits: number;
ir: number;
} | null {
const left = this.pickPartyInquiryField(mapped, raw, ["plk1", "Plk1"]);
const middle = this.pickPartyInquiryField(mapped, raw, ["plk2", "Plk2"]);
const right = this.pickPartyInquiryField(mapped, raw, ["plk3", "Plk3"]);
const serial = this.pickPartyInquiryField(mapped, raw, [
"plksrl",
"PlkSrl",
]);
if (!left || !middle || !right || !serial) return null;
const leftDigits = Number(left);
const centerDigits = Number(right);
const ir = Number(serial);
const centerAlphabet = this.plateNormalizer.normalizePlateText(middle);
if (
!Number.isFinite(leftDigits) ||
!Number.isFinite(centerDigits) ||
!Number.isFinite(ir) ||
!centerAlphabet
) {
return null;
}
return { leftDigits, centerAlphabet, centerDigits, ir };
}
private async resolveVehicleKindId( private async resolveVehicleKindId(
clientKey: FanavaranClientKey, clientKey: FanavaranClientKey,
carType?: string, carType?: string,
@@ -3781,10 +3848,6 @@ export class ClaimRequestManagementService {
FaultPercent: number; FaultPercent: number;
}; };
}): Promise<Record<string, unknown>> { }): Promise<Record<string, unknown>> {
const plate = this.resolveOwnershipPlateForClaim(
input.claimCase,
input.blameCase,
);
const damagedParty = Array.isArray(input.blameCase?.parties) const damagedParty = Array.isArray(input.blameCase?.parties)
? input.blameCase.parties.find( ? input.blameCase.parties.find(
(party: any) => (party: any) =>
@@ -3795,8 +3858,19 @@ export class ClaimRequestManagementService {
const person = damagedParty?.person ?? {}; const person = damagedParty?.person ?? {};
const vehicle = damagedParty?.vehicle ?? {}; const vehicle = damagedParty?.vehicle ?? {};
const insurance = damagedParty?.insurance ?? {}; const insurance = damagedParty?.insurance ?? {};
const inquiryMapped = vehicle?.inquiry?.mapped ?? {}; // Prefer nested inquiry (ESG/Tejarat) on the damaged party — not flattened insurance.*
const inquiryRaw = vehicle?.inquiry?.raw ?? {}; const inquiryRawPayload =
vehicle?.inquiry?.raw?.data != null &&
typeof vehicle.inquiry.raw.data === "object" &&
!Array.isArray(vehicle.inquiry.raw.data)
? vehicle.inquiry.raw.data
: (vehicle?.inquiry?.raw ?? {});
const inquiryMapped = vehicle?.inquiry?.mapped ?? inquiryRawPayload ?? {};
const inquiryRaw = inquiryRawPayload ?? {};
const plate =
this.resolveOwnershipPlateForClaim(input.claimCase, input.blameCase) ??
this.resolvePlateFromPartyInquiry(inquiryMapped, inquiryRaw);
this.logger.log( this.logger.log(
`[buildFanavaranDamageCasePayload] damagedParty resolved: userId=${damagedParty?.person?.userId ?? "NONE"}, ` + `[buildFanavaranDamageCasePayload] damagedParty resolved: userId=${damagedParty?.person?.userId ?? "NONE"}, ` +
@@ -3812,22 +3886,44 @@ export class ClaimRequestManagementService {
); );
} }
const guiltyUserId = // Policy document / unique code / coverage dates from damaged party's plate inquiry
input.blameCase?.expertSubmitReplyFinal?.guiltyUserId ?? const policyNo =
input.blameCase?.expertSubmitReply?.guiltyUserId; this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
const blamedParty = "PrntCmpDocNo",
guiltyUserId && Array.isArray(input.blameCase?.parties) "PrntPlcyCmpDocNo",
? input.blameCase.parties.find( "printNumber",
(party: any) => "insuranceNumber",
String(party?.person?.userId ?? "") === String(guiltyUserId), ]) ??
) insurance.policyNumber ??
: null;
// Get PolicyCINumber from damaged party's inquiry (mapped or raw), not blamed party
const policyCINumber =
inquiryMapped.ThirdPolicyCode ??
inquiryRaw.ThirdPolicyCode ??
null; null;
const policyCINumber = this.pickPartyInquiryField(
inquiryMapped,
inquiryRaw,
["PlcyUnqCod", "ThirdPolicyCode"],
);
const beginDate =
this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
"HBgnDte",
"StartDate",
"persianStartDate",
"SatrtDate",
]) ??
insurance.startDate ??
null;
const endDate =
this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
"HEndDte",
"EndDate",
"persianEndDate",
]) ??
insurance.endDate ??
null;
const builtYearRaw = this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
"PrdDte",
"ModelField",
"ModelCii",
]);
const builtYear = builtYearRaw ? Number(builtYearRaw) || null : null;
const carType = input.claimCase?.vehicle?.carType as string | undefined; const carType = input.claimCase?.vehicle?.carType as string | undefined;
const vehicleKindId = await this.resolveVehicleKindId( const vehicleKindId = await this.resolveVehicleKindId(
@@ -3870,24 +3966,23 @@ export class ClaimRequestManagementService {
} }
this.logger.log( this.logger.log(
`[buildFanavaranDamageCasePayload] Final DriverId=${driverFanavaranId ?? "NULL"} for nationalCodeOfDriver=${person.nationalCodeOfDriver ?? "MISSING"}`, `[buildFanavaranDamageCasePayload] Final DriverId=${driverFanavaranId ?? "NULL"} for nationalCodeOfDriver=${person.nationalCodeOfDriver ?? "MISSING"}, ` +
`PolicyNo=${policyNo ?? "NULL"}, PolicyCINumber=${policyCINumber ?? "NULL"}`,
); );
return { return {
BeginDate: insurance.startDate ?? null, BeginDate: beginDate,
BuiltYear: BuiltYear: builtYear,
Number(inquiryMapped.ModelField ?? inquiryMapped.ModelCii) || Number(inquiryMapped.PrdDte) || null, ChassisNo: this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
ChassisNo: "ShsNum",
inquiryMapped.ChassisNumberField ?? "ChassisNumberField",
inquiryMapped.ShsNum ?? "shsNam",
inquiryRaw.ChassisNumberField ?? ]),
inquiryRaw.ShsNum ??
null,
DmgHistoryStatus: input.defaults.DmgHistoryStatus, DmgHistoryStatus: input.defaults.DmgHistoryStatus,
Desc: this.formatFanavaranSelectedPartsDesc(input.selectedParts), Desc: this.formatFanavaranSelectedPartsDesc(input.selectedParts),
DmgCaseTypeId: input.defaults.DmgCaseTypeId, DmgCaseTypeId: input.defaults.DmgCaseTypeId,
DriverId: driverFanavaranId ?? null, DriverId: driverFanavaranId ?? null,
EndDate: insurance.endDate ?? null, EndDate: endDate,
EstimateAmount: FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT, EstimateAmount: FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT,
FaultPercent: input.defaults.FaultPercent, FaultPercent: input.defaults.FaultPercent,
InsuranceCorpId: await this.fanavaranLookupService.resolveInsuranceCorpId(input.clientKey), InsuranceCorpId: await this.fanavaranLookupService.resolveInsuranceCorpId(input.clientKey),
@@ -3898,12 +3993,11 @@ export class ClaimRequestManagementService {
LicenceIssuDate: person.driverBirthday ?? "1394/10/13", LicenceIssuDate: person.driverBirthday ?? "1394/10/13",
LicenceNo: person.driverLicense ?? "1124242", LicenceNo: person.driverLicense ?? "1124242",
LicenceTypeId: input.defaults.CulpritLicenceTypeId, LicenceTypeId: input.defaults.CulpritLicenceTypeId,
MotorNo: MotorNo: this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
inquiryMapped.MtrNum ?? "MtrNum",
inquiryMapped.EngineNumberField ?? "EngineNumberField",
inquiryRaw.MtrNum ?? "mtrnum",
inquiryRaw.EngineNumberField ?? ]),
null,
OwnerId: null, OwnerId: null,
PlaqueCityId: null, PlaqueCityId: null,
PlaqueKindId: plate ? input.defaults.PlaqueKindId : null, PlaqueKindId: plate ? input.defaults.PlaqueKindId : null,
@@ -3911,14 +4005,20 @@ export class ClaimRequestManagementService {
PlaqueMiddleCodeId: this.getFanavaranPlateMiddleCode( PlaqueMiddleCodeId: this.getFanavaranPlateMiddleCode(
plate?.centerAlphabet, plate?.centerAlphabet,
), ),
PlaqueNo: this.formatFanavaranPlateNo(plate), PlaqueNo:
this.pickPartyInquiryField(inquiryMapped, inquiryRaw, ["Plk"]) ??
this.formatFanavaranPlateNo(plate),
PlaqueRightNo: plate ? String(plate.centerDigits) : null, PlaqueRightNo: plate ? String(plate.centerDigits) : null,
PlaqueSampleId: plate ? input.defaults.PlaqueSampleId : null, PlaqueSampleId: plate ? input.defaults.PlaqueSampleId : null,
PlaqueSerial: plate ? String(plate.ir) : null, PlaqueSerial: plate ? String(plate.ir) : null,
PolicyNo: insurance.policyNumber ?? null, PolicyNo: policyNo,
PreviousPolicyEndDate: insurance.endDate ?? "", PreviousPolicyEndDate: endDate ?? "",
VehicleKindId: vehicleKindId, VehicleKindId: vehicleKindId,
VIN: inquiryMapped.VIN ?? inquiryRaw.VIN ?? null, VIN: this.pickPartyInquiryField(inquiryMapped, inquiryRaw, [
"VIN",
"vin",
"VinNumberField",
]),
AccidentVehicleUsedId: input.defaults.AccidentVehicleUsedId, AccidentVehicleUsedId: input.defaults.AccidentVehicleUsedId,
PolicyCINumber: policyCINumber, PolicyCINumber: policyCINumber,
}; };

View File

@@ -369,6 +369,7 @@ export class InquiryRefreshService {
} }
next.insurance.policyNumber = next.insurance.policyNumber =
mapped.PrntCmpDocNo ||
mapped.PrntPlcyCmpDocNo || mapped.PrntPlcyCmpDocNo ||
mapped.printNumber || mapped.printNumber ||
mapped.insuranceNumber || mapped.insuranceNumber ||
@@ -384,9 +385,17 @@ export class InquiryRefreshService {
? String(financialCeiling) ? String(financialCeiling)
: next.insurance.financialCeiling; : next.insurance.financialCeiling;
next.insurance.startDate = next.insurance.startDate =
mapped.persianStartDate || mapped.IssueDate || mapped.SatrtDate || next.insurance.startDate; mapped.StartDate ||
mapped.HBgnDte ||
mapped.persianStartDate ||
mapped.SatrtDate ||
mapped.IssueDate ||
next.insurance.startDate;
next.insurance.endDate = next.insurance.endDate =
mapped.persianEndDate || mapped.EndDate || next.insurance.endDate; mapped.EndDate ||
mapped.HEndDte ||
mapped.persianEndDate ||
next.insurance.endDate;
return next; return next;
} }

View File

@@ -1371,11 +1371,23 @@ export class RequestManagementService {
}; };
if (!party.insurance) party.insurance = {} as any; if (!party.insurance) party.insurance = {} as any;
party.insurance.policyNumber = inquiryMapped?.PrntPlcyCmpDocNo; party.insurance.policyNumber =
inquiryMapped?.PrntCmpDocNo ||
inquiryMapped?.PrntPlcyCmpDocNo ||
inquiryMapped?.printNumber ||
inquiryMapped?.insuranceNumber;
party.insurance.company = clientName; party.insurance.company = clientName;
party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl; party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl;
party.insurance.startDate = inquiryMapped?.IssueDate; party.insurance.startDate =
party.insurance.endDate = inquiryMapped?.EndDate; inquiryMapped?.StartDate ||
inquiryMapped?.HBgnDte ||
inquiryMapped?.persianStartDate ||
inquiryMapped?.SatrtDate ||
inquiryMapped?.IssueDate;
party.insurance.endDate =
inquiryMapped?.EndDate ||
inquiryMapped?.HEndDte ||
inquiryMapped?.persianEndDate;
// CAR BODY EXTERNAL API INQUIRY // CAR BODY EXTERNAL API INQUIRY
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) { if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
@@ -1776,11 +1788,23 @@ export class RequestManagementService {
}; };
if (!party.insurance) party.insurance = {} as any; if (!party.insurance) party.insurance = {} as any;
party.insurance.policyNumber = inquiryMapped?.PrntPlcyCmpDocNo; party.insurance.policyNumber =
inquiryMapped?.PrntCmpDocNo ||
inquiryMapped?.PrntPlcyCmpDocNo ||
inquiryMapped?.printNumber ||
inquiryMapped?.insuranceNumber;
party.insurance.company = clientName; party.insurance.company = clientName;
party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl; party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl;
party.insurance.startDate = inquiryMapped?.IssueDate; party.insurance.startDate =
party.insurance.endDate = inquiryMapped?.EndDate; inquiryMapped?.StartDate ||
inquiryMapped?.HBgnDte ||
inquiryMapped?.persianStartDate ||
inquiryMapped?.SatrtDate ||
inquiryMapped?.IssueDate;
party.insurance.endDate =
inquiryMapped?.EndDate ||
inquiryMapped?.HEndDte ||
inquiryMapped?.persianEndDate;
// Advance workflow // Advance workflow
await this.advanceWorkflowToNext(req, stepKey); await this.advanceWorkflowToNext(req, stepKey);
@@ -8592,11 +8616,23 @@ export class RequestManagementService {
}; };
if (!party.insurance) party.insurance = {} as any; if (!party.insurance) party.insurance = {} as any;
party.insurance.policyNumber = inquiryMapped?.PrntPlcyCmpDocNo; party.insurance.policyNumber =
inquiryMapped?.PrntCmpDocNo ||
inquiryMapped?.PrntPlcyCmpDocNo ||
inquiryMapped?.printNumber ||
inquiryMapped?.insuranceNumber;
party.insurance.company = clientName; party.insurance.company = clientName;
party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl; party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl;
party.insurance.startDate = inquiryMapped?.IssueDate; party.insurance.startDate =
party.insurance.endDate = inquiryMapped?.EndDate; inquiryMapped?.StartDate ||
inquiryMapped?.HBgnDte ||
inquiryMapped?.persianStartDate ||
inquiryMapped?.SatrtDate ||
inquiryMapped?.IssueDate;
party.insurance.endDate =
inquiryMapped?.EndDate ||
inquiryMapped?.HEndDte ||
inquiryMapped?.persianEndDate;
if ( if (
req.type === BlameRequestType.CAR_BODY && req.type === BlameRequestType.CAR_BODY &&
@@ -9392,11 +9428,23 @@ export class RequestManagementService {
}; };
if (!party.insurance) party.insurance = {} as any; if (!party.insurance) party.insurance = {} as any;
party.insurance.policyNumber = inquiryMapped?.PrntPlcyCmpDocNo; party.insurance.policyNumber =
inquiryMapped?.PrntCmpDocNo ||
inquiryMapped?.PrntPlcyCmpDocNo ||
inquiryMapped?.printNumber ||
inquiryMapped?.insuranceNumber;
party.insurance.company = clientName; party.insurance.company = clientName;
party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl; party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl;
party.insurance.startDate = inquiryMapped?.IssueDate; party.insurance.startDate =
party.insurance.endDate = inquiryMapped?.EndDate; inquiryMapped?.StartDate ||
inquiryMapped?.HBgnDte ||
inquiryMapped?.persianStartDate ||
inquiryMapped?.SatrtDate ||
inquiryMapped?.IssueDate;
party.insurance.endDate =
inquiryMapped?.EndDate ||
inquiryMapped?.HEndDte ||
inquiryMapped?.persianEndDate;
if ( if (
req.type === BlameRequestType.CAR_BODY && req.type === BlameRequestType.CAR_BODY &&

View File

@@ -114,4 +114,32 @@ describe("SandHubService inquiry mocks", () => {
expect(mapped.PrntPlcyCmpDocNo).toBe("1405/1143-LEGACY/200/1"); expect(mapped.PrntPlcyCmpDocNo).toBe("1405/1143-LEGACY/200/1");
}); });
it("maps ESG PrntCmpDocNo → PrntPlcyCmpDocNo and preserves begin/end dates", () => {
const mapped = (service as any).mapEsgPolicyByPlateToOldFormat({
success: true,
data: {
PrntCmpDocNo: "1110/111130/404/003412",
LastCmpDocNo: "1110/111130/403/002650",
PlcyUnqCod: "16018466143",
HBgnDte: "1404/10/23",
HEndDte: "1405/10/23",
HIsuDte: "1404/10/21",
VIN: "IRFC891V7D2301065",
MtrNum: "13389030167",
ShsNum: "NAAP41FD5BJ301065",
PrdDte: "1389",
CmpCod: "8",
CmpNam: "بيمه پارسيان",
},
});
expect(mapped.PrntPlcyCmpDocNo).toBe("1110/111130/404/003412");
expect(mapped.ThirdPolicyCode).toBe("16018466143");
expect(mapped.StartDate).toBe("1404/10/23");
expect(mapped.EndDate).toBe("1405/10/23");
expect(mapped.IssueDate).toBe("1404/10/21");
expect(mapped.VIN).toBe("IRFC891V7D2301065");
expect(mapped.ModelField).toBe("1389");
});
}); });

View File

@@ -560,14 +560,22 @@ export class SandHubService {
mtrnum: data.MtrNum ?? data.mtrnum, mtrnum: data.MtrNum ?? data.mtrnum,
shsNam: data.ShsNum ?? data.ShsNam ?? data.shsNam, shsNam: data.ShsNum ?? data.ShsNam ?? data.shsNam,
vin: data.VIN ?? data.vin, vin: data.VIN ?? data.vin,
VIN: data.VIN ?? data.vin,
ntnlId: data.NtnlId ?? data.ntnlId, ntnlId: data.NtnlId ?? data.ntnlId,
fullname: data.InsNam ?? data.fullname, fullname: data.InsNam ?? data.fullname,
ThirdPolicyCode: data.PlcyUnqCod ?? data.ThirdPolicyCode, ThirdPolicyCode: data.PlcyUnqCod ?? data.ThirdPolicyCode,
// ESG print/policy document number — canonical Tejarat name is PrntPlcyCmpDocNo
PrntPlcyCmpDocNo:
data.PrntCmpDocNo ??
data.PrntPlcyCmpDocNo ??
data.printNumber ??
data.insuranceNumber,
LastCompanyDocumentNumber: LastCompanyDocumentNumber:
data.LastCmpDocNo ?? data.LastCompanyDocumentNumber, data.LastCmpDocNo ?? data.LastCompanyDocumentNumber,
IssueDate: data.HIsuDte ?? data.IssueDate, IssueDate: data.HIsuDte ?? data.IssueDate,
StartDate: data.HBgnDte ?? data.StartDate, StartDate: data.HBgnDte ?? data.StartDate,
EndDate: data.HEndDte ?? data.EndDate, EndDate: data.HEndDte ?? data.EndDate,
ModelField: data.PrdDte ?? data.ModelField ?? data.ModelCii,
EdrsJson: data.Edrses ?? data.EdrsJson, EdrsJson: data.Edrses ?? data.EdrsJson,
}); });
} }
@@ -1010,14 +1018,26 @@ export class SandHubService {
FinancialCvrCptl: FinancialCvrCptl:
newResponse.financeCoverage || newResponse.FinancialCvrCptl || "0", newResponse.financeCoverage || newResponse.FinancialCvrCptl || "0",
// Dates // Dates — keep IssueDate (HIsuDte) distinct from StartDate (HBgnDte)
IssueDate: newResponse.persianStartDate || newResponse.IssueDate, IssueDate:
EndDate: newResponse.persianEndDate || newResponse.EndDate, newResponse.IssueDate ||
newResponse.HIsuDte ||
newResponse.persianStartDate,
StartDate:
newResponse.StartDate ||
newResponse.HBgnDte ||
newResponse.SatrtDate ||
newResponse.persianStartDate,
EndDate:
newResponse.EndDate ||
newResponse.HEndDte ||
newResponse.persianEndDate,
// Insurance policy number — canonical Tejarat name is PrntPlcyCmpDocNo; // Insurance policy number — canonical Tejarat name is PrntPlcyCmpDocNo;
// newer API formats surface it as printNumber or insuranceNumber. // ESG uses PrntCmpDocNo; newer formats use printNumber / insuranceNumber.
PrntPlcyCmpDocNo: PrntPlcyCmpDocNo:
newResponse.PrntPlcyCmpDocNo || newResponse.PrntPlcyCmpDocNo ||
newResponse.PrntCmpDocNo ||
newResponse.printNumber || newResponse.printNumber ||
newResponse.insuranceNumber || newResponse.insuranceNumber ||
null, null,