Fixed damagedParts unified structure and resend problems

This commit is contained in:
SepehrYahyaee
2026-06-03 11:34:21 +03:30
parent 456135ad08
commit 077bae429e
6 changed files with 154 additions and 95 deletions

View File

@@ -32,13 +32,17 @@ export function resendRequestHasPayload(r: {
}): boolean {
if (!r) return false;
if (String(r.resendDescription || "").trim() !== "") return true;
if (Array.isArray(r.resendDocuments) && r.resendDocuments.length > 0) return true;
if (Array.isArray(r.resendCarParts) && r.resendCarParts.length > 0) return true;
if (Array.isArray(r.resendDocuments) && r.resendDocuments.length > 0)
return true;
if (Array.isArray(r.resendCarParts) && r.resendCarParts.length > 0)
return true;
return false;
}
/** Normalize expert-requested document keys (strings or `{ key }`) to canonical enum strings. */
export function normalizeResendDocumentKeys(docs: unknown[] | undefined): string[] {
export function normalizeResendDocumentKeys(
docs: unknown[] | undefined,
): string[] {
if (!Array.isArray(docs)) return [];
const keys: string[] = [];
for (const d of docs) {
@@ -61,10 +65,7 @@ export function normalizeResendPartKeys(
selectedParts?: unknown,
): string[] {
if (!Array.isArray(parts)) return [];
const selectedNorm = normalizeDamageSelectedParts(
selectedParts,
carType,
);
const selectedNorm = normalizeDamageSelectedParts(selectedParts, carType);
const keys: string[] = [];
for (const p of parts) {
const enriched =
@@ -72,8 +73,7 @@ export function normalizeResendPartKeys(
matchResendPartFromSelected(p, selectedNorm);
if (enriched) {
const ck =
enriched.catalogKey?.trim() ||
catalogLikeKeyFromPart(enriched);
enriched.catalogKey?.trim() || catalogLikeKeyFromPart(enriched);
if (ck) keys.push(ck);
continue;
}
@@ -108,7 +108,10 @@ function resolveResendPartRow(
const fromSelected = matchResendPartFromSelected(raw, selectedNorm ?? []);
if (fromSelected) return fromSelected;
if (fromRaw) return fromRaw;
const o = (raw && typeof raw === "object" ? raw : {}) as Record<string, unknown>;
const o = (raw && typeof raw === "object" ? raw : {}) as Record<
string,
unknown
>;
const fallbackKey =
typeof o.key === "string" && o.key.trim()
? o.key.trim()
@@ -123,8 +126,7 @@ function resolveResendPartRow(
typeof o.label_fa === "string" && o.label_fa.trim()
? o.label_fa.trim()
: fallbackKey,
catalogKey:
typeof o.catalogKey === "string" ? o.catalogKey : undefined,
catalogKey: typeof o.catalogKey === "string" ? o.catalogKey : undefined,
};
}
@@ -149,8 +151,7 @@ export function mapExpertResendCarPartsForClient(
const stored =
raw && typeof raw === "object" ? (raw as Record<string, unknown>) : {};
const sp = resolveResendPartRow(raw, options.carType, selectedNorm);
const catalogKey =
sp.catalogKey?.trim() || catalogLikeKeyFromPart(sp);
const catalogKey = sp.catalogKey?.trim() || catalogLikeKeyFromPart(sp);
const captureKey = catalogKey || partLookupKey(sp);
const cap = getDamagedPartCaptureBlob(
options.damagedPartsData,
@@ -193,8 +194,7 @@ export function normalizeResendCarPartsForStorage(
const stored =
raw && typeof raw === "object" ? (raw as Record<string, unknown>) : {};
const sp = resolveResendPartRow(raw, carType, selectedNorm);
const catalogKey =
sp.catalogKey?.trim() || catalogLikeKeyFromPart(sp);
const catalogKey = sp.catalogKey?.trim() || catalogLikeKeyFromPart(sp);
const row: Record<string, unknown> = {
id: sp.id,
name: sp.name,
@@ -217,8 +217,13 @@ function getRequiredDocEntry(claim: any, documentKey: string): unknown {
return rd instanceof Map ? rd.get(documentKey) : rd[documentKey];
}
export function isRequiredDocumentUploaded(claim: any, documentKey: string): boolean {
const doc = getRequiredDocEntry(claim, documentKey) as { uploaded?: boolean } | undefined;
export function isRequiredDocumentUploaded(
claim: any,
documentKey: string,
): boolean {
const doc = getRequiredDocEntry(claim, documentKey) as
| { uploaded?: boolean }
| undefined;
return !!doc?.uploaded;
}
@@ -241,7 +246,8 @@ export function hasDamagedPartCapture(claim: any, partKey: string): boolean {
export function canFinalizeExpertResend(claim: any): boolean {
if (!claim) return false;
if (claim.status !== ClaimCaseStatus.WAITING_FOR_USER_RESEND) return false;
if (claim.workflow?.currentStep !== ClaimWorkflowStep.USER_EXPERT_RESEND) return false;
if (claim.workflow?.currentStep !== ClaimWorkflowStep.USER_EXPERT_RESEND)
return false;
const r = claim.evaluation?.damageExpertResend;
if (!r || r.fulfilledAt) return false;
@@ -279,16 +285,39 @@ export function documentKeyAllowedForExpertResend(
return allowed.has(normalized);
}
export function partKeyAllowedForExpertResend(claim: any, partKey: string): boolean {
export function partKeyAllowedForExpertResend(
claim: any,
partKey: string,
): boolean {
const r = claim?.evaluation?.damageExpertResend;
if (!r || r.fulfilledAt) return false;
const carType = claim?.vehicle?.carType as ClaimVehicleTypeV2 | undefined;
const allowed = new Set(
normalizeResendPartKeys(
r.resendCarParts,
carType,
claim?.damage?.selectedParts,
),
const selectedParts = claim?.damage?.selectedParts;
// Normalize the stored resend parts to their canonical catalog keys
const allowedKeys = new Set(
normalizeResendPartKeys(r.resendCarParts, carType, selectedParts),
);
return allowed.has(partKey);
// Normalize the incoming partKey the same way so the comparison is apples-to-apples
const resolvedKeys = normalizeResendPartKeys(
[partKey],
carType,
selectedParts,
);
const resolvedKey = resolvedKeys[0];
// Also try direct catalogKey/name match against the stored objects as fallback
const directMatch = ((r.resendCarParts as any[]) ?? []).some((p: any) => {
if (!p || typeof p !== "object") return String(p) === partKey;
return (
p.catalogKey === partKey ||
p.key === partKey ||
p.name === partKey ||
(p.id != null && String(p.id) === partKey)
);
});
return directMatch || (resolvedKey != null && allowedKeys.has(resolvedKey));
}