Route inquiries by participant role

This commit is contained in:
SepehrYahyaee
2026-09-14 10:35:11 +03:30
parent 461afbb6b9
commit 98c7ebb83a
10 changed files with 446 additions and 138 deletions

View File

@@ -176,12 +176,39 @@ describe("SandHubService inquiry mocks", () => {
});
await expect(
service.getPolicyByChassisInquiry("NAAR03HFFRDE07024", {
enforceDeploymentClientMatch: true,
}),
service.getPolicyByChassisInquiry(
{
nationalCode: "1234567890",
chassis: "NAAR03HFFRDE07024",
},
{ enforceDeploymentClientMatch: true },
),
).rejects.toBeInstanceOf(ForbiddenException);
});
it("sends the policyholder national code with the VIN inquiry", async () => {
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
const esg = jest.spyOn(service as any, "makeEsgRequest").mockResolvedValue({
success: true,
data: { CmpCod: "8", CmpNam: "بیمه پارسیان" },
});
await service.getPolicyByChassisInquiry({
nationalCode: "0012345678",
chassis: "NAAR03HFFRDE07024",
});
expect(esg).toHaveBeenCalledWith(
expect.stringContaining("/inquiry/policyByChassis"),
{
nationalCode: "0012345678",
chassis: "NAAR03HFFRDE07024",
},
"vinChassis",
undefined,
);
});
it("does not accept a policy when CLIENT_ID is not configured", async () => {
delete process.env.CLIENT_ID;
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
@@ -295,6 +322,47 @@ describe("SandHubService inquiry mocks", () => {
expect(result.source).toBe("ESG_CAR_BODY_VIN_INQUIRY");
});
it("uses the tenant Fanavaran VIN lookup for non-Parsian car-body inquiries", async () => {
process.env.CLIENT_ID = "15";
process.env.FANAVARAN_CLIENT = "tejaratno";
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
lookupsService.findLastProcessedCarPolicy.mockResolvedValue({
policy: { CINumber: "BODY-15" },
customer: {},
vehicle: { VIN: "NAAR03HFFRDE07024" },
});
const tejarat = jest.spyOn(service, "getTejaratCarBodyInquiry");
const result = await service.getCarBodyInquiry({
nationalCodeOfInsurer: "0012345678",
plate: "NAAR03HFFRDE07024",
});
expect(lookupsService.findLastProcessedCarPolicy).toHaveBeenCalledWith(
"car-body",
{ nationalCode: "0012345678", vin: "NAAR03HFFRDE07024" },
);
expect(tejarat).not.toHaveBeenCalled();
expect(result.source).toBe("TEJARAT_CAR_BODY_VIN_INQUIRY");
});
it("returns a VIN-shaped car-body mock without invoking a plate adapter", async () => {
process.env.CLIENT_ID = "15";
process.env.FANAVARAN_CLIENT = "tejaratno";
const tejarat = jest.spyOn(service, "getTejaratCarBodyInquiry");
const result = await service.getCarBodyInquiry({
nationalCodeOfInsurer: "0012345678",
plate: "NAAR03HFFRDE07024",
});
expect(tejarat).not.toHaveBeenCalled();
expect(lookupsService.findLastProcessedCarPolicy).not.toHaveBeenCalled();
expect(result.source).toBe("TEJARAT_CAR_BODY_VIN_INQUIRY");
expect(result.mapped.VinNumberField).toBe("NAAR03HFFRDE07024");
expect(result.mapped.insurerNationalCode).toBe("0012345678");
});
it("uses car-body mock shape in Tejarat helper when inquiry is off", async () => {
const raw = await (service as any).makeTejaratRequest(
"http://example/block-inquiry-tejarat/badane",

View File

@@ -250,11 +250,16 @@ export class SandHubService {
}
private buildMockCarBodyInquiryRaw(
userDetail: SandHubDetailDto,
userDetail: CarBodyInquiryDetail,
ctx: MockInquiryCompanyContext,
): Record<string, unknown> {
const companyId = Number(ctx.companyId);
const plate = userDetail?.plate;
const plate =
typeof userDetail?.plate === "string" ? undefined : userDetail?.plate;
const vin =
typeof userDetail?.plate === "string"
? userDetail.plate
: "LFP8C7PC3R1K12157";
const platePartOne = Number(plate?.leftDigits ?? 16);
const platePartThree = Number(plate?.centerDigits ?? 498);
const plateSerialNumber = Number(plate?.ir ?? 60);
@@ -272,8 +277,8 @@ export class SandHubService {
issueDate: "1405/01/16",
hasEndorsement: null,
motorNumber: "TZ196XYAP223A210074",
chassisNumber: "LFP8C7PC3R1K12157",
vin: "LFP8C7PC3R1K12157",
chassisNumber: vin,
vin,
plateTypeId: 9,
plateTypeTitle: "پلاک قدیمی",
platePartOne,
@@ -933,28 +938,48 @@ export class SandHubService {
}> {
const useParsianCarBodyLookup = this.shouldUseParsianCarBodyLookup();
const live = await this.isInquiryLive("carBodyPlate", options);
const plateOrVin = userDetail.plate;
const isVinInquiry = typeof plateOrVin === "string";
if (!live) {
// Mock results are generated for the active deployment. They must not be
// treated as evidence of a real insurer and therefore do not go through
// the live-policy insurer gate.
const result = await this.getTejaratCarBodyInquiry(
userDetail as SandHubDetailDto,
options,
);
const ctx = await this.mockCompanyContext(options);
const raw = this.buildMockCarBodyInquiryRaw(userDetail, ctx);
const result = { raw, mapped: this.mapCarBodyInquiryResponse(raw) };
return {
source:
typeof userDetail.plate === "string"
? useParsianCarBodyLookup
? "ESG_CAR_BODY_VIN_INQUIRY"
: "TEJARAT_CAR_BODY_VIN_INQUIRY"
: useParsianCarBodyLookup
? "ESG_CAR_BODY_INQUIRY"
: "TEJARAT_CAR_BODY_INQUIRY",
source: isVinInquiry
? useParsianCarBodyLookup
? "ESG_CAR_BODY_VIN_INQUIRY"
: "TEJARAT_CAR_BODY_VIN_INQUIRY"
: useParsianCarBodyLookup
? "ESG_CAR_BODY_INQUIRY"
: "TEJARAT_CAR_BODY_INQUIRY",
...result,
};
}
if (isVinInquiry) {
const raw = await this.lookupsService.findLastProcessedCarPolicy(
"car-body",
{
nationalCode: String(userDetail.nationalCodeOfInsurer),
vin: plateOrVin,
},
);
if (useParsianCarBodyLookup) {
this.assertParsianCarBodyLookupMatchesDeployment();
}
return {
source: useParsianCarBodyLookup
? "ESG_CAR_BODY_VIN_INQUIRY"
: "TEJARAT_CAR_BODY_VIN_INQUIRY",
raw,
mapped: mapEsgCarBodyPolicyToInquiry(raw),
};
}
if (!useParsianCarBodyLookup) {
const result = await this.getTejaratCarBodyInquiry(
userDetail as SandHubDetailDto,
@@ -962,28 +987,18 @@ export class SandHubService {
);
this.assertInsuranceMatchesDeployment(result.mapped, "CAR_BODY");
return {
source:
typeof userDetail.plate === "string"
? "TEJARAT_CAR_BODY_VIN_INQUIRY"
: "TEJARAT_CAR_BODY_INQUIRY",
source: "TEJARAT_CAR_BODY_INQUIRY",
...result,
};
}
const plateOrVin = userDetail.plate;
const query =
typeof plateOrVin === "string"
? {
nationalCode: String(userDetail.nationalCodeOfInsurer),
vin: plateOrVin,
}
: {
nationalCode: String(userDetail.nationalCodeOfInsurer),
plaqueLeft: String(plateOrVin.leftDigits),
plaqueLetter: String(plateOrVin.centerAlphabet),
plaqueRight: String(plateOrVin.centerDigits),
plaqueSerial: String(plateOrVin.ir),
};
const query = {
nationalCode: String(userDetail.nationalCodeOfInsurer),
plaqueLeft: String(plateOrVin.leftDigits),
plaqueLetter: String(plateOrVin.centerAlphabet),
plaqueRight: String(plateOrVin.centerDigits),
plaqueSerial: String(plateOrVin.ir),
};
const raw = await this.lookupsService.findLastProcessedCarPolicy(
"car-body",
query,
@@ -991,10 +1006,7 @@ export class SandHubService {
this.assertParsianCarBodyLookupMatchesDeployment();
return {
source:
typeof plateOrVin === "string"
? "ESG_CAR_BODY_VIN_INQUIRY"
: "ESG_CAR_BODY_INQUIRY",
source: "ESG_CAR_BODY_INQUIRY",
raw,
mapped: mapEsgCarBodyPolicyToInquiry(raw),
};
@@ -1109,16 +1121,19 @@ export class SandHubService {
* `buildMockPlateInquiryRaw` so the downstream mapper (`mapEsgPolicyByPlateToOldFormat`)
* can normalise it into the same `{ raw, mapped }` contract used by the plate path.
*
* @param chassisNo - 17-character VIN / chassis number
* @param identity - policyholder national code and 17-character VIN/chassis
* @param options - optional per-tenant client scope
*/
async getPolicyByChassisInquiry(
chassisNo: string,
identity: { nationalCode: string; chassis: string },
options?: SandHubInquiryOptions,
): Promise<{ raw: any; mapped: any }> {
const baseUrl = process.env.ESG_URL ?? "http://192.168.20.22:8085";
const requestUrl = `${baseUrl}/inquiry/policyByChassis`;
const requestPayload = { chassisNo };
const requestPayload = {
nationalCode: String(identity.nationalCode),
chassis: String(identity.chassis),
};
const live = await this.isInquiryLive("vinChassis", options);
@@ -1126,7 +1141,7 @@ export class SandHubService {
const ctx = await this.mockCompanyContext(options);
const raw = this.buildMockPlateInquiryRaw(ctx);
this.logger.debug(
`[MOCK] getPolicyByChassisInquiry chassisNo=${chassisNo}`,
`[MOCK] getPolicyByChassisInquiry nationalCode=${identity.nationalCode} chassis=${identity.chassis}`,
);
const mapped = this.mapEsgPolicyByPlateToOldFormat(raw);
this.enforceDeploymentClientMatch(mapped, "THIRD_PARTY", options);