1
0
forked from Yara724/api

Merge pull request 'Centralized car body inquiry' (#104) from s.yahyaee/yara724-api:main into main

Reviewed-on: Yara724/api#104
This commit is contained in:
2026-06-01 16:38:12 +03:30
2 changed files with 130 additions and 11 deletions

View File

@@ -1118,13 +1118,44 @@ export class RequestManagementService {
party.insurance.startDate = inquiryMapped?.IssueDate; party.insurance.startDate = inquiryMapped?.IssueDate;
party.insurance.endDate = inquiryMapped?.EndDate; party.insurance.endDate = inquiryMapped?.EndDate;
// CAR_BODY: persist mocked car-body insurance in party's insurance (same place as usual inquiry) // CAR BODY EXTERNAL API INQUIRY
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) { if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
const carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry({ const carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry({
nationalCodeOfInsurer: body.nationalCodeOfInsurer, nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.plate, plate: body.plate,
}); });
(party.insurance as any).carBodyInsurance = carBodyInfo;
// Raw + mapped stored under vehicle (same pattern as third-party inquiry)
party.vehicle.inquiry = {
...party.vehicle.inquiry, // preserve existing third-party inquiry if present
carBody: {
source: "TEJARAT_CAR_BODY_INQUIRY",
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
},
};
// Flat key fields extracted alongside third-party insurance fields
const m = carBodyInfo.mapped;
(party.insurance as any).carBodyInsurance = {
policyNumber: m.policyNumber ?? null,
companyId: m.companyId ?? null,
companyName: m.CompanyName ?? null,
insurerName: m.insurerName ?? null,
insurerNationalCode: m.insurerNationalCode ?? null,
ownerNationalCode: m.ownerNationalCode ?? null,
chassisNumber: m.ChassisNumberField ?? null,
vin: m.VinNumberField ?? null,
motorNumber: m.EngineNumberField ?? null,
vehicleGroup: m.vehicleGroupTitle ?? null,
vehicleSystem: m.vehicleSystemTitle ?? null,
startDate: m.StartDate ?? null,
endDate: m.EndDate ?? null,
issueDate: m.IssueDate ?? null,
noLossYearsCount: m.noLossYearsCount ?? null,
lossDocuments: m.lossDocuments ?? [],
hasEndorsement: m.hasEndorsement ?? null,
};
} }
// Advance workflow // Advance workflow

View File

@@ -355,17 +355,13 @@ export class SandHubService {
return await this.sandHubDbService.findOneBySandHubId(sandHubId); return await this.sandHubDbService.findOneBySandHubId(sandHubId);
} }
/**
* Tejarat block inquiry for Car Body Insurance (Badane).
* Returns both raw API response and mapped old-format response structure.
*/
async getTejaratCarBodyInquiry(userDetail: SandHubDetailDto): Promise<{ async getTejaratCarBodyInquiry(userDetail: SandHubDetailDto): Promise<{
raw: any; raw: any;
mapped: Record<string, unknown>;
}> { }> {
const baseUrl = const baseUrl =
process.env.TEJARAT_INQUIRY_BASE_URL ?? "http://82.99.202.245:3027"; process.env.TEJARAT_INQUIRY_BASE_URL ?? "http://82.99.202.245:3027";
// 1. Build payload following the strict data requirements of the external API
const requestPayload = { const requestPayload = {
part1: Number(userDetail.plate.leftDigits), part1: Number(userDetail.plate.leftDigits),
part2: String(userDetail.plate.centerAlphabet), part2: String(userDetail.plate.centerAlphabet),
@@ -380,11 +376,8 @@ export class SandHubService {
let raw: any; let raw: any;
if (live) { if (live) {
// 2. Safely obtain a fresh or cached access token using your helper
const token = await this.getTejaratAccessToken(); const token = await this.getTejaratAccessToken();
try { try {
// 3. Make the live call using NestJS HttpService + firstValueFrom pattern
const response = await firstValueFrom( const response = await firstValueFrom(
this.httpService.post(requestUrl, requestPayload, { this.httpService.post(requestUrl, requestPayload, {
headers: { headers: {
@@ -403,8 +396,103 @@ export class SandHubService {
); );
throw error; throw error;
} }
} else {
// Mock — reuse the default mock and adapt it to the car-body shape
this.logger.debug(
`[MOCK] getTejaratCarBodyInquiry plate=${JSON.stringify(requestPayload)}`,
);
raw = {
data: {
printNumber: "MOCK-BADANE-001",
companyId: 34,
companyName: "بیمه تجارت نو",
beginDate: "1404/06/15",
endDate: "1405/06/15",
issueDate: "1404/06/13",
hasEndorsement: null,
motorNumber: "MOCK-ENGINE",
chassisNumber: "MOCK-CHASSIS",
vin: "MOCK-VIN",
vehicleSystemTitle: "سایپا",
vehicleGroupTitle: "سواری چهار سیلندر",
insurerNationalCode: userDetail.nationalCodeOfInsurer,
insurerName: "نام آزمایشی",
ownerNationalCode: userDetail.nationalCodeOfInsurer,
noLossYearsCount: 0,
lossDocuments: [],
},
isSuccess: true,
statusCode: 200,
message: "mock-ok",
};
} }
return { raw };
const mapped = this.mapCarBodyInquiryResponse(raw);
return { raw, mapped };
}
/**
* Maps the Tejarat car-body (badane) API response to a consistent
* shape that mirrors the third-party inquiry mapped format.
* Callers should always use `mapped` for display; `raw` is kept for audit.
*/
private mapCarBodyInquiryResponse(raw: any): Record<string, unknown> {
if (!raw) return {};
const data = raw?.data ?? raw; // some responses nest under `data`
return {
// Identity
policyNumber: data.printNumber ?? data.insuranceNumber ?? null,
companyId: data.companyId ?? null,
CompanyCode: data.companyId ?? null,
CompanyName: data.companyName ?? data.companyPersianName ?? null,
// Insurer
insurerNationalCode:
data.insurerNationalCode ?? data.ownerNationalCode ?? null,
insurerName: data.insurerName ?? null,
ownerNationalCode: data.ownerNationalCode ?? null,
InsuranceFullName: data.insurerName ?? data.ownerName ?? null,
// Vehicle
motorNumber: data.motorNumber ?? data.EngineNumberField ?? null,
EngineNumberField: data.motorNumber ?? data.EngineNumberField ?? null,
chassisNumber: data.chassisNumber ?? data.ChassisNumberField ?? null,
ChassisNumberField: data.chassisNumber ?? data.ChassisNumberField ?? null,
vin: data.vin ?? data.VinNumberField ?? null,
VinNumberField: data.vin ?? data.VinNumberField ?? null,
vehicleGroupTitle: data.vehicleGroupTitle ?? null,
vehicleSystemTitle: data.vehicleSystemTitle ?? null,
MapTypNam: data.vehicleGroupTitle ?? data.vehicleSystemTitle ?? null,
// Policy dates (Jalali strings from the API)
IssueDate: data.issueDate ?? data.persianStartDate ?? null,
StartDate: data.beginDate ?? data.persianStartDate ?? null,
EndDate: data.endDate ?? data.persianEndDate ?? null,
// Plate
plateTypeTitle: data.plateTypeTitle ?? null,
platePartOne: data.platePartOne ?? null,
platePartThree: data.platePartThree ?? null,
plateSerialNumber: data.plateSerialNumber ?? null,
plateLetterTitle: data.plateLetterTitle ?? null,
// Loss / no-claim history
noLossYearsCount: data.noLossYearsCount ?? null,
lossDocuments: Array.isArray(data.lossDocuments)
? data.lossDocuments
: [],
// Misc
hasEndorsement: data.hasEndorsement ?? null,
previousId: data.previousId ?? null,
// Status passthrough
isSuccess: raw?.isSuccess ?? true,
statusCode: raw?.statusCode ?? 200,
message: raw?.message ?? null,
};
} }
private async makeSandHubRequest(url: string, payload: any, maxRetries = 3) { private async makeSandHubRequest(url: string, payload: any, maxRetries = 3) {