Retain inquiry audit context on failure

This commit is contained in:
SepehrYahyaee
2026-09-13 11:42:20 +03:30
parent fe22e69351
commit 287978a555
3 changed files with 67 additions and 20 deletions

View File

@@ -230,10 +230,18 @@ describe("inquiry participant resolver", () => {
expect(query).toHaveBeenCalledTimes(2);
expect(result.plateKind).toBe("PREVIOUS");
expect(result.attempts).toEqual([
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", () => {

View File

@@ -421,6 +421,8 @@ export async function runPlateInquiryWithFallback<T>(options: {
plateKind: "CURRENT" | "PREVIOUS";
attempts: Array<{
plateKind: "CURRENT" | "PREVIOUS";
plate: InquiryVehicleInputDto["currentPlate"];
vin?: string;
succeeded: boolean;
usable?: boolean;
error?: string;
@@ -432,6 +434,8 @@ export async function runPlateInquiryWithFallback<T>(options: {
let lastError: unknown;
const attempts: Array<{
plateKind: "CURRENT" | "PREVIOUS";
plate: InquiryVehicleInputDto["currentPlate"];
vin?: string;
succeeded: boolean;
usable?: boolean;
error?: string;
@@ -446,6 +450,8 @@ export async function runPlateInquiryWithFallback<T>(options: {
if (!usable) {
attempts.push({
plateKind: candidate.kind,
plate: candidate.plate,
...(options.vehicle?.vin ? { vin: options.vehicle.vin } : {}),
succeeded: true,
usable: false,
});
@@ -464,6 +470,8 @@ export async function runPlateInquiryWithFallback<T>(options: {
}
attempts.push({
plateKind: candidate.kind,
plate: candidate.plate,
...(options.vehicle?.vin ? { vin: options.vehicle.vin } : {}),
succeeded: true,
usable: true,
});
@@ -477,6 +485,8 @@ export async function runPlateInquiryWithFallback<T>(options: {
if (!alreadyRecorded) {
attempts.push({
plateKind: candidate.kind,
plate: candidate.plate,
...(options.vehicle?.vin ? { vin: options.vehicle.vin } : {}),
succeeded: false,
error: error instanceof Error ? error.message : String(error),
});

View File

@@ -336,6 +336,18 @@ export class RequestManagementService {
}
}
private recordInquiryParticipantContext(
req: any,
role: PartyRole,
submission: NormalizedInquirySubmission<Record<string, any>>,
): void {
this.recordPartyCaseInquiryStatus(req, "participantContext", role, true, {
participants: submission.participants.participants,
participantRoles: submission.participants.roles,
vehicle: submission.vehicle,
});
}
private async getThirdPartyPlateInquiry(
submission: NormalizedInquirySubmission<Record<string, any>>,
options?: Record<string, any>,
@@ -587,7 +599,10 @@ export class RequestManagementService {
if (!req?._id || !req.inquiries) return;
try {
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
$set: {
inquiries: req.inquiries,
...(Array.isArray(req.parties) ? { parties: req.parties } : {}),
},
});
} catch (error: any) {
this.logger.error(
@@ -1791,9 +1806,7 @@ export class RequestManagementService {
{},
err,
);
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
await this.persistBlameInquiryAudit(req);
throw new HttpException("Inquiry failed", HttpStatus.BAD_REQUEST);
}
@@ -1808,9 +1821,7 @@ export class RequestManagementService {
raw: inquiryRaw,
mapped: inquiryMapped,
});
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
await this.persistBlameInquiryAudit(req);
throw new HttpException(
inquiryMapped.Error.Message || "Inquiry returned error",
HttpStatus.BAD_REQUEST,
@@ -1932,9 +1943,7 @@ export class RequestManagementService {
{},
err,
);
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
await this.persistBlameInquiryAudit(req);
this.throwCarBodyInquiryFailure(err);
}
@@ -2189,9 +2198,7 @@ export class RequestManagementService {
{},
err,
);
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
await this.persistBlameInquiryAudit(req);
throw new HttpException("VIN inquiry failed", HttpStatus.BAD_REQUEST);
}
@@ -2204,9 +2211,7 @@ export class RequestManagementService {
raw: inquiryRaw,
mapped: inquiryMapped,
});
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
await this.persistBlameInquiryAudit(req);
throw new HttpException(
inquiryMapped.Error.Message || "VIN inquiry returned error",
HttpStatus.BAD_REQUEST,
@@ -2363,9 +2368,7 @@ export class RequestManagementService {
{},
err,
);
await this.blameRequestDbService.findByIdAndUpdate(req._id, {
$set: { inquiries: req.inquiries },
});
await this.persistBlameInquiryAudit(req);
this.throwCarBodyInquiryFailure(err);
}
}
@@ -6832,6 +6835,18 @@ export class RequestManagementService {
formData.firstPartyPlate,
PartyRole.FIRST,
);
this.recordInquiryParticipantContext(
req,
PartyRole.FIRST,
inquirySubmission,
);
const existingFirstPartyIndex = this.getPartyIndex(req, PartyRole.FIRST);
if (existingFirstPartyIndex !== -1) {
this.applyInquiryParticipantsToParty(
req.parties[existingFirstPartyIndex],
inquirySubmission,
);
}
const firstPartyPlate = inquirySubmission.dto;
let sandHubReport: any;
try {
@@ -7130,6 +7145,14 @@ export class RequestManagementService {
plateDto,
role,
);
this.recordInquiryParticipantContext(req, role, inquirySubmission);
const existingPartyIndex = this.getPartyIndex(req, role);
if (existingPartyIndex !== -1) {
this.applyInquiryParticipantsToParty(
req.parties[existingPartyIndex],
inquirySubmission,
);
}
plateDto = inquirySubmission.dto;
const policyholderUnknown =
inquirySubmission.thirdPartyPolicyholder.unknown === true;
@@ -9667,6 +9690,7 @@ export class RequestManagementService {
}
if (inquiryMapped?.Error) {
await this.persistBlameInquiryAudit(req);
throw new BadRequestException(
inquiryMapped.Error.Message ||
`${roleLabel} party plate inquiry returned an error`,
@@ -9676,6 +9700,7 @@ export class RequestManagementService {
const clientName = inquiryMapped?.CompanyName;
const companyCode = inquiryMapped?.CompanyCode;
if (!clientName && !policyholderUnknown) {
await this.persistBlameInquiryAudit(req);
throw new BadRequestException(
`CompanyName missing from ${roleLabel} party inquiry response`,
);
@@ -9687,6 +9712,7 @@ export class RequestManagementService {
)
: null;
if (clientName && !client) {
await this.persistBlameInquiryAudit(req);
throw new BadRequestException(
`CompanyCode missing or invalid in ${roleLabel} party inquiry response`,
);
@@ -10517,6 +10543,7 @@ export class RequestManagementService {
}
if (inquiryMapped?.Error) {
await this.persistBlameInquiryAudit(req);
throw new BadRequestException(
inquiryMapped.Error.Message ||
`${roleLabel} party VIN inquiry returned an error`,
@@ -10526,6 +10553,7 @@ export class RequestManagementService {
const clientName = inquiryMapped?.CompanyName;
const companyCode = inquiryMapped?.CompanyCode;
if (!clientName) {
await this.persistBlameInquiryAudit(req);
throw new BadRequestException(
`CompanyName missing from ${roleLabel} party VIN inquiry response`,
);
@@ -10535,6 +10563,7 @@ export class RequestManagementService {
clientName,
);
if (!client) {
await this.persistBlameInquiryAudit(req);
throw new BadRequestException(
`CompanyCode missing or invalid in ${roleLabel} party VIN inquiry response`,
);