forked from Yara724/api
Fixed claim/blame damagedParts
This commit is contained in:
@@ -97,8 +97,6 @@ import {
|
||||
hasClaimCarAngleCapture,
|
||||
hasDamagedPartCapture,
|
||||
legacyAngleDamagedPartFieldKeysToUnset,
|
||||
legacyDamagedPartTitleEnFromPartKey,
|
||||
resolveCanonicalDamagedPartStorageKey,
|
||||
type ClaimCarAngleKey,
|
||||
} from "src/helpers/claim-car-angle-media";
|
||||
import {
|
||||
@@ -106,6 +104,16 @@ import {
|
||||
OUTER_PARTS_BY_CAR_TYPE,
|
||||
OuterPartCatalogItem,
|
||||
} from "src/static/outer-car-parts-catalog";
|
||||
import {
|
||||
carPartDamageLabelForFactorRecord,
|
||||
catalogItemToSelectedPart,
|
||||
catalogLikeKeyFromPart,
|
||||
coerceDamagedPartsMediaToArray,
|
||||
migrateExpertReplyCarPartDamageToUnified,
|
||||
normalizeDamageSelectedParts,
|
||||
partIdentityKey,
|
||||
resolvePartCaptureIndex,
|
||||
} from "src/helpers/outer-damage-parts";
|
||||
|
||||
@Injectable()
|
||||
export class ClaimRequestManagementService {
|
||||
@@ -716,17 +724,32 @@ export class ClaimRequestManagementService {
|
||||
throw new BadRequestException("Car part damage is already set.");
|
||||
}
|
||||
this.assertCarPartDamageAtMostTwoOfFourSides(dto.carPartDamage);
|
||||
const selectedParts = this.carDamagePartDtoToOuterPartSlugs(dto.carPartDamage);
|
||||
if (!selectedParts.length) {
|
||||
const selectedSlugStrings = this.carDamagePartDtoToOuterPartSlugs(
|
||||
dto.carPartDamage,
|
||||
);
|
||||
if (!selectedSlugStrings.length) {
|
||||
throw new BadRequestException(
|
||||
"No outer damaged parts could be derived from carPartDamage. Check part selections.",
|
||||
);
|
||||
}
|
||||
const selectedPartObjs = normalizeDamageSelectedParts(
|
||||
selectedSlugStrings,
|
||||
working.vehicle?.carType as ClaimVehicleTypeV2 | undefined,
|
||||
undefined,
|
||||
);
|
||||
const damagedPartsStubs = selectedPartObjs.map((p) => ({
|
||||
id: p.id ?? undefined,
|
||||
name: p.name,
|
||||
side: p.side,
|
||||
label_fa: p.label_fa,
|
||||
...(p.catalogKey ? { catalogKey: p.catalogKey } : {}),
|
||||
}));
|
||||
|
||||
const updated = await this.claimCaseDbService.findByIdAndUpdate(
|
||||
claimRequestId,
|
||||
{
|
||||
"damage.selectedParts": selectedParts,
|
||||
"damage.selectedParts": selectedPartObjs,
|
||||
"media.damagedParts": damagedPartsStubs,
|
||||
status: ClaimCaseStatus.SELECTING_OTHER_PARTS,
|
||||
"workflow.currentStep": ClaimWorkflowStep.SELECT_OTHER_PARTS,
|
||||
"workflow.nextStep": ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
|
||||
@@ -744,7 +767,7 @@ export class ClaimRequestManagementService {
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
stepKey: ClaimWorkflowStep.SELECT_OUTER_PARTS,
|
||||
selectedParts,
|
||||
selectedParts: selectedPartObjs,
|
||||
description: "Field expert submitted outer damage parts",
|
||||
},
|
||||
},
|
||||
@@ -1922,7 +1945,10 @@ export class ClaimRequestManagementService {
|
||||
* - convert factorLink ObjectId -> public URL
|
||||
* - enrich daghi.branchId with branchName when available
|
||||
*/
|
||||
private async mapEvaluationForClient(evaluation: any): Promise<any | undefined> {
|
||||
private async mapEvaluationForClient(
|
||||
evaluation: any,
|
||||
carType?: ClaimVehicleTypeV2,
|
||||
): Promise<any | undefined> {
|
||||
if (!evaluation) return undefined;
|
||||
|
||||
const mapReply = async (reply: any) => {
|
||||
@@ -1988,6 +2014,13 @@ export class ClaimRequestManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
if (nextPart.carPartDamage != null) {
|
||||
nextPart.carPartDamage = migrateExpertReplyCarPartDamageToUnified(
|
||||
nextPart.carPartDamage,
|
||||
carType,
|
||||
);
|
||||
}
|
||||
|
||||
return nextPart;
|
||||
});
|
||||
|
||||
@@ -2032,7 +2065,9 @@ export class ClaimRequestManagementService {
|
||||
const parts = finalReply?.parts || [];
|
||||
const missingFactors = parts
|
||||
.filter((p) => p.factorNeeded === true && !p.factorLink)
|
||||
.map((p) => p.carPartDamage || p.partId);
|
||||
.map((p) =>
|
||||
carPartDamageLabelForFactorRecord(p.carPartDamage) || p.partId,
|
||||
);
|
||||
|
||||
if (missingFactors.length > 0) {
|
||||
throw new HttpException(
|
||||
@@ -2259,7 +2294,7 @@ export class ClaimRequestManagementService {
|
||||
const factorRecord = await this.claimFactorsImageDbService.create({
|
||||
claimId,
|
||||
partId,
|
||||
partName: part.carPartDamage,
|
||||
partName: carPartDamageLabelForFactorRecord(part.carPartDamage),
|
||||
path: file.path,
|
||||
fileName: file.filename,
|
||||
uploadedAt: new Date(),
|
||||
@@ -2396,7 +2431,9 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
const partNameForRecord = part.carPartDamage ?? part.partId;
|
||||
const partNameForRecord =
|
||||
carPartDamageLabelForFactorRecord(part.carPartDamage) ||
|
||||
String(part.partId ?? "");
|
||||
|
||||
const factorRecord = await this.claimFactorsImageDbService.create({
|
||||
claimId: new Types.ObjectId(claimRequestId),
|
||||
@@ -3980,41 +4017,46 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
selectedParts = selectedItems.map((p) => p.key);
|
||||
const selectedPartIds = selectedItems.map((p) => p.id);
|
||||
const selectedOuterParts = selectedItems.map((p) => ({
|
||||
id: p.id,
|
||||
key: p.key,
|
||||
const selectedPartDocs = selectedItems.map((p) =>
|
||||
catalogItemToSelectedPart(p, catalog),
|
||||
);
|
||||
const damagedPartsInitial = selectedPartDocs.map((p) => ({
|
||||
id: p.id ?? undefined,
|
||||
name: p.name,
|
||||
side: p.side,
|
||||
label_fa: p.label_fa,
|
||||
...(p.catalogKey ? { catalogKey: p.catalogKey } : {}),
|
||||
}));
|
||||
const selectedPartIds = selectedItems.map((p) => p.id);
|
||||
|
||||
// 6. Update claim case with selected parts and move to next step
|
||||
const updatedClaim = await this.claimCaseDbService.findByIdAndUpdate(
|
||||
claimRequestId,
|
||||
{
|
||||
'damage.selectedParts': selectedParts,
|
||||
'damage.selectedOuterParts': selectedOuterParts,
|
||||
'vehicle.carType': selectedCarType,
|
||||
'status': ClaimCaseStatus.SELECTING_OTHER_PARTS,
|
||||
'workflow.currentStep': ClaimWorkflowStep.SELECT_OTHER_PARTS,
|
||||
'workflow.nextStep': ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
|
||||
"damage.selectedParts": selectedPartDocs,
|
||||
"media.damagedParts": damagedPartsInitial,
|
||||
"vehicle.carType": selectedCarType,
|
||||
status: ClaimCaseStatus.SELECTING_OTHER_PARTS,
|
||||
"workflow.currentStep": ClaimWorkflowStep.SELECT_OTHER_PARTS,
|
||||
"workflow.nextStep": ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
|
||||
$unset: { "damage.selectedOuterParts": "" },
|
||||
$push: {
|
||||
'workflow.completedSteps': ClaimWorkflowStep.SELECT_OUTER_PARTS,
|
||||
"workflow.completedSteps": ClaimWorkflowStep.SELECT_OUTER_PARTS,
|
||||
history: {
|
||||
type: 'STEP_COMPLETED',
|
||||
type: "STEP_COMPLETED",
|
||||
actor: {
|
||||
actorId: new Types.ObjectId(currentUserId),
|
||||
actorName: claimCase.owner?.fullName || 'User',
|
||||
actorType: 'user',
|
||||
actorName: claimCase.owner?.fullName || "User",
|
||||
actorType: "user",
|
||||
},
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
stepKey: ClaimWorkflowStep.SELECT_OUTER_PARTS,
|
||||
selectedParts: selectedParts,
|
||||
selectedParts: selectedPartDocs,
|
||||
selectedPartIds,
|
||||
carType: selectedCarType,
|
||||
partsCount: selectedParts?.length,
|
||||
description: `User selected ${selectedParts?.length} damaged outer parts`,
|
||||
partsCount: selectedPartDocs?.length,
|
||||
description: `User selected ${selectedPartDocs?.length} damaged outer parts`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -4022,22 +4064,23 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
|
||||
if (!updatedClaim) {
|
||||
throw new InternalServerErrorException('Failed to update claim case');
|
||||
throw new InternalServerErrorException("Failed to update claim case");
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Outer parts selected for claim ${claimRequestId}: ${selectedParts?.length} parts`,
|
||||
`Outer parts selected for claim ${claimRequestId}: ${selectedPartDocs?.length} parts`,
|
||||
);
|
||||
|
||||
// 7. Return response
|
||||
return {
|
||||
claimRequestId: updatedClaim._id.toString(),
|
||||
publicId: updatedClaim.publicId,
|
||||
selectedParts: selectedParts,
|
||||
selectedParts: selectedPartDocs,
|
||||
selectedPartIds,
|
||||
currentStep: ClaimWorkflowStep.SELECT_OTHER_PARTS,
|
||||
nextStep: ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
|
||||
message: 'Outer parts selected successfully. Please proceed to select other parts and provide bank information.',
|
||||
message:
|
||||
"Outer parts selected successfully. Please proceed to select other parts and provide bank information.",
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) throw error;
|
||||
@@ -4290,19 +4333,6 @@ export class ClaimRequestManagementService {
|
||||
if (!catalogByKey.has(item.key)) catalogByKey.set(item.key, item);
|
||||
}
|
||||
|
||||
const getPartLabel = (key: string): { fa: string; en: string } => {
|
||||
const catalogItem = catalogByKey.get(key);
|
||||
if (catalogItem) {
|
||||
const en = key
|
||||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||||
.replace(/_/g, " ")
|
||||
.trim()
|
||||
.replace(/\b\w/g, (c) => c.toUpperCase());
|
||||
return { fa: catalogItem.titleFa, en };
|
||||
}
|
||||
return { fa: key, en: key };
|
||||
};
|
||||
|
||||
// Required documents: CAR_BODY needs 7 (damaged + green card); THIRD_PARTY needs 13 (add guilty_*)
|
||||
const blameRequest = claimCase.blameRequestId
|
||||
? await this.blameRequestDbService.findById(claimCase.blameRequestId.toString())
|
||||
@@ -4356,46 +4386,36 @@ export class ClaimRequestManagementService {
|
||||
),
|
||||
}));
|
||||
|
||||
// Damaged parts from selected parts
|
||||
const selectedParts = claimCase.damage?.selectedParts || [];
|
||||
const selectedOuterParts = Array.isArray(claimCase.damage?.selectedOuterParts)
|
||||
? claimCase.damage.selectedOuterParts
|
||||
: [];
|
||||
const selectedOuterPartByKey = new Map<
|
||||
string,
|
||||
{ id?: number; side?: string }
|
||||
>(
|
||||
selectedOuterParts.map((p) => [
|
||||
p.key,
|
||||
{
|
||||
id: p.id,
|
||||
side: p.side,
|
||||
},
|
||||
]),
|
||||
const carType = claimCase.vehicle?.carType as ClaimVehicleTypeV2 | undefined;
|
||||
const selectedNorm = normalizeDamageSelectedParts(
|
||||
claimCase.damage?.selectedParts,
|
||||
carType,
|
||||
(claimCase.damage as any)?.selectedOuterParts,
|
||||
);
|
||||
|
||||
const damagedParts = selectedParts.map(partKey => {
|
||||
const label = getPartLabel(partKey);
|
||||
const selectedMeta = selectedOuterPartByKey.get(partKey);
|
||||
const catalogMeta = catalogByKey.get(partKey);
|
||||
const side = selectedMeta?.side ?? catalogMeta?.side;
|
||||
const sideFaMap: Record<string, string> = {
|
||||
left: "چپ",
|
||||
right: "راست",
|
||||
front: "جلو",
|
||||
back: "عقب",
|
||||
top: "بالا",
|
||||
};
|
||||
const sideFa = side ? sideFaMap[side] : undefined;
|
||||
const damagedParts = selectedNorm.map((sp) => {
|
||||
const catalogMeta = sp.catalogKey
|
||||
? catalogByKey.get(sp.catalogKey)
|
||||
: sp.name
|
||||
? catalogByKey.get(catalogLikeKeyFromPart(sp))
|
||||
: undefined;
|
||||
const labelEnName = sp.name
|
||||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||||
.replace(/_/g, " ")
|
||||
.trim()
|
||||
.replace(/\b\w/g, (c) => c.toUpperCase());
|
||||
const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp);
|
||||
return {
|
||||
id: selectedMeta?.id ?? catalogMeta?.id,
|
||||
key: partKey,
|
||||
side,
|
||||
label_fa: sideFa ? `${label.fa} (${sideFa})` : label.fa,
|
||||
label_en: label.en,
|
||||
id: sp.id ?? catalogMeta?.id,
|
||||
key: sp.name,
|
||||
name: sp.name,
|
||||
side: sp.side,
|
||||
label_fa: sp.label_fa,
|
||||
label_en: labelEnName,
|
||||
captured: hasDamagedPartCapture(
|
||||
claimCase.media?.damagedParts as any,
|
||||
partKey,
|
||||
ck,
|
||||
selectedNorm,
|
||||
),
|
||||
};
|
||||
});
|
||||
@@ -4832,48 +4852,90 @@ export class ClaimRequestManagementService {
|
||||
},
|
||||
};
|
||||
|
||||
const selectedBefore = (claimCase.damage?.selectedParts || []) as string[];
|
||||
const carType = claimCase.vehicle?.carType as ClaimVehicleTypeV2 | undefined;
|
||||
const selectedOuterLegacy = (claimCase.damage as any)?.selectedOuterParts;
|
||||
const selectedBeforeNorm = normalizeDamageSelectedParts(
|
||||
claimCase.damage?.selectedParts,
|
||||
carType,
|
||||
selectedOuterLegacy,
|
||||
);
|
||||
let nextSelected = [...selectedBeforeNorm];
|
||||
let nextMedia = coerceDamagedPartsMediaToArray(
|
||||
claimCase.media?.damagedParts,
|
||||
nextSelected,
|
||||
);
|
||||
|
||||
if (treatAsAngle && angleCanon) {
|
||||
updateData[`media.carAngles.${angleCanon}`] = captureData;
|
||||
const unsetFieldKeys = legacyAngleDamagedPartFieldKeysToUnset(
|
||||
angleCanon,
|
||||
body.captureKey,
|
||||
selectedBefore,
|
||||
);
|
||||
if (unsetFieldKeys.length) {
|
||||
updateData.$unset = {};
|
||||
for (const k of unsetFieldKeys) {
|
||||
updateData.$unset[`media.damagedParts.${k}`] = "";
|
||||
if (!Array.isArray(claimCase.media?.damagedParts)) {
|
||||
const unsetFieldKeys = legacyAngleDamagedPartFieldKeysToUnset(
|
||||
angleCanon,
|
||||
body.captureKey,
|
||||
claimCase.damage?.selectedParts,
|
||||
carType,
|
||||
selectedOuterLegacy,
|
||||
);
|
||||
if (unsetFieldKeys.length) {
|
||||
updateData.$unset = {};
|
||||
for (const k of unsetFieldKeys) {
|
||||
updateData.$unset[`media.damagedParts.${k}`] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const canonicalPartKey = resolveCanonicalDamagedPartStorageKey(
|
||||
let idx = resolvePartCaptureIndex(
|
||||
body.captureKey,
|
||||
selectedBefore,
|
||||
nextSelected,
|
||||
nextMedia,
|
||||
);
|
||||
updateData[`media.damagedParts.${canonicalPartKey}`] = captureData;
|
||||
const raw = String(body.captureKey ?? "").trim();
|
||||
const titleLegacy =
|
||||
legacyDamagedPartTitleEnFromPartKey(canonicalPartKey);
|
||||
const unsetPartKeys = new Set<string>();
|
||||
if (raw && raw !== canonicalPartKey) unsetPartKeys.add(raw);
|
||||
if (titleLegacy && titleLegacy !== canonicalPartKey) {
|
||||
unsetPartKeys.add(titleLegacy);
|
||||
if (isResendCapture && body.captureType === "part" && idx < 0) {
|
||||
const added = normalizeDamageSelectedParts(
|
||||
[body.captureKey],
|
||||
carType,
|
||||
undefined,
|
||||
);
|
||||
const row =
|
||||
added[0] || {
|
||||
id: null,
|
||||
name: body.captureKey,
|
||||
side: "",
|
||||
label_fa: body.captureKey,
|
||||
catalogKey: body.captureKey,
|
||||
};
|
||||
nextSelected.push(row);
|
||||
idx = nextSelected.length - 1;
|
||||
nextMedia.push({});
|
||||
}
|
||||
if (unsetPartKeys.size) {
|
||||
updateData.$unset = updateData.$unset || {};
|
||||
for (const k of unsetPartKeys) {
|
||||
updateData.$unset[`media.damagedParts.${k}`] = "";
|
||||
}
|
||||
if (idx < 0) {
|
||||
throw new BadRequestException(
|
||||
`Unknown damaged-part captureKey "${body.captureKey}". Use catalog id, 0-based index, or catalog key.`,
|
||||
);
|
||||
}
|
||||
while (nextMedia.length <= idx) {
|
||||
nextMedia.push({});
|
||||
}
|
||||
const base = nextSelected[idx] || {
|
||||
id: null,
|
||||
name: String(body.captureKey),
|
||||
side: "",
|
||||
label_fa: String(body.captureKey),
|
||||
};
|
||||
nextMedia[idx] = {
|
||||
...(base.id != null ? { id: base.id } : {}),
|
||||
name: base.name,
|
||||
side: base.side,
|
||||
label_fa: base.label_fa,
|
||||
...(base.catalogKey ? { catalogKey: base.catalogKey } : {}),
|
||||
...nextMedia[idx],
|
||||
...captureData,
|
||||
};
|
||||
updateData["media.damagedParts"] = nextMedia;
|
||||
if (
|
||||
isResendCapture &&
|
||||
nextSelected.length !== selectedBeforeNorm.length
|
||||
) {
|
||||
updateData["damage.selectedParts"] = nextSelected;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
isResendCapture &&
|
||||
body.captureType === "part" &&
|
||||
!selectedBefore.includes(body.captureKey)
|
||||
) {
|
||||
updateData.$addToSet = { "damage.selectedParts": body.captureKey };
|
||||
}
|
||||
|
||||
const updatedClaim = await this.claimCaseDbService.findByIdAndUpdate(
|
||||
@@ -4908,10 +4970,14 @@ export class ClaimRequestManagementService {
|
||||
data && (data instanceof Map ? data.get(key) : data[key]);
|
||||
|
||||
// Use same logic as getCaptureRequirementsV2 to determine completion
|
||||
const anglesKeys = ['front', 'back', 'left', 'right'];
|
||||
const anglesKeys = ["front", "back", "left", "right"];
|
||||
const carAnglesData = updatedClaim?.media?.carAngles as any;
|
||||
const damagedPartsData = updatedClaim?.media?.damagedParts as any;
|
||||
const selectedParts = updatedClaim?.damage?.selectedParts || [];
|
||||
const selectedNormAfter = normalizeDamageSelectedParts(
|
||||
updatedClaim?.damage?.selectedParts,
|
||||
updatedClaim?.vehicle?.carType as ClaimVehicleTypeV2,
|
||||
(updatedClaim?.damage as any)?.selectedOuterParts,
|
||||
);
|
||||
|
||||
const anglesCaptured = anglesKeys.filter((k) =>
|
||||
hasClaimCarAngleCapture(
|
||||
@@ -4920,12 +4986,17 @@ export class ClaimRequestManagementService {
|
||||
k as ClaimCarAngleKey,
|
||||
),
|
||||
).length;
|
||||
const partsCaptured = selectedParts.filter((p) =>
|
||||
hasDamagedPartCapture(damagedPartsData, p),
|
||||
).length;
|
||||
const partsCaptured = selectedNormAfter.filter((sp) => {
|
||||
const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp);
|
||||
return hasDamagedPartCapture(
|
||||
damagedPartsData,
|
||||
ck,
|
||||
selectedNormAfter,
|
||||
);
|
||||
}).length;
|
||||
|
||||
const allCapturesComplete =
|
||||
anglesCaptured >= 4 && partsCaptured >= selectedParts.length;
|
||||
anglesCaptured >= 4 && partsCaptured >= selectedNormAfter.length;
|
||||
|
||||
if (allCapturesComplete) {
|
||||
await this.claimCaseDbService.findByIdAndUpdate(claimRequestId, {
|
||||
@@ -4952,7 +5023,8 @@ export class ClaimRequestManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
const remaining = (4 - anglesCaptured) + (selectedParts.length - partsCaptured);
|
||||
const remaining =
|
||||
(4 - anglesCaptured) + (selectedNormAfter.length - partsCaptured);
|
||||
const message = allCapturesComplete
|
||||
? 'All captures complete. Please proceed to upload required documents.'
|
||||
: `${body.captureType === 'angle' ? 'Angle' : 'Part'} captured successfully. ${remaining} captures remaining.`;
|
||||
@@ -5190,11 +5262,29 @@ export class ClaimRequestManagementService {
|
||||
side: p.side,
|
||||
}));
|
||||
|
||||
const mergedSelected = [...(claimCase.damage?.selectedParts ?? [])];
|
||||
const objectionCarType = claimCase.vehicle?.carType as
|
||||
| ClaimVehicleTypeV2
|
||||
| undefined;
|
||||
const mergedNorm = normalizeDamageSelectedParts(
|
||||
claimCase.damage?.selectedParts,
|
||||
objectionCarType,
|
||||
(claimCase.damage as any)?.selectedOuterParts,
|
||||
);
|
||||
const mergedKeys = new Set(mergedNorm.map((p) => partIdentityKey(p)));
|
||||
for (const np of newParts) {
|
||||
const key = np.partName?.trim();
|
||||
if (key && !mergedSelected.includes(key)) {
|
||||
mergedSelected.push(key);
|
||||
const name = np.partName?.trim();
|
||||
if (!name) continue;
|
||||
const side = String(np.side ?? "").trim();
|
||||
const row = {
|
||||
id: null as number | null,
|
||||
name,
|
||||
side,
|
||||
label_fa: name,
|
||||
};
|
||||
const k = partIdentityKey(row);
|
||||
if (!mergedKeys.has(k)) {
|
||||
mergedNorm.push(row);
|
||||
mergedKeys.add(k);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5212,7 +5302,7 @@ export class ClaimRequestManagementService {
|
||||
'workflow.currentStep': ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT,
|
||||
'workflow.nextStep': ClaimWorkflowStep.EXPERT_COST_EVALUATION,
|
||||
'evaluation.objection': objectionPayload,
|
||||
'damage.selectedParts': mergedSelected,
|
||||
'damage.selectedParts': mergedNorm,
|
||||
},
|
||||
$unset: {
|
||||
'evaluation.ownerPricedPartsApproval': "",
|
||||
@@ -5692,47 +5782,56 @@ export class ClaimRequestManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
const getPartLabelFa = (key: string): string => {
|
||||
const labels: Record<string, string> = {
|
||||
hood: 'کاپوت',
|
||||
trunk: 'صندوق عقب',
|
||||
roof: 'سقف',
|
||||
front_right_door: 'درب جلو راست',
|
||||
front_left_door: 'درب جلو چپ',
|
||||
rear_right_door: 'درب عقب راست',
|
||||
rear_left_door: 'درب عقب چپ',
|
||||
front_bumper: 'سپر جلو',
|
||||
rear_bumper: 'سپر عقب',
|
||||
front_right_fender: 'گلگیر جلو راست',
|
||||
front_left_fender: 'گلگیر جلو چپ',
|
||||
rear_right_fender: 'گلگیر عقب راست',
|
||||
rear_left_fender: 'گلگیر عقب چپ',
|
||||
};
|
||||
return labels[key] || key;
|
||||
};
|
||||
|
||||
const carTypeDetails = claim.vehicle?.carType as ClaimVehicleTypeV2 | undefined;
|
||||
const selectedNormDetails = normalizeDamageSelectedParts(
|
||||
claim.damage?.selectedParts,
|
||||
carTypeDetails,
|
||||
(claim.damage as any)?.selectedOuterParts,
|
||||
);
|
||||
const damagedPartsData = claim.media?.damagedParts as any;
|
||||
const damagedParts: Record<
|
||||
string,
|
||||
{ label_fa: string; captured: boolean; url?: string }
|
||||
> = {};
|
||||
const resendPartKeys = normalizeResendPartKeys(
|
||||
claim.evaluation?.damageExpertResend?.resendCarParts,
|
||||
);
|
||||
const partKeysForDetails = new Set<string>([
|
||||
...((claim.damage?.selectedParts || []) as string[]),
|
||||
...resendPartKeys,
|
||||
]);
|
||||
for (const p of partKeysForDetails) {
|
||||
const cap = getDamagedPartCaptureBlob(damagedPartsData, p) as
|
||||
| { url?: string; path?: string }
|
||||
| undefined;
|
||||
damagedParts[p] = {
|
||||
label_fa: getPartLabelFa(p),
|
||||
const displayParts = [...selectedNormDetails];
|
||||
const seenDetailKeys = new Set(
|
||||
selectedNormDetails.map((p) => partIdentityKey(p)),
|
||||
);
|
||||
for (const rk of resendPartKeys) {
|
||||
const extra =
|
||||
normalizeDamageSelectedParts([rk], carTypeDetails, undefined)[0] ||
|
||||
{
|
||||
id: null,
|
||||
name: rk,
|
||||
side: "",
|
||||
label_fa: rk,
|
||||
catalogKey: rk,
|
||||
};
|
||||
const k = partIdentityKey(extra);
|
||||
if (!seenDetailKeys.has(k)) {
|
||||
displayParts.push(extra);
|
||||
seenDetailKeys.add(k);
|
||||
}
|
||||
}
|
||||
|
||||
const damagedParts = displayParts.map((sp, index) => {
|
||||
const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp);
|
||||
const cap = getDamagedPartCaptureBlob(
|
||||
damagedPartsData,
|
||||
ck,
|
||||
selectedNormDetails,
|
||||
) as { url?: string; path?: string; fileName?: string } | undefined;
|
||||
return {
|
||||
index,
|
||||
id: sp.id,
|
||||
name: sp.name,
|
||||
side: sp.side,
|
||||
label_fa: sp.label_fa,
|
||||
captured: !!cap,
|
||||
url: cap?.url || (cap?.path ? buildFileLink(cap.path) : undefined),
|
||||
...(cap?.path ? { path: cap.path } : {}),
|
||||
...(cap?.fileName ? { fileName: cap.fileName } : {}),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const er = claim.evaluation?.damageExpertResend;
|
||||
const expertResend =
|
||||
@@ -5773,7 +5872,10 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const mappedEvaluation = await this.mapEvaluationForClient(claim.evaluation);
|
||||
const mappedEvaluation = await this.mapEvaluationForClient(
|
||||
claim.evaluation,
|
||||
claim.vehicle?.carType as ClaimVehicleTypeV2 | undefined,
|
||||
);
|
||||
|
||||
return {
|
||||
claimRequestId: claim._id.toString(),
|
||||
@@ -5787,7 +5889,7 @@ export class ClaimRequestManagementService {
|
||||
blameRequestNo: claim.blameRequestNo,
|
||||
...(ownerData ? { owner: ownerData } : {}),
|
||||
vehicle: claim.vehicle,
|
||||
selectedParts: claim.damage?.selectedParts,
|
||||
selectedParts: selectedNormDetails,
|
||||
otherParts: claim.damage?.otherParts,
|
||||
money: isExpertViewer ? moneyForExpert : moneyForUser,
|
||||
requiredDocuments: Object.keys(requiredDocumentsStatus).length > 0 ? requiredDocumentsStatus : undefined,
|
||||
|
||||
Reference in New Issue
Block a user