forked from Yara724/api
fix: harden claim review and inquiry workflows
Preserve damage history and current vehicle price, restore depreciation mapping, normalize inquiry/report output, and support resumable expert review with paginated case retrieval.
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
ReinquiryInquiriesResponseDto,
|
||||
ReinquiryPartyResultDto,
|
||||
} from "./dto/reinquiry-inquiries.dto";
|
||||
import { getInquiryErrorMessage } from "src/common/utils/inquiry-error";
|
||||
|
||||
type PlateParts = {
|
||||
leftDigits: number;
|
||||
@@ -48,7 +49,7 @@ export class InquiryRefreshService {
|
||||
|
||||
if (!body.publicId && !body.blameRequestId && limit === 0) {
|
||||
throw new BadRequestException(
|
||||
"Provide publicId, blameRequestId, or limit for bulk refresh.",
|
||||
"برای اجرای مجدد استعلام، شناسه عمومی پرونده، شناسه پرونده یا تعداد پروندهها را وارد کنید.",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,14 +59,16 @@ export class InquiryRefreshService {
|
||||
if (body.publicId) filter.publicId = body.publicId;
|
||||
if (body.blameRequestId) {
|
||||
if (!Types.ObjectId.isValid(body.blameRequestId)) {
|
||||
throw new BadRequestException("Invalid blameRequestId");
|
||||
throw new BadRequestException("شناسه پرونده معتبر نیست.");
|
||||
}
|
||||
filter._id = new Types.ObjectId(body.blameRequestId);
|
||||
}
|
||||
|
||||
let docs = await this.blameRequestDbService.find(filter, { lean: true });
|
||||
if (!docs.length) {
|
||||
throw new NotFoundException("No matching blame cases found");
|
||||
throw new NotFoundException(
|
||||
"پرونده تقصیر مطابق اطلاعات واردشده یافت نشد.",
|
||||
);
|
||||
}
|
||||
docs = limit > 0 ? docs.slice(0, limit) : docs;
|
||||
|
||||
@@ -111,8 +114,8 @@ export class InquiryRefreshService {
|
||||
if (index === -1) {
|
||||
partyResults.push({
|
||||
role,
|
||||
thirdParty: { ok: false, message: "party not found" },
|
||||
person: { ok: false, message: "party not found" },
|
||||
thirdParty: { ok: false, message: "طرف پرونده یافت نشد." },
|
||||
person: { ok: false, message: "طرف پرونده یافت نشد." },
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -150,7 +153,9 @@ export class InquiryRefreshService {
|
||||
blameRequestId: new Types.ObjectId(String(doc._id)),
|
||||
});
|
||||
claimsUpdated = linkedClaims.length;
|
||||
this.logger.log(`[dry-run] ${label} would update blame + ${claimsUpdated} claim(s)`);
|
||||
this.logger.log(
|
||||
`[dry-run] ${label} would update blame + ${claimsUpdated} claim(s)`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -208,9 +213,7 @@ export class InquiryRefreshService {
|
||||
plateId: party?.vehicle?.plateId,
|
||||
...(plate ? { plate } : {}),
|
||||
...(nationalCode ? { nationalCode } : {}),
|
||||
...(birthDate !== null && birthDate !== undefined
|
||||
? { birthDate }
|
||||
: {}),
|
||||
...(birthDate !== null && birthDate !== undefined ? { birthDate } : {}),
|
||||
};
|
||||
|
||||
if (dryRun) {
|
||||
@@ -223,8 +226,8 @@ export class InquiryRefreshService {
|
||||
result.thirdParty = {
|
||||
ok: false,
|
||||
message: !plate
|
||||
? "plate not found on party"
|
||||
: "nationalCodeOfInsurer/nationalCodeOfDriver missing",
|
||||
? "پلاک برای این طرف پرونده ثبت نشده است."
|
||||
: "کد ملی برای این طرف پرونده ثبت نشده است.",
|
||||
};
|
||||
} else {
|
||||
await this.waitForRateLimit();
|
||||
@@ -249,7 +252,9 @@ export class InquiryRefreshService {
|
||||
inquiriesChanged = true;
|
||||
result.thirdParty = {
|
||||
ok: false,
|
||||
message: inquiry.mapped.Error.Message || "third-party inquiry error",
|
||||
message:
|
||||
inquiry.mapped.Error.Message ||
|
||||
getInquiryErrorMessage(inquiry.mapped, "thirdPartyPlate"),
|
||||
};
|
||||
} else {
|
||||
nextParty = this.applyThirdPartyToParty(
|
||||
@@ -292,11 +297,18 @@ export class InquiryRefreshService {
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.recordPartyInquiry(inquiries, "thirdParty", role, false, {}, error);
|
||||
this.recordPartyInquiry(
|
||||
inquiries,
|
||||
"thirdParty",
|
||||
role,
|
||||
false,
|
||||
{},
|
||||
error,
|
||||
);
|
||||
inquiriesChanged = true;
|
||||
result.thirdParty = {
|
||||
ok: false,
|
||||
message: error?.message || String(error),
|
||||
message: getInquiryErrorMessage(error, "thirdPartyPlate"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -305,8 +317,8 @@ export class InquiryRefreshService {
|
||||
result.person = {
|
||||
ok: false,
|
||||
message: !nationalCode
|
||||
? "nationalCodeOfInsurer/nationalCodeOfDriver missing"
|
||||
: "insurerBirthday/driverBirthday missing",
|
||||
? "کد ملی برای این طرف پرونده ثبت نشده است."
|
||||
: "تاریخ تولد برای این طرف پرونده ثبت نشده است.",
|
||||
};
|
||||
} else {
|
||||
await this.waitForRateLimit();
|
||||
@@ -333,7 +345,7 @@ export class InquiryRefreshService {
|
||||
inquiriesChanged = true;
|
||||
result.person = {
|
||||
ok: false,
|
||||
message: error?.message || String(error),
|
||||
message: getInquiryErrorMessage(error, "personalIdentity"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -477,12 +489,14 @@ export class InquiryRefreshService {
|
||||
): Promise<void> {
|
||||
const blameDoc = await this.blameRequestDbService.findById(blameId);
|
||||
if (!blameDoc) {
|
||||
throw new NotFoundException(`Blame case ${blameId} not found`);
|
||||
throw new NotFoundException("پرونده تقصیر یافت نشد.");
|
||||
}
|
||||
|
||||
for (const role of roles) {
|
||||
const memParty = updatedParties.find((party) => party?.role === role);
|
||||
const docIdx = blameDoc.parties.findIndex((party) => party?.role === role);
|
||||
const docIdx = blameDoc.parties.findIndex(
|
||||
(party) => party?.role === role,
|
||||
);
|
||||
if (!memParty || docIdx === -1) continue;
|
||||
|
||||
const party = blameDoc.parties[docIdx];
|
||||
@@ -514,7 +528,9 @@ export class InquiryRefreshService {
|
||||
party.insurance.company = memParty.insurance.company;
|
||||
}
|
||||
if (memParty.insurance.financialCeiling !== undefined) {
|
||||
party.insurance.financialCeiling = String(memParty.insurance.financialCeiling);
|
||||
party.insurance.financialCeiling = String(
|
||||
memParty.insurance.financialCeiling,
|
||||
);
|
||||
}
|
||||
if (memParty.insurance.startDate !== undefined) {
|
||||
party.insurance.startDate = memParty.insurance.startDate;
|
||||
@@ -541,7 +557,8 @@ export class InquiryRefreshService {
|
||||
});
|
||||
|
||||
const inquiryPatch: Record<string, unknown> = {};
|
||||
if (inquiries.thirdParty) inquiryPatch["inquiries.thirdParty"] = inquiries.thirdParty;
|
||||
if (inquiries.thirdParty)
|
||||
inquiryPatch["inquiries.thirdParty"] = inquiries.thirdParty;
|
||||
if (inquiries.person) inquiryPatch["inquiries.person"] = inquiries.person;
|
||||
if (!Object.keys(inquiryPatch).length) return 0;
|
||||
|
||||
@@ -590,14 +607,16 @@ export class InquiryRefreshService {
|
||||
|
||||
private normalizeInquiryError(error: any): Record<string, unknown> {
|
||||
return {
|
||||
message: error?.message || String(error),
|
||||
message: getInquiryErrorMessage(error, "generic"),
|
||||
status: error?.status ?? error?.response?.status,
|
||||
data: error?.data ?? error?.response?.data,
|
||||
};
|
||||
}
|
||||
|
||||
private resolvePartyPlate(party: Record<string, any>): PlateParts | null {
|
||||
const fromPlateId = this.parsePlateFromCompactString(party?.vehicle?.plateId);
|
||||
const fromPlateId = this.parsePlateFromCompactString(
|
||||
party?.vehicle?.plateId,
|
||||
);
|
||||
if (fromPlateId) return fromPlateId;
|
||||
|
||||
const candidates = [
|
||||
@@ -608,14 +627,24 @@ export class InquiryRefreshService {
|
||||
].filter(Boolean);
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const leftDigits = this.firstPresent(candidate.Plk1, candidate.platePartOne);
|
||||
const leftDigits = this.firstPresent(
|
||||
candidate.Plk1,
|
||||
candidate.platePartOne,
|
||||
);
|
||||
const centerAlphabet = this.firstPresent(
|
||||
candidate.plateLetterid,
|
||||
candidate.plateLetterId,
|
||||
candidate.plateLetterTitle,
|
||||
);
|
||||
const centerDigits = this.firstPresent(candidate.Plk3, candidate.platePartThree);
|
||||
const ir = this.firstPresent(candidate.PlkSrl, candidate.plkSrl, candidate.plateSerialNumber);
|
||||
const centerDigits = this.firstPresent(
|
||||
candidate.Plk3,
|
||||
candidate.platePartThree,
|
||||
);
|
||||
const ir = this.firstPresent(
|
||||
candidate.PlkSrl,
|
||||
candidate.plkSrl,
|
||||
candidate.plateSerialNumber,
|
||||
);
|
||||
|
||||
if (
|
||||
leftDigits !== undefined &&
|
||||
@@ -623,7 +652,9 @@ export class InquiryRefreshService {
|
||||
centerDigits !== undefined &&
|
||||
ir !== undefined
|
||||
) {
|
||||
const plateLetter = this.plateNormalizer.normalizePlateText(String(centerAlphabet));
|
||||
const plateLetter = this.plateNormalizer.normalizePlateText(
|
||||
String(centerAlphabet),
|
||||
);
|
||||
const parsed: PlateParts = {
|
||||
leftDigits: Number(leftDigits),
|
||||
centerAlphabet: plateLetter,
|
||||
@@ -653,7 +684,9 @@ export class InquiryRefreshService {
|
||||
const ir = Number(irRaw);
|
||||
const leftDigits = Number(leftRaw);
|
||||
const centerDigits = Number(centerRaw);
|
||||
const centerAlphabet = this.plateNormalizer.normalizePlateText(String(alphaRaw || ""));
|
||||
const centerAlphabet = this.plateNormalizer.normalizePlateText(
|
||||
String(alphaRaw || ""),
|
||||
);
|
||||
if (
|
||||
!Number.isFinite(ir) ||
|
||||
!Number.isFinite(leftDigits) ||
|
||||
@@ -685,6 +718,8 @@ export class InquiryRefreshService {
|
||||
}
|
||||
|
||||
private firstPresent(...values: unknown[]): unknown {
|
||||
return values.find((value) => value !== undefined && value !== null && value !== "");
|
||||
return values.find(
|
||||
(value) => value !== undefined && value !== null && value !== "",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user