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 { assertPreviousPlateInquiryMatchesVin, isMappedPolicyCurrent, normalizeInquirySubmission, participantForRole, participantForStoredPartyRole, resolveInquiryParticipants, resolveInquirySubjects, resolveInquiryVehicle, runPlateInquiryWithFallback, sanitizeStoredInquiryParticipants, vehiclePlateCandidates, } 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("previousPolicyholderNationalCode"); }); 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("vehicle.vin must contain exactly 17 characters."); }); it("rejects an incomplete current plate", () => { expect(() => resolveInquiryVehicle({ currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "", ir: "22", }, }), ).toThrow("vehicle.currentPlate.centerDigits is required."); }); it("rejects invalid vehicle choice values", () => { expect(() => resolveInquiryVehicle({ registrationState: "SOLD" as any, currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, }), ).toThrow("vehicle.registrationState must be CURRENT or RECENTLY_TRANSFERRED."); expect(() => resolveInquiryVehicle({ currentPlate: { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }, isNewCar: "false" as any, }), ).toThrow("vehicle.isNewCar must be a boolean."); }); 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("orders the current plate before the previous-plate fallback", () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const previousPlate = { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }; expect( vehiclePlateCandidates({ registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate, previousPlate, vin: "NAAM01E15HK123456", previousPolicyholderNationalCode: "0098765432", }), ).toEqual([ { kind: "CURRENT", plate: currentPlate }, { kind: "PREVIOUS", plate: previousPlate }, ]); }); it("rejects a previous-plate result for another chassis", () => { expect(() => assertPreviousPlateInquiryMatchesVin("NAAM01E15HK123456", { VinNumberField: "DIFFERENTVIN00001", }), ).toThrow(BadRequestException); }); 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("falls back to the previous plate and accepts only a matching VIN", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const previousPlate = { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }; const query = jest .fn() .mockRejectedValueOnce(new Error("not found")) .mockResolvedValueOnce({ mapped: { VinNumberField: "NAAM01E15HK123456", CompanyName: "پارسیان" }, }); const result = await runPlateInquiryWithFallback<{ mapped: { VinNumberField?: string; CompanyName?: string }; }>({ vehicle: { registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate, previousPlate, vin: "NAAM01E15HK123456", previousPolicyholderNationalCode: "0098765432", }, fallbackCurrentPlate: currentPlate, query, isUsable: (value) => !!value.mapped.CompanyName, mappedValue: (value) => value.mapped, }); expect(query).toHaveBeenCalledTimes(2); expect(query).toHaveBeenNthCalledWith(1, currentPlate, "CURRENT"); expect(query).toHaveBeenNthCalledWith(2, previousPlate, "PREVIOUS"); expect(result.plateKind).toBe("PREVIOUS"); expect(result.attempts).toMatchObject([ { plateKind: "CURRENT", succeeded: false, error: "not found" }, { plateKind: "PREVIOUS", succeeded: true, usable: true }, ]); expect(result.attempts[0]).toMatchObject({ plate: currentPlate, vin: "NAAM01E15HK123456", }); expect(result.attempts[1]).toMatchObject({ plate: previousPlate, 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("falls back from a stale current policy to a current previous-plate policy", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const previousPlate = { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }; const query = jest .fn() .mockResolvedValueOnce({ mapped: { CompanyName: "پارسیان", EndDate: "1404/01/01" }, }) .mockResolvedValueOnce({ mapped: { CompanyName: "پارسیان", EndDate: "1406/01/01", VinNumberField: "NAAM01E15HK123456", }, }); const result = await runPlateInquiryWithFallback<{ mapped: Record; }>({ vehicle: resolveInquiryVehicle({ registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate, previousPlate, vin: "NAAM01E15HK123456", previousPolicyholderNationalCode: "0098765432", }), fallbackCurrentPlate: currentPlate, query, isUsable: (value) => !!value.mapped.CompanyName && isMappedPolicyCurrent(value.mapped, "2026-09-13"), mappedValue: (value) => value.mapped, }); expect(result.plateKind).toBe("PREVIOUS"); expect(result.attempts[0]).toMatchObject({ plateKind: "CURRENT", succeeded: true, usable: false, }); }); it("rejects the result and retains audit attempts when every plate is unusable", async () => { const currentPlate = { leftDigits: "44", centerAlphabet: "ب", centerDigits: "111", ir: "22", }; const previousPlate = { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }; await expect( runPlateInquiryWithFallback({ vehicle: resolveInquiryVehicle({ registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate, previousPlate, vin: "NAAM01E15HK123456", previousPolicyholderNationalCode: "0098765432", }), fallbackCurrentPlate: currentPlate, query: async () => ({ mapped: { CompanyName: "پارسیان" } }), isUsable: () => false, mappedValue: (value) => value.mapped, }), ).rejects.toMatchObject({ attempts: [ { plateKind: "CURRENT", succeeded: true, usable: false }, { plateKind: "PREVIOUS", succeeded: true, usable: false }, ], }); }); it("does not use the previous plate after a transport or 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( runPlateInquiryWithFallback({ vehicle: resolveInquiryVehicle({ registrationState: VehicleRegistrationState.RECENTLY_TRANSFERRED, currentPlate, previousPlate: { leftDigits: "55", centerAlphabet: "ج", centerDigits: "222", ir: "33", }, vin: "NAAM01E15HK123456", previousPolicyholderNationalCode: "0098765432", }), fallbackCurrentPlate: currentPlate, query, isUsable: () => false, mappedValue: () => ({}), }), ).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("THIRD_PARTY_POLICYHOLDER does not support the unknown option."); }); 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", }, ]); }); });