enforced matching client id for moving on with the case

This commit is contained in:
SepehrYahyaee
2026-09-07 15:06:06 +03:30
parent 7e3b308572
commit 229957e283
4 changed files with 317 additions and 45 deletions

View File

@@ -134,6 +134,30 @@ function formatJalaliCompact(raw: number | string | null | undefined): string |
export class RequestManagementService { export class RequestManagementService {
private readonly logger = new Logger(RequestManagementService.name); private readonly logger = new Logger(RequestManagementService.name);
/**
* Only the guilty (currently first) party's THIRD_PARTY policy must belong
* to this deployment. CAR_BODY flows deliberately do not constrain that
* separate third-party policy; their car-body lookup is checked on its own.
*/
private policyInquiryOptions(
requestType: BlameRequestType | string,
partyRole: PartyRole,
clientId?: string,
) {
const enforceDeploymentClientMatch =
requestType === BlameRequestType.THIRD_PARTY &&
partyRole === PartyRole.FIRST;
if (!clientId && !enforceDeploymentClientMatch) return undefined;
return {
...(clientId ? { clientId } : {}),
...(enforceDeploymentClientMatch
? { enforceDeploymentClientMatch: true }
: {}),
};
}
private stepKeyToPartyRole(stepKey: WorkflowStep): PartyRole { private stepKeyToPartyRole(stepKey: WorkflowStep): PartyRole {
if (String(stepKey).startsWith("FIRST_")) return PartyRole.FIRST; if (String(stepKey).startsWith("FIRST_")) return PartyRole.FIRST;
if (String(stepKey).startsWith("SECOND_")) return PartyRole.SECOND; if (String(stepKey).startsWith("SECOND_")) return PartyRole.SECOND;
@@ -1283,9 +1307,11 @@ export class RequestManagementService {
const inquiryClientId = party.person?.clientId const inquiryClientId = party.person?.clientId
? String(party.person.clientId) ? String(party.person.clientId)
: undefined; : undefined;
const inquiryOptions = inquiryClientId const inquiryOptions = this.policyInquiryOptions(
? { clientId: inquiryClientId } req.type,
: undefined; role,
inquiryClientId,
);
try { try {
const inquiry = await this.sandHubService.getTejaratBlockInquiry( const inquiry = await this.sandHubService.getTejaratBlockInquiry(
{ {
@@ -1513,15 +1539,10 @@ export class RequestManagementService {
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) { if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
let carBodyInfo: any; let carBodyInfo: any;
try { try {
carBodyInfo = await this.sandHubService.getCarBodyInquiry( carBodyInfo = await this.sandHubService.getCarBodyInquiry({
{
nationalCodeOfInsurer: body.nationalCodeOfInsurer, nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.plate, plate: body.plate,
}, });
resolvedClientId
? { clientId: String(resolvedClientId) }
: inquiryOptions,
);
this.recordPartyCaseInquiryStatus(req, "carBody", role, true, { this.recordPartyCaseInquiryStatus(req, "carBody", role, true, {
source: carBodyInfo.source, source: carBodyInfo.source,
raw: carBodyInfo.raw, raw: carBodyInfo.raw,
@@ -1763,9 +1784,11 @@ export class RequestManagementService {
const inquiryClientId = party.person?.clientId const inquiryClientId = party.person?.clientId
? String(party.person.clientId) ? String(party.person.clientId)
: undefined; : undefined;
const inquiryOptions = inquiryClientId const inquiryOptions = this.policyInquiryOptions(
? { clientId: inquiryClientId } req.type,
: undefined; role,
inquiryClientId,
);
let inquiryRaw: any; let inquiryRaw: any;
let inquiryMapped: any; let inquiryMapped: any;
@@ -1952,6 +1975,79 @@ export class RequestManagementService {
inquiryMapped?.HEndDte || inquiryMapped?.HEndDte ||
inquiryMapped?.persianEndDate; inquiryMapped?.persianEndDate;
// CAR_BODY eligibility is independent of the third-party policy above.
// The VIN flow must make the same deployment-scoped lookup as the plate
// flow before the case is allowed to advance.
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
try {
const carBodyInfo = await this.sandHubService.getCarBodyInquiry({
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.vin,
});
this.recordPartyCaseInquiryStatus(req, "carBody", role, true, {
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
});
party.vehicle.inquiry = {
...party.vehicle.inquiry,
carBody: {
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
},
};
const m = carBodyInfo.mapped as any;
(party.insurance as any).carBodyInsurance = {
policyNumber: m.policyNumber ?? null,
companyId: m.companyId ?? m.CompanyCode ?? null,
companyName: m.CompanyName ?? null,
insurerName: m.insurerName ?? null,
chassisNumber: m.ChassisNumberField ?? null,
vin: m.VinNumberField ?? null,
motorNumber: m.EngineNumberField ?? null,
startDate: m.StartDate ?? null,
endDate: m.EndDate ?? null,
issueDate: m.IssueDate ?? null,
noLossYearsCount: m.noLossYearsCount ?? null,
lossDocuments: m.lossDocuments ?? [],
};
const carBodyCompanyCode = m.companyId ?? m.CompanyCode;
const carBodyCompanyName = m.CompanyName ?? m.companyPersianName;
if (carBodyCompanyCode && carBodyCompanyName) {
const carBodyClient =
await this.clientService.findOrCreateClientByCompanyCode(
carBodyCompanyCode,
carBodyCompanyName,
);
const carBodyClientId =
(carBodyClient as any)?._id ?? (carBodyClient as any)?._doc?._id;
if (carBodyClientId) party.person.clientId = carBodyClientId;
}
} catch (err: any) {
this.logger.error(
`[CAR_BODY] VIN inquiry failed for request=${req._id}: ${err?.message || err}`,
);
this.recordPartyCaseInquiryStatus(
req,
"carBody",
role,
false,
{},
err,
);
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
throw new HttpException(
"Car body inquiry failed",
HttpStatus.BAD_REQUEST,
);
}
}
// Advance workflow // Advance workflow
await this.advanceWorkflowToNext(req, stepKey); await this.advanceWorkflowToNext(req, stepKey);
@@ -2934,6 +3030,13 @@ export class RequestManagementService {
body: AddPlateDto, body: AddPlateDto,
partyType: "firstParty" | "secondParty", partyType: "firstParty" | "secondParty",
) { ) {
if (request.type === "THIRD_PARTY" && partyType === "firstParty") {
this.sandHubService.assertInsuranceMatchesDeployment(
sandHubReport,
"THIRD_PARTY",
);
}
const clientName = sandHubReport?.CompanyName; const clientName = sandHubReport?.CompanyName;
const companyCode = sandHubReport?.CompanyCode; const companyCode = sandHubReport?.CompanyCode;
@@ -3024,12 +3127,10 @@ export class RequestManagementService {
// For CAR_BODY type, persist the provider response and its mapped fields. // For CAR_BODY type, persist the provider response and its mapped fields.
if (request.type === "CAR_BODY" && partyType === "firstParty") { if (request.type === "CAR_BODY" && partyType === "firstParty") {
const carBodyInquiry = await this.sandHubService.getCarBodyInquiry( const carBodyInquiry = await this.sandHubService.getCarBodyInquiry({
{
nationalCodeOfInsurer: body.nationalCodeOfInsurer, nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.plate, plate: body.plate,
} as any, } as any);
);
const carBodyInfo = carBodyInquiry.mapped as any; const carBodyInfo = carBodyInquiry.mapped as any;
this.logger.log( this.logger.log(
@@ -6470,6 +6571,13 @@ export class RequestManagementService {
"secondParty and guiltyPartyPhoneNumber are required.", "secondParty and guiltyPartyPhoneNumber are required.",
); );
} }
if (
formData.guiltyPartyPhoneNumber !== formData.firstPartyPhoneNumber
) {
throw new BadRequestException(
"The first party is the guilty party in this flow.",
);
}
if (!formData?.expertDescription?.desc) { if (!formData?.expertDescription?.desc) {
throw new BadRequestException("expertDescription.desc is required."); throw new BadRequestException("expertDescription.desc is required.");
} }
@@ -6508,6 +6616,12 @@ export class RequestManagementService {
throw err; throw err;
} }
const sandHubReport = (sandHubResponse["_doc"] || sandHubResponse) as any; const sandHubReport = (sandHubResponse["_doc"] || sandHubResponse) as any;
if (role === PartyRole.FIRST) {
this.sandHubService.assertInsuranceMatchesDeployment(
sandHubReport,
"THIRD_PARTY",
);
}
this.recordPartyCaseInquiryStatus( this.recordPartyCaseInquiryStatus(
req, req,
"thirdParty", "thirdParty",
@@ -7119,15 +7233,13 @@ export class RequestManagementService {
); );
} }
// Validate guilty party phone number matches one of the parties // The first party is the guilty party in every supported THIRD_PARTY flow.
if (request.type === "THIRD_PARTY") { if (request.type === "THIRD_PARTY") {
const guiltyMatchesFirst = if (
formData.guiltyPartyPhoneNumber === formData.firstPartyPhoneNumber; formData.guiltyPartyPhoneNumber !== formData.firstPartyPhoneNumber
const guiltyMatchesSecond = ) {
formData.guiltyPartyPhoneNumber === formData.secondParty.phoneNumber;
if (!guiltyMatchesFirst && !guiltyMatchesSecond) {
throw new BadRequestException( throw new BadRequestException(
"Guilty party phone number must match either first or second party phone number", "The first party is the guilty party in this flow.",
); );
} }
} }
@@ -7199,6 +7311,10 @@ export class RequestManagementService {
nationalCodeOfInsurer: firstPartyPlate.nationalCodeOfInsurer, nationalCodeOfInsurer: firstPartyPlate.nationalCodeOfInsurer,
}); });
const sandHubReport = sandHubResponse["_doc"] || sandHubResponse; const sandHubReport = sandHubResponse["_doc"] || sandHubResponse;
this.sandHubService.assertInsuranceMatchesDeployment(
sandHubReport,
"THIRD_PARTY",
);
const clientName = const clientName =
sandHubReport?.CompanyName || sandHubReport?.LastCompanyName; sandHubReport?.CompanyName || sandHubReport?.LastCompanyName;
@@ -8693,7 +8809,7 @@ export class RequestManagementService {
const roleLabel = partyRole === PartyRole.FIRST ? "FIRST" : "SECOND"; const roleLabel = partyRole === PartyRole.FIRST ? "FIRST" : "SECOND";
let clientId: string | undefined; let clientId: string | undefined;
const inquiryOptions = (cid?: string) => const inquiryOptions = (cid?: string) =>
cid ? { clientId: cid } : undefined; this.policyInquiryOptions(req.type, partyRole, cid);
let inquiryRaw: any; let inquiryRaw: any;
let inquiryMapped: any; let inquiryMapped: any;
@@ -8813,13 +8929,10 @@ export class RequestManagementService {
partyRole === PartyRole.FIRST partyRole === PartyRole.FIRST
) { ) {
try { try {
const carBodyInfo = await this.sandHubService.getCarBodyInquiry( const carBodyInfo = await this.sandHubService.getCarBodyInquiry({
{
nationalCodeOfInsurer: partyData.nationalCodeOfInsurer, nationalCodeOfInsurer: partyData.nationalCodeOfInsurer,
plate: partyData.plate as any, plate: partyData.plate as any,
}, });
clientId ? { clientId } : undefined,
);
this.recordPartyCaseInquiryStatus(req, "carBody", partyRole, true, { this.recordPartyCaseInquiryStatus(req, "carBody", partyRole, true, {
source: carBodyInfo.source, source: carBodyInfo.source,
raw: carBodyInfo.raw, raw: carBodyInfo.raw,
@@ -9548,7 +9661,7 @@ export class RequestManagementService {
const roleLabel = partyRole === PartyRole.FIRST ? "FIRST" : "SECOND"; const roleLabel = partyRole === PartyRole.FIRST ? "FIRST" : "SECOND";
let clientId: string | undefined; let clientId: string | undefined;
const inquiryOptions = (cid?: string) => const inquiryOptions = (cid?: string) =>
cid ? { clientId: cid } : undefined; this.policyInquiryOptions(req.type, partyRole, cid);
let inquiryRaw: any; let inquiryRaw: any;
let inquiryMapped: any; let inquiryMapped: any;
@@ -9668,13 +9781,10 @@ export class RequestManagementService {
partyRole === PartyRole.FIRST partyRole === PartyRole.FIRST
) { ) {
try { try {
const carBodyInfo = await this.sandHubService.getCarBodyInquiry( const carBodyInfo = await this.sandHubService.getCarBodyInquiry({
{
nationalCodeOfInsurer: partyData.nationalCodeOfInsurer, nationalCodeOfInsurer: partyData.nationalCodeOfInsurer,
plate: partyData.vin as any, // VIN used as identifier for CAR_BODY plate: partyData.vin as any, // VIN used as identifier for CAR_BODY
}, });
clientId ? { clientId } : undefined,
);
this.recordPartyCaseInquiryStatus(req, "carBody", partyRole, true, { this.recordPartyCaseInquiryStatus(req, "carBody", partyRole, true, {
source: carBodyInfo.source, source: carBodyInfo.source,
raw: carBodyInfo.raw, raw: carBodyInfo.raw,

View File

@@ -9,6 +9,9 @@ export class SandHubInquiryOptionsDto {
"Insurer client Mongo ObjectId. When omitted, resolves from deployment CLIENT_ID env.", "Insurer client Mongo ObjectId. When omitted, resolves from deployment CLIENT_ID env.",
}) })
clientId?: string; clientId?: string;
/** Require the returned policy insurer to match the deployment CLIENT_ID. */
enforceDeploymentClientMatch?: boolean;
} }
export type SandHubInquiryOptions = SandHubInquiryOptionsDto; export type SandHubInquiryOptions = SandHubInquiryOptionsDto;

View File

@@ -1,4 +1,8 @@
import { SandHubService } from "./sand-hub.service"; import { SandHubService } from "./sand-hub.service";
import {
ForbiddenException,
ServiceUnavailableException,
} from "@nestjs/common";
import { ExternalInquirySettingsService } from "src/client/external-inquiry-settings.service"; import { ExternalInquirySettingsService } from "src/client/external-inquiry-settings.service";
import { SandHubDetailDto } from "./dto/sand-hub.dto"; import { SandHubDetailDto } from "./dto/sand-hub.dto";
@@ -34,7 +38,7 @@ describe("SandHubService inquiry mocks", () => {
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
delete process.env.CLIENT_ID; process.env.CLIENT_ID = "8";
delete process.env.FANAVARAN_CLIENT; delete process.env.FANAVARAN_CLIENT;
service = new SandHubService( service = new SandHubService(
httpService as any, httpService as any,
@@ -132,6 +136,87 @@ describe("SandHubService inquiry mocks", () => {
expect(result.mapped.PrntPlcyCmpDocNo).toBe("REAL-ESG-POLICY"); expect(result.mapped.PrntPlcyCmpDocNo).toBe("REAL-ESG-POLICY");
}); });
it("rejects a guilty third-party policy issued by another insurer", async () => {
process.env.CLIENT_ID = "15";
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
jest.spyOn(service as any, "makeTejaratRequest").mockResolvedValue({
CompanyCode: "8",
CompanyName: "بیمه پارسیان",
PrntPlcyCmpDocNo: "OTHER-INSURER-POLICY",
});
await expect(
service.getTejaratBlockInquiry(userDetail, {
enforceDeploymentClientMatch: true,
} as any),
).rejects.toBeInstanceOf(ForbiddenException);
});
it("allows an unchecked third-party policy from another insurer", async () => {
process.env.CLIENT_ID = "15";
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
jest.spyOn(service as any, "makeTejaratRequest").mockResolvedValue({
CompanyCode: "8",
CompanyName: "بیمه پارسیان",
});
await expect(service.getTejaratBlockInquiry(userDetail)).resolves.toEqual(
expect.objectContaining({
mapped: expect.objectContaining({ CompanyCode: "8" }),
}),
);
});
it("rejects a guilty VIN third-party policy issued by another insurer", async () => {
process.env.CLIENT_ID = "15";
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
jest.spyOn(service as any, "makeEsgRequest").mockResolvedValue({
success: true,
data: { CmpCod: "8", CmpNam: "بیمه پارسیان" },
});
await expect(
service.getPolicyByChassisInquiry("NAAR03HFFRDE07024", {
enforceDeploymentClientMatch: true,
}),
).rejects.toBeInstanceOf(ForbiddenException);
});
it("does not accept a policy when CLIENT_ID is not configured", async () => {
delete process.env.CLIENT_ID;
await expect(service.getCarBodyInquiry(userDetail)).rejects.toBeInstanceOf(
ServiceUnavailableException,
);
});
it("rejects a CAR_BODY policy from another insurer on the Parsian lookup route", async () => {
process.env.CLIENT_ID = "15";
process.env.FANAVARAN_CLIENT = "parsian";
externalInquirySettings.isInquiryLive.mockResolvedValue(true);
lookupsService.findLastProcessedCarPolicy.mockResolvedValue({
policy: { CINumber: "70019846985" },
customer: {},
vehicle: {},
});
await expect(service.getCarBodyInquiry(userDetail)).rejects.toBeInstanceOf(
ForbiddenException,
);
});
it("rejects a CAR_BODY policy from another insurer on the Tejarat lookup route", async () => {
process.env.CLIENT_ID = "15";
jest.spyOn(service, "getTejaratCarBodyInquiry").mockResolvedValue({
raw: { data: { companyId: "8" } },
mapped: { companyId: "8", CompanyCode: "8" },
});
await expect(service.getCarBodyInquiry(userDetail)).rejects.toBeInstanceOf(
ForbiddenException,
);
});
it("uses the processed CAR_BODY lookup when the active Fanavaran client is Parsian", async () => { it("uses the processed CAR_BODY lookup when the active Fanavaran client is Parsian", async () => {
process.env.FANAVARAN_CLIENT = "parsian"; process.env.FANAVARAN_CLIENT = "parsian";
externalInquirySettings.isInquiryLive.mockResolvedValue(true); externalInquirySettings.isInquiryLive.mockResolvedValue(true);

View File

@@ -2,6 +2,7 @@ import { HttpService } from "@nestjs/axios";
import { import {
BadGatewayException, BadGatewayException,
BadRequestException, BadRequestException,
ForbiddenException,
GatewayTimeoutException, GatewayTimeoutException,
Injectable, Injectable,
Logger, Logger,
@@ -89,6 +90,60 @@ export class SandHubService {
return resolveFanavaranClientKey() === "parsian"; return resolveFanavaranClientKey() === "parsian";
} }
/**
* A case may proceed only when the policy belongs to the insurer served by
* this deployment. Callers opt in for the guilty/first-party policy only.
*/
assertInsuranceMatchesDeployment(
mapped: Record<string, unknown> | null | undefined,
insuranceLine: "THIRD_PARTY" | "CAR_BODY",
): void {
const expectedClientCode = String(process.env.CLIENT_ID ?? "").trim();
if (!expectedClientCode) {
throw new ServiceUnavailableException(
"CLIENT_ID must be configured before insurance eligibility can be checked.",
);
}
const actualClientCode = String(
mapped?.CompanyCode ?? mapped?.companyId ?? mapped?.CompanyId ?? "",
).trim();
if (actualClientCode === expectedClientCode) return;
throw new ForbiddenException(
`${insuranceLine} policy insurer does not match this deployment.`,
);
}
private enforceDeploymentClientMatch(
mapped: Record<string, unknown>,
insuranceLine: "THIRD_PARTY" | "CAR_BODY",
options?: SandHubInquiryOptions,
): void {
if (options?.enforceDeploymentClientMatch) {
this.assertInsuranceMatchesDeployment(mapped, insuranceLine);
}
}
/**
* The processed Fanavaran CAR_BODY endpoint is a Parsian-only source and its
* response does not contain a reliable insurer company code. Treat the source
* itself as proof that the returned policy is Parsian.
*/
private assertParsianCarBodyLookupMatchesDeployment(): void {
const expectedClientCode = String(process.env.CLIENT_ID ?? "").trim();
if (!expectedClientCode) {
throw new ServiceUnavailableException(
"CLIENT_ID must be configured before insurance eligibility can be checked.",
);
}
if (expectedClientCode === "8") return;
throw new ForbiddenException(
"CAR_BODY policy insurer does not match this deployment.",
);
}
/** Fixed plate/insurance inquiry payload used everywhere we mock block-inquiry style APIs. */ /** Fixed plate/insurance inquiry payload used everywhere we mock block-inquiry style APIs. */
private buildMockPlateInquiryRaw( private buildMockPlateInquiryRaw(
ctx: MockInquiryCompanyContext, ctx: MockInquiryCompanyContext,
@@ -779,6 +834,11 @@ export class SandHubService {
ir: String(userDetail.plate.ir), ir: String(userDetail.plate.ir),
}); });
if (offlineHit) { if (offlineHit) {
this.enforceDeploymentClientMatch(
offlineHit.mapped,
"THIRD_PARTY",
options,
);
return { return {
raw: offlineHit.raw, raw: offlineHit.raw,
mapped: offlineHit.mapped, mapped: offlineHit.mapped,
@@ -818,6 +878,7 @@ export class SandHubService {
); );
} }
const mapped = this.mapEsgPolicyByPlateToOldFormat(raw); const mapped = this.mapEsgPolicyByPlateToOldFormat(raw);
this.enforceDeploymentClientMatch(mapped, "THIRD_PARTY", options);
return { raw, mapped }; return { raw, mapped };
} }
@@ -846,6 +907,7 @@ export class SandHubService {
); );
} }
const mapped = this.mapNewApiResponseToOldFormat(raw); const mapped = this.mapNewApiResponseToOldFormat(raw);
this.enforceDeploymentClientMatch(mapped, "THIRD_PARTY", options);
return { raw, mapped }; return { raw, mapped };
} }
@@ -874,6 +936,7 @@ export class SandHubService {
userDetail as SandHubDetailDto, userDetail as SandHubDetailDto,
options, options,
); );
this.assertInsuranceMatchesDeployment(result.mapped, "CAR_BODY");
return { return {
source: source:
typeof userDetail.plate === "string" typeof userDetail.plate === "string"
@@ -890,6 +953,7 @@ export class SandHubService {
userDetail as SandHubDetailDto, userDetail as SandHubDetailDto,
options, options,
); );
this.assertParsianCarBodyLookupMatchesDeployment();
return { return {
source: source:
typeof userDetail.plate === "string" typeof userDetail.plate === "string"
@@ -917,6 +981,7 @@ export class SandHubService {
"car-body", "car-body",
query, query,
); );
this.assertParsianCarBodyLookupMatchesDeployment();
return { return {
source: source:
@@ -1057,6 +1122,7 @@ export class SandHubService {
`[MOCK] getPolicyByChassisInquiry chassisNo=${chassisNo}`, `[MOCK] getPolicyByChassisInquiry chassisNo=${chassisNo}`,
); );
const mapped = this.mapEsgPolicyByPlateToOldFormat(raw); const mapped = this.mapEsgPolicyByPlateToOldFormat(raw);
this.enforceDeploymentClientMatch(mapped, "THIRD_PARTY", options);
return { raw, mapped }; return { raw, mapped };
} }
@@ -1067,6 +1133,7 @@ export class SandHubService {
options, options,
); );
const mapped = this.mapEsgPolicyByPlateToOldFormat(raw); const mapped = this.mapEsgPolicyByPlateToOldFormat(raw);
this.enforceDeploymentClientMatch(mapped, "THIRD_PARTY", options);
return { raw, mapped }; return { raw, mapped };
} }
@@ -1297,6 +1364,7 @@ export class SandHubService {
} }
const result = this.mapNewApiResponseToOldFormat(response); const result = this.mapNewApiResponseToOldFormat(response);
this.enforceDeploymentClientMatch(result, "THIRD_PARTY", options);
// if (result.usgCod !== "8") { // if (result.usgCod !== "8") {
// throw new Error("خودرو شما شخصی / سواری نمی باشد") // throw new Error("خودرو شما شخصی / سواری نمی باشد")
@@ -1304,6 +1372,12 @@ export class SandHubService {
return result; return result;
} catch (err) { } catch (err) {
if (
err instanceof ForbiddenException ||
err instanceof ServiceUnavailableException
) {
throw err;
}
throw new Error(err); throw new Error(err);
} }
} }