From 34142942e5a1c283624c9fa362c15294c2b520a9 Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Sun, 7 Jun 2026 10:34:10 +0330 Subject: [PATCH] Simplified captcha, Fixed unified damaged parts --- src/captcha/captcha.service.ts | 2 +- .../dto/claim-damaged-part.enricher.ts | 69 +++++++++++++++---- src/expert-claim/expert-claim.service.ts | 4 +- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/captcha/captcha.service.ts b/src/captcha/captcha.service.ts index 5b00d88..c7ed27f 100644 --- a/src/captcha/captcha.service.ts +++ b/src/captcha/captcha.service.ts @@ -13,7 +13,7 @@ export class CaptchaService { generate(): GeneratedCaptcha { const captcha = svgCaptcha.create({ size: 5, - ignoreChars: "abcdefghijklmnopqrstuvwxyzACDEFGHIJKLMNOPQRSTUVWXYZ", + ignoreChars: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", noise: 1, color: false, background: "#f8fafc", diff --git a/src/expert-claim/dto/claim-damaged-part.enricher.ts b/src/expert-claim/dto/claim-damaged-part.enricher.ts index 99d8741..6e47ce2 100644 --- a/src/expert-claim/dto/claim-damaged-part.enricher.ts +++ b/src/expert-claim/dto/claim-damaged-part.enricher.ts @@ -27,26 +27,48 @@ export function buildEnrichedDamagedParts(params: { } = params; const priceDropLines: any[] = evaluationBlock?.priceDrop?.partLines ?? []; + + // objectionParts stores { partId, carPartDamage, side } — not { id, name } const objectionParts: any[] = evaluationBlock?.objection?.objectionParts ?? []; + + // newParts stores { partId, partName, side } — not { id, name } 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; + // Helpers that match against the ACTUAL stored field names + function partMatchesObjection(sp: any, objPart: any): boolean { + if (sp.id != null && objPart.partId != null && sp.id === objPart.partId) + return true; + const objName = objPart.carPartDamage ?? objPart.name ?? objPart.partName; + if (objName && (sp.name === objName || sp.label_fa === objName)) + return true; + return false; + } + + function partMatchesNewObjection(sp: any, newPart: any): boolean { + if (sp.id != null && newPart.partId != null && sp.id === newPart.partId) + return true; + const newName = newPart.partName ?? newPart.name; + if (newName && (sp.name === newName || sp.label_fa === newName)) + return true; + return false; + } + function isPartInResend(sp: any): boolean { return resendCarParts.some( (r: any) => - r.id === sp.id || r.name === sp.name || r.catalogKey === sp.catalogKey, + (sp.id != null && r.id === sp.id) || + r.catalogKey === sp.catalogKey || + r.name === sp.name, ); } function resolveOrigin(sp: any): EnrichedDamagedPart["origin"] { - if ( - newObjectionParts.some((p: any) => p.id === sp.id || p.name === sp.name) - ) { + if (newObjectionParts.some((p) => partMatchesNewObjection(sp, p))) { return "added_by_objection"; } if ( @@ -65,7 +87,6 @@ export function buildEnrichedDamagedParts(params: { if (!captured) { return inResend ? "resend_requested" : "pending"; } - // captured=true + was in a resend request that is now fulfilled → "resent" return inResend && resendFulfilledAt ? "resent" : "uploaded"; } @@ -77,8 +98,30 @@ export function buildEnrichedDamagedParts(params: { ck, selectedParts, ) as { url?: string; path?: string } | undefined; - const captured = hasDamagedPartCapture(damagedPartsData, ck, selectedParts); - const url = cap?.url || (cap?.path ? buildFileLink(cap.path) : undefined); + + // Fallback: if id is null but media.damagedParts has a match by name + const captured = + hasDamagedPartCapture(damagedPartsData, ck, selectedParts) || + (sp.id == null && Array.isArray(damagedPartsData) + ? (damagedPartsData as any[]).some( + (d) => d.name === sp.name && d.side === sp.side && d.path, + ) + : false); + + const capUrl = + cap?.url || + (cap?.path ? buildFileLink(cap.path) : undefined) || + (sp.id == null && Array.isArray(damagedPartsData) + ? (() => { + const match = (damagedPartsData as any[]).find( + (d) => d.name === sp.name && d.side === sp.side && d.path, + ); + return ( + match?.url || + (match?.path ? buildFileLink(match.path) : undefined) + ); + })() + : undefined); const matchingPriceDrop = priceDropLines.find( (line: any) => @@ -86,11 +129,9 @@ export function buildEnrichedDamagedParts(params: { 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 isObjected = objectionParts.some((p) => partMatchesObjection(sp, p)); + const isNewlyAdded = newObjectionParts.some((p) => + partMatchesNewObjection(sp, p), ); const isNewByExpert = expertAddedParts.some( (p: any) => p.id === sp.id || p.name === sp.name, @@ -109,7 +150,7 @@ export function buildEnrichedDamagedParts(params: { origin: resolveOrigin(sp), captureStatus: resolveCaptureStatus(sp, captured), captured, - url, + url: capUrl, objection: { isObjected, diff --git a/src/expert-claim/expert-claim.service.ts b/src/expert-claim/expert-claim.service.ts index 4bf2b95..a69f8cf 100644 --- a/src/expert-claim/expert-claim.service.ts +++ b/src/expert-claim/expert-claim.service.ts @@ -4122,7 +4122,7 @@ export class ExpertClaimService { blameRequestId: claim.blameRequestId?.toString(), blameRequestNo: claim.blameRequestNo, money: moneyPayload, - selectedParts: selectedNormExpert, + // selectedParts: selectedNormExpert, otherParts: claim.damage?.otherParts, requiredDocuments: Object.keys(requiredDocumentsStatus).length > 0 @@ -4134,7 +4134,7 @@ export class ExpertClaimService { evaluation: enrichedEvaluation as | ClaimDetailV2ResponseDto["evaluation"] | undefined, - objection, + // objection, videoCapture, blameCase: blameCaseForApi, blameExpertDecision,