forked from Yara724/api
fix: align inquiry errors and expert review rules
This commit is contained in:
@@ -4,13 +4,63 @@ import {
|
||||
} from "./inquiry-error";
|
||||
|
||||
describe("inquiry error messages", () => {
|
||||
it("turns ESG not-found responses into a contextual plate message", () => {
|
||||
it("preserves a Persian ESG not-found response", () => {
|
||||
expect(
|
||||
getInquiryErrorMessage(
|
||||
{ success: false, message: "موردی یافت نشد" },
|
||||
"thirdPartyPlate",
|
||||
),
|
||||
).toBe("بیمهنامه شخص ثالثی مطابق پلاک و کد ملی واردشده یافت نشد.");
|
||||
).toBe("موردی یافت نشد");
|
||||
});
|
||||
|
||||
it.each([
|
||||
["RECORD_NOT_FOUND", "رکوردی یافت نشد", "Provider request failed"],
|
||||
[
|
||||
"INQUIRY_NO_MATCH",
|
||||
"نتیجهای مطابق با اطلاعات وارد شده یافت نشد",
|
||||
"Inquiry returned no matching result",
|
||||
],
|
||||
])(
|
||||
"prefers ESG messageFa for %s over the technical message",
|
||||
(code, messageFa, message) => {
|
||||
expect(
|
||||
getInquiryErrorMessage(
|
||||
{
|
||||
error: {
|
||||
code,
|
||||
message,
|
||||
messageFa,
|
||||
providerMessage: message,
|
||||
providerCode: code,
|
||||
},
|
||||
attemptSummary: {
|
||||
attempts: [{ code, message, messageFa }],
|
||||
},
|
||||
},
|
||||
"thirdPartyPlate",
|
||||
),
|
||||
).toBe(messageFa);
|
||||
},
|
||||
);
|
||||
|
||||
it("finds messageFa inside an HTTP response envelope", () => {
|
||||
expect(
|
||||
getInquiryErrorMessage(
|
||||
{
|
||||
response: {
|
||||
status: 404,
|
||||
data: {
|
||||
error: {
|
||||
code: "RECORD_NOT_FOUND",
|
||||
message: "Provider request failed",
|
||||
messageFa: "رکوردی یافت نشد",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"thirdPartyPlate",
|
||||
),
|
||||
).toBe("رکوردی یافت نشد");
|
||||
});
|
||||
|
||||
it("distinguishes VIN and car-body not-found failures", () => {
|
||||
|
||||
@@ -87,7 +87,25 @@ export function inquiryErrorStatus(error: unknown): number | undefined {
|
||||
}
|
||||
|
||||
export function extractInquiryProviderMessage(error: unknown): string {
|
||||
for (const record of errorRecords(error)) {
|
||||
const records = errorRecords(error);
|
||||
|
||||
// The normalized ESG/Parsian envelope carries the safe user-facing text in
|
||||
// messageFa while `message` and `providerMessage` may remain technical.
|
||||
// Search every envelope level for that explicit Persian field before
|
||||
// considering generic message fields on an outer object.
|
||||
for (const record of records) {
|
||||
for (const key of [
|
||||
"messageFa",
|
||||
"MessageFa",
|
||||
"messageFA",
|
||||
"persianMessage",
|
||||
] as const) {
|
||||
const message = cleanMessage(record[key]);
|
||||
if (message) return message;
|
||||
}
|
||||
}
|
||||
|
||||
for (const record of records) {
|
||||
for (const key of ["message", "Message", "detail", "title"] as const) {
|
||||
const message = cleanMessage(record[key]);
|
||||
if (message) return message;
|
||||
@@ -128,13 +146,21 @@ export function isInquiryTimeout(error: unknown): boolean {
|
||||
const hasPersian = (value: string): boolean => /[\u0600-\u06ff]/.test(value);
|
||||
|
||||
const isNotFound = (error: unknown, message: string): boolean => {
|
||||
const root = asRecord(error);
|
||||
const responseData = asRecord(asRecord(root?.response)?.data);
|
||||
const code = String(root?.code ?? responseData?.code ?? "").toUpperCase();
|
||||
const codes = errorRecords(error).flatMap((record) =>
|
||||
[record.code, record.providerCode]
|
||||
.map((code) => String(code ?? "").toUpperCase())
|
||||
.filter(Boolean),
|
||||
);
|
||||
return (
|
||||
inquiryErrorStatus(error) === 404 ||
|
||||
["NOT_FOUND", "POLICY_NOT_FOUND", "NO_POLICY", "RECORD_NOT_FOUND"].includes(
|
||||
code,
|
||||
codes.some((code) =>
|
||||
[
|
||||
"NOT_FOUND",
|
||||
"POLICY_NOT_FOUND",
|
||||
"NO_POLICY",
|
||||
"RECORD_NOT_FOUND",
|
||||
"INQUIRY_NO_MATCH",
|
||||
].includes(code),
|
||||
) ||
|
||||
/\bnot[ -]?found\b|\bno (?:active |relevant )?(?:record|policy|item)\b|record\.not\.found|موردی یافت نشد|یافت نشد|پیدا نشد|فاقد بیمه(?:| )?نامه/i.test(
|
||||
message,
|
||||
@@ -175,6 +201,11 @@ export function getInquiryErrorMessage(
|
||||
): string {
|
||||
const providerMessage = extractInquiryProviderMessage(error);
|
||||
|
||||
// Persian text supplied by the provider is already the intended client
|
||||
// message. Preserve it verbatim instead of replacing it with a local
|
||||
// contextual fallback such as "inquiry not found".
|
||||
if (providerMessage && hasPersian(providerMessage)) return providerMessage;
|
||||
|
||||
if (isNotFound(error, providerMessage)) return NOT_FOUND_MESSAGES[context];
|
||||
|
||||
if (
|
||||
@@ -208,10 +239,6 @@ export function getInquiryErrorMessage(
|
||||
return "سرویس استعلام در دسترس نیست. لطفاً کمی بعد دوباره تلاش کنید.";
|
||||
}
|
||||
|
||||
// A provider's specific Persian validation/business message is already safe
|
||||
// and more useful than replacing it with a broad local validation message.
|
||||
if (providerMessage && hasPersian(providerMessage)) return providerMessage;
|
||||
|
||||
if (isInvalidInput(providerMessage) || inquiryErrorStatus(error) === 422) {
|
||||
return INVALID_MESSAGES[context];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user