forked from Yara724/api
Fixed bugs
This commit is contained in:
@@ -82,6 +82,8 @@ import {
|
|||||||
coerceDamagedPartsMediaToArray,
|
coerceDamagedPartsMediaToArray,
|
||||||
normalizeCarPartDamageForExpertReply,
|
normalizeCarPartDamageForExpertReply,
|
||||||
normalizeDamageSelectedParts,
|
normalizeDamageSelectedParts,
|
||||||
|
partIdentityKey,
|
||||||
|
partIdentityKeyFromCarPartDamage,
|
||||||
} from "src/helpers/outer-damage-parts";
|
} from "src/helpers/outer-damage-parts";
|
||||||
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
||||||
import { snapshotFromDamageExpert } from "src/helpers/expert-profile-snapshot";
|
import { snapshotFromDamageExpert } from "src/helpers/expert-profile-snapshot";
|
||||||
@@ -2639,6 +2641,17 @@ export class ExpertClaimService {
|
|||||||
reply.parts?.length > 0
|
reply.parts?.length > 0
|
||||||
? this.validateAndNormalizeDaghiForExpertReplyV2(reply.parts)
|
? this.validateAndNormalizeDaghiForExpertReplyV2(reply.parts)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
const ownerSelectedParts = normalizeDamageSelectedParts(
|
||||||
|
(claim as any)?.damage?.selectedParts,
|
||||||
|
carTypeSubmit,
|
||||||
|
(claim as any)?.damage?.selectedOuterParts,
|
||||||
|
);
|
||||||
|
const ownerSelectedIdentitySet = new Set(
|
||||||
|
ownerSelectedParts.map((p) => partIdentityKey(p)),
|
||||||
|
);
|
||||||
|
const seenIdentities = new Set<string>();
|
||||||
|
|
||||||
const processedParts = daghiNormalized.map((p) => {
|
const processedParts = daghiNormalized.map((p) => {
|
||||||
let carPartDamage: Record<string, unknown>;
|
let carPartDamage: Record<string, unknown>;
|
||||||
try {
|
try {
|
||||||
@@ -2653,7 +2666,31 @@ export class ExpertClaimService {
|
|||||||
}`,
|
}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return { ...p, carPartDamage };
|
|
||||||
|
const identityKey = partIdentityKeyFromCarPartDamage(carPartDamage);
|
||||||
|
if (!identityKey) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
`Invalid carPartDamage for part ${p.partId}: cannot derive a stable identity (need a catalog id or both name and side).`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
ownerSelectedIdentitySet.size > 0 &&
|
||||||
|
!ownerSelectedIdentitySet.has(identityKey)
|
||||||
|
) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
`Part "${identityKey}" is not in the owner's selected damaged parts; only parts the user picked (or added via objection) can be priced.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seenIdentities.has(identityKey)) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
`Duplicate part submitted in expert reply: ${identityKey}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
seenIdentities.add(identityKey);
|
||||||
|
|
||||||
|
return { ...p, partId: identityKey, carPartDamage };
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mixedFactorAndPrice, allFactorLines } = classifyV2ExpertPricingParts(
|
const { mixedFactorAndPrice, allFactorLines } = classifyV2ExpertPricingParts(
|
||||||
|
|||||||
@@ -298,6 +298,40 @@ export function partIdentityKey(p: DamageSelectedPartV2): string {
|
|||||||
return `${p.side}|${p.name}`;
|
return `${p.side}|${p.name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same canonical identity as `partIdentityKey`, but derived directly from a
|
||||||
|
* unified `carPartDamage` snapshot (the shape we persist on
|
||||||
|
* `evaluation.damageExpertReply*.parts[].carPartDamage`).
|
||||||
|
*
|
||||||
|
* Returns `null` when the input cannot produce an identity (no `id`, no
|
||||||
|
* `name`). Callers should treat that as an invalid expert reply line.
|
||||||
|
*/
|
||||||
|
export function partIdentityKeyFromCarPartDamage(
|
||||||
|
carPartDamage: unknown,
|
||||||
|
): string | null {
|
||||||
|
if (
|
||||||
|
!carPartDamage ||
|
||||||
|
typeof carPartDamage !== "object" ||
|
||||||
|
Array.isArray(carPartDamage)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const o = carPartDamage as Record<string, unknown>;
|
||||||
|
const idRaw = o.id;
|
||||||
|
const id =
|
||||||
|
typeof idRaw === "number" && Number.isFinite(idRaw)
|
||||||
|
? idRaw
|
||||||
|
: typeof idRaw === "string" &&
|
||||||
|
idRaw.trim() &&
|
||||||
|
Number.isFinite(Number(idRaw))
|
||||||
|
? Number(idRaw)
|
||||||
|
: null;
|
||||||
|
const name = typeof o.name === "string" ? o.name.trim() : "";
|
||||||
|
const side = typeof o.side === "string" ? o.side.trim() : "";
|
||||||
|
if (id == null && !name) return null;
|
||||||
|
return partIdentityKey({ id, name, side, label_fa: "" });
|
||||||
|
}
|
||||||
|
|
||||||
function normPartSegment(s: string): string {
|
function normPartSegment(s: string): string {
|
||||||
return String(s ?? "").replace(/[^a-z0-9]/gi, "").toLowerCase();
|
return String(s ?? "").replace(/[^a-z0-9]/gi, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user