Validation for prices and objection

This commit is contained in:
SepehrYahyaee
2026-05-20 11:08:47 +03:30
parent 511d478064
commit e4dfe7c572
18 changed files with 467 additions and 60 deletions

View File

@@ -116,9 +116,11 @@ import {
type DamageSelectedPartV2,
migrateExpertReplyCarPartDamageToUnified,
normalizeDamageSelectedParts,
partIdentityKey,
parseCatalogPartIdInput,
partLookupKey,
resolvePartCaptureIndex,
} from "src/helpers/outer-damage-parts";
import { normalizeMoneyAmountString } from "src/utils/unicode-digits";
import {
CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS,
@@ -5544,19 +5546,20 @@ export class ClaimRequestManagementService {
);
}
const pricedPartIdSet =
const pricedCatalogIds =
activeExpert?.parts?.length ?
new Set(
activeExpert.parts
.filter((p) => p.factorNeeded !== true)
.map((p) => String((p as { partId?: string }).partId ?? ""))
.filter(Boolean),
.map((p) => parseCatalogPartIdInput(p.partId))
.filter((id): id is number => id != null),
)
: new Set<string>();
: new Set<number>();
if (partsIn.length && pricingObjectionEligible) {
for (const op of partsIn) {
if (!pricedPartIdSet.has(String(op.partId))) {
const catalogId = parseCatalogPartIdInput(op.partId);
if (catalogId == null || !pricedCatalogIds.has(catalogId)) {
throw new BadRequestException(
`Only priced repair lines can be disputed (${String(op.partId)} is factor-only or unknown).`,
);
@@ -5565,19 +5568,28 @@ export class ClaimRequestManagementService {
}
const objectionParts = partsIn.map((p) => ({
partId: p.partId,
reason: p.reason,
partPrice: p.partPrice,
partSalary: p.partSalary,
partId: parseCatalogPartIdInput(p.partId)!,
reason: p.reason?.trim() || undefined,
partPrice:
p.partPrice != null && String(p.partPrice).trim() !== ""
? normalizeMoneyAmountString(String(p.partPrice))
: undefined,
partSalary:
p.partSalary != null && String(p.partSalary).trim() !== ""
? normalizeMoneyAmountString(String(p.partSalary))
: undefined,
typeOfDamage: p.typeOfDamage != null ? String(p.typeOfDamage) : undefined,
carPartDamage: p.carPartDamage,
side: p.side,
carPartDamage: p.carPartDamage?.trim() || undefined,
side: p.side?.trim() || undefined,
}));
const newParts = newPartsIn.map((p) => ({
partId: p.partId ? String(p.partId) : new Types.ObjectId().toString(),
partName: p.partName,
side: p.side,
partId:
p.partId != null && parseCatalogPartIdInput(p.partId) != null
? parseCatalogPartIdInput(p.partId)!
: new Types.ObjectId().toString(),
partName: p.partName.trim(),
side: p.side?.trim() || undefined,
}));
const objectionCarType = claimCase.vehicle?.carType as
@@ -5588,7 +5600,7 @@ export class ClaimRequestManagementService {
objectionCarType,
(claimCase.damage as any)?.selectedOuterParts,
);
const mergedKeys = new Set(mergedNorm.map((p) => partIdentityKey(p)));
const mergedKeys = new Set(mergedNorm.map((p) => partLookupKey(p)));
for (const np of newParts) {
const name = np.partName?.trim();
if (!name) continue;
@@ -5599,7 +5611,7 @@ export class ClaimRequestManagementService {
side,
label_fa: name,
};
const k = partIdentityKey(row);
const k = partLookupKey(row);
if (!mergedKeys.has(k)) {
mergedNorm.push(row);
mergedKeys.add(k);
@@ -6112,7 +6124,7 @@ export class ClaimRequestManagementService {
);
const displayParts = [...selectedNormDetails];
const seenDetailKeys = new Set(
selectedNormDetails.map((p) => partIdentityKey(p)),
selectedNormDetails.map((p) => partLookupKey(p)),
);
for (const rk of resendPartKeys) {
const extra =
@@ -6124,7 +6136,7 @@ export class ClaimRequestManagementService {
label_fa: rk,
catalogKey: rk,
};
const k = partIdentityKey(extra);
const k = partLookupKey(extra);
if (!seenDetailKeys.has(k)) {
displayParts.push(extra);
seenDetailKeys.add(k);