import { BadRequestException } from "@nestjs/common"; import { BlameRequestType } from "src/Types&Enums/blame-request-management/blameRequestType.enum"; import { InquiryParticipantRole, VehicleRegistrationState, } from "src/common/dto/inquiry-participants.dto"; import { isMappedPolicyCurrent, normalizeInquirySubmission, participantForRole, participantForStoredPartyRole, resolveInquiryParticipants, resolveInquirySubjects, resolveInquiryVehicle, runCurrentPlateInquiry, sanitizeStoredInquiryParticipants, } from "./inquiry-participant-resolver"; describe("inquiry participant resolver", () => { it("links several roles to one explicitly shared person", () => { const resolved = resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, { driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: true, licenseNumber: "123456789", licenseType: "1", }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { sameAs: InquiryParticipantRole.VEHICLE_OWNER, }, }); expect(resolved.participants).toHaveLength(1); expect(resolved.roles).toEqual({ driver: "DRIVER", vehicleOwner: "DRIVER", thirdPartyPolicyholder: "DRIVER", }); }); it("requires both previous plate and VIN for a recent transfer", () => { expect(() => resolveInquiryVehicle({ registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, }), ).toThrow(BadRequestException); }); it("requires the previous policyholder national code for a recent transfer", () => { expect(() => resolveInquiryVehicle({ registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, previousPlate: { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }, vin: "NAAM01E15HK123456", }), ).toThrow("کد ملی بیمه‌گذار قبلی"); }); it("defaults an omitted registration state to CURRENT", () => { expect( resolveInquiryVehicle({ currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, }).registrationState, ).toBe(VehicleRegistrationState.CURRENT); }); it("requires an exact 17-character VIN whenever VIN is provided", () => { expect(() => resolveInquiryVehicle({ registrationState: VehicleRegistrationState.CURRENT, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, vin: "TOO-SHORT", }), ).toThrow("شماره شاسی (VIN) باید دقیقاً ۱۷ کاراکتر باشد."); }); it("rejects an incomplete current plate", () => { expect(() => resolveInquiryVehicle({ currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "", ir: "22", }, }), ).toThrow("سه رقم میانی پلاک در پلاک فعلی الزامی است."); }); it("rejects invalid vehicle choice values", () => { expect(() => resolveInquiryVehicle({ registrationState: "SOLD" as any, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, }), ).toThrow("وضعیت پلاک خودرو باید «فعلی» یا «تازه تعویض‌شده» باشد."); expect(() => resolveInquiryVehicle({ currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, isNewCar: "false" as any, }), ).toThrow("وضعیت صفر بودن خودرو نامعتبر است."); }); it("rejects a previous policyholder national code for a current registration", () => { expect(() => resolveInquiryVehicle({ registrationState: VehicleRegistrationState.CURRENT, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, previousPolicyholderNationalCode: "0098765432", }), ).toThrow(BadRequestException); }); it("rejects the removed flat inquiry contract", () => { expect(() => resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, { nationalCodeOfDriver: "0012345678", driverBirthday: "1370/01/01", driverLicense: "123456789", nationalCodeOfInsurer: "0098765432", insurerBirthday: "1360/02/02", driverIsInsurer: false, } as any), ).toThrow(BadRequestException); }); it("rejects phone numbers in participant inquiry identity", () => { expect(() => resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, { driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: false, phoneNumber: "09120000000", }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { sameAs: InquiryParticipantRole.DRIVER, }, } as any), ).toThrow(BadRequestException); }); it("keeps third-party and car-body policyholders distinct", () => { const resolved = resolveInquiryParticipants(BlameRequestType.CAR_BODY, { driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: false, }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { nationalCode: "0023456789", birthday: "1360/02/02", }, carBodyPolicyholder: { nationalCode: "0034567890", birthday: "1350/03/03", }, }); expect( participantForRole( resolved, InquiryParticipantRole.THIRD_PARTY_POLICYHOLDER, )?.nationalCode, ).toBe("0023456789"); expect( participantForRole(resolved, InquiryParticipantRole.CAR_BODY_POLICYHOLDER) ?.nationalCode, ).toBe("0034567890"); }); it("projects role-complete input onto the existing inquiry fields", () => { const normalized = normalizeInquirySubmission(BlameRequestType.CAR_BODY, { vehicle: { currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, }, driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: true, licenseNumber: "D-1", licenseType: "1", }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { nationalCode: "0023456789", birthday: "1360/02/02", }, carBodyPolicyholder: { nationalCode: "0034567890", birthday: "1350/03/03", }, }); expect(normalized.dto.nationalCodeOfInsurer).toBe("0023456789"); expect(normalized.dto.nationalCodeOfDriver).toBe("0012345678"); expect(normalized.carBodyPolicyholder?.nationalCode).toBe("0034567890"); expect(normalized.vehicleOwner?.nationalCode).toBe("0012345678"); }); it("routes each inquiry to its domain participant", () => { const normalized = normalizeInquirySubmission(BlameRequestType.CAR_BODY, { vehicle: { currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, }, driver: { nationalCode: "0011111111", birthday: "1370/01/01", hasDrivingLicense: false, }, vehicleOwner: { nationalCode: "0022222222", birthday: "1365/02/02", }, thirdPartyPolicyholder: { nationalCode: "0033333333", birthday: "1360/03/03", }, carBodyPolicyholder: { nationalCode: "0044444444", birthday: "1355/04/04", }, }); expect(resolveInquirySubjects(normalized)).toEqual({ thirdPartyPolicyNationalCode: "0033333333", carBodyPolicyNationalCode: "0044444444", shebaNationalCode: "0022222222", driverNationalCode: "0011111111", }); }); it("resolves a persisted vehicle owner for later Sheba validation", () => { const party = { participants: [ { participantId: "DRIVER", nationalCode: "0011111111" }, { participantId: "VEHICLE_OWNER", nationalCode: "0022222222" }, ], participantRoles: { driver: "DRIVER", vehicleOwner: "VEHICLE_OWNER", thirdPartyPolicyholder: "DRIVER", }, }; expect( participantForStoredPartyRole(party, InquiryParticipantRole.VEHICLE_OWNER) ?.nationalCode, ).toBe("0022222222"); }); it("requires the driver's licence status in the new contract", () => { expect(() => resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, { driver: { nationalCode: "0012345678", birthday: "1370/01/01" }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { sameAs: InquiryParticipantRole.VEHICLE_OWNER, }, }), ).toThrow(BadRequestException); }); it("runs only one inquiry for the current plate", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const query = jest.fn().mockResolvedValue({ mapped: { CompanyName: "پارسیان" }, }); const result = await runCurrentPlateInquiry<{ mapped: { CompanyName?: string }; }>({ currentPlate, vin: "NAAM01E15HK123456", query, isUsable: (value) => !!value.mapped.CompanyName, }); expect(query).toHaveBeenCalledTimes(1); expect(query).toHaveBeenCalledWith(currentPlate); expect(result.plateKind).toBe("CURRENT"); expect(result.attempts).toMatchObject([ { plateKind: "CURRENT", succeeded: true, usable: true }, ]); expect(result.attempts[0]).toMatchObject({ plate: currentPlate, vin: "NAAM01E15HK123456", }); }); it("rejects a car-body policyholder on a third-party case", () => { expect(() => resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, { driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: false, }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { sameAs: InquiryParticipantRole.VEHICLE_OWNER, }, carBodyPolicyholder: { nationalCode: "0034567890", birthday: "1350/03/03", }, }), ).toThrow(BadRequestException); }); it("does not accept a previous plate unless recent transfer is declared", () => { expect(() => resolveInquiryVehicle({ registrationState: VehicleRegistrationState.CURRENT, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, previousPlate: { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }, }), ).toThrow(BadRequestException); }); it("rejects sameAs together with any person-specific fields", () => { expect(() => resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, { driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: false, }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER, fullName: "Duplicate details must not be silently discarded", }, thirdPartyPolicyholder: { sameAs: InquiryParticipantRole.DRIVER, }, }), ).toThrow(BadRequestException); }); it("rejects conflicting legacy and structured current plates", () => { expect(() => normalizeInquirySubmission(BlameRequestType.THIRD_PARTY, { plate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, vehicle: { registrationState: VehicleRegistrationState.CURRENT, currentPlate: { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }, }, driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: false, }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { sameAs: InquiryParticipantRole.DRIVER, }, }), ).toThrow(BadRequestException); }); it("treats an expired policy result as stale", () => { expect(isMappedPolicyCurrent({ EndDate: "1404/01/01" }, "2026-09-13")).toBe( false, ); expect(isMappedPolicyCurrent({ EndDate: "1406/01/01" }, "2026-09-13")).toBe( true, ); }); it("rejects a stale current policy without trying another plate", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const query = jest.fn().mockResolvedValue({ mapped: { CompanyName: "پارسیان", EndDate: "1404/01/01" }, }); await expect( runCurrentPlateInquiry<{ mapped: Record }>({ currentPlate, query, isUsable: (value) => !!value.mapped.CompanyName && isMappedPolicyCurrent(value.mapped, "2026-09-13"), }), ).rejects.toMatchObject({ attempts: [{ plateKind: "CURRENT", succeeded: true, usable: false }], }); expect(query).toHaveBeenCalledTimes(1); }); it("retains the current-plate audit attempt when the result is unusable", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; await expect( runCurrentPlateInquiry({ currentPlate, vin: "NAAM01E15HK123456", query: async () => ({ mapped: { CompanyName: "پارسیان" } }), isUsable: () => false, }), ).rejects.toMatchObject({ attempts: [{ plateKind: "CURRENT", succeeded: true, usable: false }], }); }); it("preserves a mapped provider message when the current result is unusable", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; await expect( runCurrentPlateInquiry({ currentPlate, query: async () => ({ mapped: { Error: { Message: "رکوردی یافت نشد" } }, }), isUsable: () => false, errorMessage: (value) => value.mapped.Error.Message, }), ).rejects.toThrow("رکوردی یافت نشد"); }); it("retains one failed current-plate attempt after a provider outage", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const query = jest.fn().mockRejectedValue( Object.assign(new Error("upstream timeout"), { code: "ETIMEDOUT", }), ); await expect( runCurrentPlateInquiry({ currentPlate, vin: "NAAM01E15HK123456", query, isUsable: () => false, }), ).rejects.toThrow("upstream timeout"); expect(query).toHaveBeenCalledTimes(1); }); it("rejects the removed unknown policyholder option", () => { const input = { driver: { nationalCode: "0012345678", birthday: "1370/01/01", hasDrivingLicense: false, }, vehicleOwner: { sameAs: InquiryParticipantRole.DRIVER }, thirdPartyPolicyholder: { unknown: true }, }; expect(() => resolveInquiryParticipants(BlameRequestType.THIRD_PARTY, input as any), ).toThrow("ثبت بیمه‌گذار شخص ثالث به‌صورت نامشخص امکان‌پذیر نیست."); }); it("strips the removed unknown field from historical participant output", () => { expect( sanitizeStoredInquiryParticipants([ { participantId: "THIRD_PARTY_POLICYHOLDER", nationalCode: "0012345678", unknown: true, }, ]), ).toEqual([ { participantId: "THIRD_PARTY_POLICYHOLDER", nationalCode: "0012345678", }, ]); }); });