// claim-damaged-part.enricher.ts import { DamagedPartCaptureStatus, EnrichedDamagedPart, } from "./claim-damaged-part.types"; export function buildEnrichedDamagedParts(params: { selectedParts: any[]; damagedPartsData: any; evaluationBlock: any; expertAddedParts?: any[]; getDamagedPartCaptureBlob: (data: any, key: string, parts: any[]) => any; hasDamagedPartCapture: (data: any, key: string, parts: any[]) => boolean; catalogLikeKeyFromPart: (part: any) => string; buildFileLink: (path: string) => string; }): EnrichedDamagedPart[] { const { selectedParts, damagedPartsData, evaluationBlock, expertAddedParts = [], getDamagedPartCaptureBlob, hasDamagedPartCapture, catalogLikeKeyFromPart, buildFileLink, } = params; const priceDropLines: any[] = evaluationBlock?.priceDrop?.partLines ?? []; const objectionParts: any[] = evaluationBlock?.objection?.objectionParts ?? []; const newObjectionParts: any[] = evaluationBlock?.objection?.newParts ?? []; // Resend block — lives at evaluation.damageExpertResend const damageExpertResend = evaluationBlock?.damageExpertResend; const resendCarParts: any[] = damageExpertResend?.resendCarParts ?? []; const resendFulfilledAt: Date | undefined = damageExpertResend?.fulfilledAt; function isPartInResend(sp: any): boolean { return resendCarParts.some( (r: any) => r.id === sp.id || r.name === sp.name || r.catalogKey === sp.catalogKey, ); } function resolveOrigin(sp: any): EnrichedDamagedPart["origin"] { if ( newObjectionParts.some((p: any) => p.id === sp.id || p.name === sp.name) ) { return "added_by_objection"; } if ( expertAddedParts.some((p: any) => p.id === sp.id || p.name === sp.name) ) { return "added_by_expert"; } return "user_selected"; } function resolveCaptureStatus( sp: any, captured: boolean, ): DamagedPartCaptureStatus { const inResend = isPartInResend(sp); if (!captured) { return inResend ? "resend_requested" : "pending"; } // captured=true + was in a resend request that is now fulfilled → "resent" return inResend && resendFulfilledAt ? "resent" : "uploaded"; } return selectedParts.map((sp, index) => { const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp); const cap = getDamagedPartCaptureBlob( damagedPartsData, ck, selectedParts, ) as { url?: string; path?: string } | undefined; const captured = hasDamagedPartCapture(damagedPartsData, ck, selectedParts); const url = cap?.url || (cap?.path ? buildFileLink(cap.path) : undefined); const matchingPriceDrop = priceDropLines.find( (line: any) => line.partId === sp.id || line.priceDropPartKey?.toLowerCase() === sp.name?.toLowerCase(), ); const isObjected = objectionParts.some( (p: any) => p.id === sp.id || p.name === sp.name, ); const isNewlyAdded = newObjectionParts.some( (p: any) => p.id === sp.id || p.name === sp.name, ); const isNewByExpert = expertAddedParts.some( (p: any) => p.id === sp.id || p.name === sp.name, ); const inResend = isPartInResend(sp); return { index, partId: sp.id ?? null, id: sp.id ?? null, name: sp.name, side: sp.side, label_fa: sp.label_fa, ...(sp.catalogKey ? { catalogKey: sp.catalogKey } : {}), origin: resolveOrigin(sp), captureStatus: resolveCaptureStatus(sp, captured), captured, url, objection: { isObjected, isNewlyAdded, ...(isNewlyAdded ? { addedBy: isNewByExpert ? "expert" : "user" } : {}), }, resend: { wasRequested: inResend, isFulfilled: inResend && !!resendFulfilledAt, ...(inResend && damageExpertResend?.requestedAt ? { requestedAt: damageExpertResend.requestedAt } : {}), ...(inResend && resendFulfilledAt ? { fulfilledAt: resendFulfilledAt } : {}), }, pricing: { hasPriceDrop: !!matchingPriceDrop, severity: matchingPriceDrop?.severity ?? null, coefficient: matchingPriceDrop?.coefficient ?? null, }, }; }); }