From 8b34e94de3a2f4ccd7887dd77aadd401eb2aae0d Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Sun, 6 Sep 2026 15:08:12 +0330 Subject: [PATCH 1/2] Fixed Car_Body inquiry for Parsian --- src/sand-hub/sand-hub.service.spec.ts | 23 +++++++++++++++++++++++ src/sand-hub/sand-hub.service.ts | 11 ++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/sand-hub/sand-hub.service.spec.ts b/src/sand-hub/sand-hub.service.spec.ts index 915623a..a5b9f89 100644 --- a/src/sand-hub/sand-hub.service.spec.ts +++ b/src/sand-hub/sand-hub.service.spec.ts @@ -32,6 +32,7 @@ describe("SandHubService inquiry mocks", () => { beforeEach(() => { jest.clearAllMocks(); delete process.env.CLIENT_ID; + delete process.env.FANAVARAN_CLIENT; service = new SandHubService( httpService as any, sandHubDbService as any, @@ -107,6 +108,28 @@ describe("SandHubService inquiry mocks", () => { expect(httpService.post).not.toHaveBeenCalled(); }); + it("uses the processed CAR_BODY lookup when the active Fanavaran client is Parsian", async () => { + process.env.FANAVARAN_CLIENT = "parsian"; + externalInquirySettings.isInquiryLive.mockResolvedValue(true); + lookupsService.findLastProcessedCarPolicy.mockResolvedValue({ + policy: { CINumber: "70019846985" }, + customer: {}, + vehicle: {}, + }); + const tejarat = jest + .spyOn(service, "getTejaratCarBodyInquiry") + .mockResolvedValue({ raw: { mocked: true }, mapped: {} }); + + const result = await service.getCarBodyInquiry(userDetail); + + expect(lookupsService.findLastProcessedCarPolicy).toHaveBeenCalledWith( + "car-body", + expect.objectContaining({ nationalCode: "1234567890" }), + ); + expect(tejarat).not.toHaveBeenCalled(); + expect(result.raw).not.toEqual({ mocked: true }); + }); + it("keeps ESG car-body inquiry in mock mode when the per-client toggle is off", async () => { process.env.CLIENT_ID = "8"; diff --git a/src/sand-hub/sand-hub.service.ts b/src/sand-hub/sand-hub.service.ts index 28b2f8a..4f2eedc 100644 --- a/src/sand-hub/sand-hub.service.ts +++ b/src/sand-hub/sand-hub.service.ts @@ -80,6 +80,15 @@ export class SandHubService { return String(process.env.CLIENT_ID ?? "") === "8"; } + /** + * The processed Fanavaran CAR_BODY lookup belongs only to the Parsian + * Fanavaran profile. Do not use the deployment-wide ESG selector here: + * `FANAVARAN_CLIENT=parsian` is valid even when CLIENT_ID is not 8. + */ + private shouldUseParsianCarBodyLookup(): boolean { + return resolveFanavaranClientKey() === "parsian"; + } + /** Fixed plate/insurance inquiry payload used everywhere we mock block-inquiry style APIs. */ private buildMockPlateInquiryRaw( ctx: MockInquiryCompanyContext, @@ -857,7 +866,7 @@ export class SandHubService { raw: any; mapped: Record; }> { - if (!this.shouldUseEsgInquiryProvider()) { + if (!this.shouldUseParsianCarBodyLookup()) { const result = await this.getTejaratCarBodyInquiry( userDetail as SandHubDetailDto, options, From 519967855e723ff9a685b404e02fd577651e6957 Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Mon, 7 Sep 2026 13:00:18 +0330 Subject: [PATCH 2/2] Fixed mock TP Inquiry --- src/sand-hub/sand-hub.service.spec.ts | 30 ++++++++++++++++-- src/sand-hub/sand-hub.service.ts | 45 ++++++++++++++------------- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/sand-hub/sand-hub.service.spec.ts b/src/sand-hub/sand-hub.service.spec.ts index a5b9f89..699f100 100644 --- a/src/sand-hub/sand-hub.service.spec.ts +++ b/src/sand-hub/sand-hub.service.spec.ts @@ -15,6 +15,9 @@ describe("SandHubService inquiry mocks", () => { const lookupsService = { findLastProcessedCarPolicy: jest.fn(), }; + const offlineInquiryService = { + findPlateInquiry: jest.fn(), + }; let service: SandHubService; @@ -38,12 +41,11 @@ describe("SandHubService inquiry mocks", () => { sandHubDbService as any, externalInquirySettings as unknown as ExternalInquirySettingsService, plateNormalizer as any, - { - findPlateInquiry: jest.fn().mockResolvedValue(null), - } as any, + offlineInquiryService as any, lookupsService as any, ); externalInquirySettings.isInquiryLive.mockResolvedValue(false); + offlineInquiryService.findPlateInquiry.mockResolvedValue(null); externalInquirySettings.getMockCompanyContext.mockResolvedValue({ companyId: "8", companyName: "بیمه پارسیان", @@ -108,6 +110,28 @@ describe("SandHubService inquiry mocks", () => { expect(httpService.post).not.toHaveBeenCalled(); }); + it("does not let an offline third-party seed override a live ESG inquiry", async () => { + process.env.CLIENT_ID = "8"; + externalInquirySettings.isInquiryLive.mockResolvedValue(true); + offlineInquiryService.findPlateInquiry.mockResolvedValue({ + source: "OFFLINE_SEED_INQUIRY", + raw: { mocked: true }, + mapped: { PrntPlcyCmpDocNo: "MOCK-POLICY" }, + }); + const esg = jest + .spyOn(service as any, "makeEsgRequest") + .mockResolvedValue({ + success: true, + data: { PrntCmpDocNo: "REAL-ESG-POLICY" }, + }); + + const result = await service.getTejaratBlockInquiry(userDetail); + + expect(esg).toHaveBeenCalled(); + expect(result.raw).not.toEqual({ mocked: true }); + expect(result.mapped.PrntPlcyCmpDocNo).toBe("REAL-ESG-POLICY"); + }); + it("uses the processed CAR_BODY lookup when the active Fanavaran client is Parsian", async () => { process.env.FANAVARAN_CLIENT = "parsian"; externalInquirySettings.isInquiryLive.mockResolvedValue(true); diff --git a/src/sand-hub/sand-hub.service.ts b/src/sand-hub/sand-hub.service.ts index 4f2eedc..d489e14 100644 --- a/src/sand-hub/sand-hub.service.ts +++ b/src/sand-hub/sand-hub.service.ts @@ -766,25 +766,30 @@ export class SandHubService { person?: Record; }; }> { - const offlineHit = await this.offlineInquiryService.findPlateInquiry({ - clientKey: resolveFanavaranClientKey(), - nationalCode: String(userDetail.nationalCodeOfInsurer), - leftDigits: String(userDetail.plate.leftDigits), - centerAlphabet: String(userDetail.plate.centerAlphabet), - centerDigits: String(userDetail.plate.centerDigits), - ir: String(userDetail.plate.ir), - }); - if (offlineHit) { - return { - raw: offlineHit.raw, - mapped: offlineHit.mapped, - offline: { - source: offlineHit.source, - fanavaranDriverId: offlineHit.fanavaranDriverId, - insurance: offlineHit.insurance, - person: offlineHit.person, - }, - }; + const live = await this.isInquiryLive("thirdPartyPlate", options); + // Offline records are a fallback for disabled inquiry mode only. They must + // never override a configured live ESG/Tejarat inquiry. + if (!live) { + const offlineHit = await this.offlineInquiryService.findPlateInquiry({ + clientKey: resolveFanavaranClientKey(), + nationalCode: String(userDetail.nationalCodeOfInsurer), + leftDigits: String(userDetail.plate.leftDigits), + centerAlphabet: String(userDetail.plate.centerAlphabet), + centerDigits: String(userDetail.plate.centerDigits), + ir: String(userDetail.plate.ir), + }); + if (offlineHit) { + return { + raw: offlineHit.raw, + mapped: offlineHit.mapped, + offline: { + source: offlineHit.source, + fanavaranDriverId: offlineHit.fanavaranDriverId, + insurance: offlineHit.insurance, + person: offlineHit.person, + }, + }; + } } const ctx = await this.mockCompanyContext(options); @@ -799,7 +804,6 @@ export class SandHubService { }; const requestUrl = `${baseUrl}/inquiry/policyByPlate`; - const live = await this.isInquiryLive("thirdPartyPlate", options); const raw = live ? await this.makeEsgRequest( requestUrl, @@ -828,7 +832,6 @@ export class SandHubService { }; const requestUrl = `${baseUrl}/block-inquiry-tejarat`; - const live = await this.isInquiryLive("thirdPartyPlate", options); const raw = live ? await this.makeTejaratRequest( requestUrl,