1
0
forked from Yara724/api

Fixed bugs of car-body steps

This commit is contained in:
SepehrYahyaee
2026-04-18 10:10:19 +03:30
parent 9a65071276
commit 1a1d55bc2e
3 changed files with 177 additions and 84 deletions

View File

@@ -3525,7 +3525,23 @@ export class ClaimRequestManagementService {
}
// 5. Convert selected parts to storage format (simple array of strings)
const selectedParts = body.selectedParts;
// Backward compatibility: some clients may still send legacy `carPartDamage` object.
let selectedParts = Array.isArray((body as any)?.selectedParts)
? ((body as any).selectedParts as string[])
: [];
if (selectedParts.length === 0 && (body as any)?.carPartDamage) {
this.assertCarPartDamageAtMostTwoOfFourSides(
(body as any).carPartDamage as CarDamagePartDto,
);
selectedParts = this.carDamagePartDtoToOuterPartSlugs(
(body as any).carPartDamage as CarDamagePartDto,
);
}
if (selectedParts.length === 0) {
throw new BadRequestException(
"selectedParts is required and must contain at least one item",
);
}
// 6. Update claim case with selected parts and move to next step
const updatedClaim = await this.claimCaseDbService.findByIdAndUpdate(
@@ -3548,8 +3564,8 @@ export class ClaimRequestManagementService {
metadata: {
stepKey: ClaimWorkflowStep.SELECT_OUTER_PARTS,
selectedParts: selectedParts,
partsCount: selectedParts.length,
description: `User selected ${selectedParts.length} damaged outer parts`,
partsCount: selectedParts?.length,
description: `User selected ${selectedParts?.length} damaged outer parts`,
},
},
},
@@ -3561,7 +3577,7 @@ export class ClaimRequestManagementService {
}
this.logger.log(
`Outer parts selected for claim ${claimRequestId}: ${selectedParts.length} parts`,
`Outer parts selected for claim ${claimRequestId}: ${selectedParts?.length} parts`,
);
// 7. Return response
@@ -3607,6 +3623,7 @@ export class ClaimRequestManagementService {
body: SelectOtherPartsV2Dto,
currentUserId: string,
actor?: { sub: string; role?: string },
file?: Express.Multer.File,
): Promise<SelectOtherPartsV2ResponseDto> {
try {
// 1. Validate claim exists
@@ -3645,40 +3662,108 @@ export class ClaimRequestManagementService {
}
// 5. Prepare data
const otherParts = body.otherParts || [];
const shebaNumber = body.shebaNumber;
const nationalCode = body.nationalCodeOfOwner;
// Backward compatibility aliases:
// - shebaNumber <- sheba
// - nationalCodeOfOwner <- nationalCodeOfInsurer
let otherParts = Array.isArray((body as any)?.otherParts)
? (body as any).otherParts
: [];
// Multipart clients may send otherParts as JSON string
if (!Array.isArray((body as any)?.otherParts) && typeof (body as any)?.otherParts === "string") {
try {
const parsed = JSON.parse((body as any).otherParts);
otherParts = Array.isArray(parsed) ? parsed : [];
} catch {
otherParts = [];
}
}
const shebaInput = String(
((body as any).shebaNumber ?? (body as any).sheba ?? "") as string,
)
.replace(/\s/g, "");
// 6. Update claim case with other parts, bank info and move to next step
const updatedClaim = await this.claimCaseDbService.findByIdAndUpdate(
claimRequestId,
{
'damage.otherParts': otherParts.length > 0 ? otherParts : undefined,
'money.sheba': shebaNumber,
'money.nationalCodeOfInsurer': nationalCode,
'status': ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS,
'workflow.currentStep': ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
'workflow.nextStep': ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
$push: {
'workflow.completedSteps': ClaimWorkflowStep.SELECT_OTHER_PARTS,
history: {
type: 'STEP_COMPLETED',
actor: {
actorId: new Types.ObjectId(currentUserId),
actorName: claimCase.owner?.fullName || 'User',
actorType: 'user',
},
timestamp: new Date(),
metadata: {
stepKey: ClaimWorkflowStep.SELECT_OTHER_PARTS,
otherParts: otherParts,
otherPartsCount: otherParts.length,
hasBankInfo: true,
description: `User selected ${otherParts.length} other damaged parts and provided bank information`,
},
const shebaDigits = shebaInput.replace(/^IR/i, "");
const shebaNumber = `IR${shebaDigits}`;
const nationalCode = String(
((body as any).nationalCodeOfOwner ??
(body as any).nationalCodeOfInsurer ??
"") as string,
).replace(/\s/g, "");
if (!/^[0-9]{24}$/.test(shebaDigits)) {
throw new BadRequestException(
"shebaNumber is required and must be valid (IR + 24 digits or only 24 digits)",
);
}
if (!/^[0-9]{10}$/.test(nationalCode)) {
throw new BadRequestException(
"nationalCodeOfOwner is required and must be exactly 10 digits",
);
}
const updatePayload: any = {
'damage.otherParts': otherParts.length > 0 ? otherParts : undefined,
'money.sheba': shebaNumber,
'money.nationalCodeOfInsurer': nationalCode,
'status': ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS,
'workflow.currentStep': ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
'workflow.nextStep': ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
$push: {
'workflow.completedSteps': ClaimWorkflowStep.SELECT_OTHER_PARTS,
history: {
type: 'STEP_COMPLETED',
actor: {
actorId: new Types.ObjectId(currentUserId),
actorName: claimCase.owner?.fullName || 'User',
actorType: 'user',
},
timestamp: new Date(),
metadata: {
stepKey: ClaimWorkflowStep.SELECT_OTHER_PARTS,
otherParts: otherParts,
otherPartsCount: otherParts.length,
hasBankInfo: true,
hasGreenCardUpload: !!file,
description: `User selected ${otherParts.length} other damaged parts and provided bank information`,
},
},
},
};
if (file) {
const existingGreen =
(claimCase.requiredDocuments as any)?.get?.(
ClaimRequiredDocumentType.CAR_GREEN_CARD,
) ||
(claimCase.requiredDocuments as any)?.[
ClaimRequiredDocumentType.CAR_GREEN_CARD
];
if (existingGreen?.uploaded) {
throw new ConflictException(
"car_green_card has already been uploaded for this claim",
);
}
const docRef = await this.claimRequiredDocumentDbService.create({
path: file.path,
fileName: file.filename,
claimId: new Types.ObjectId(claimRequestId),
documentType: ClaimRequiredDocumentType.CAR_GREEN_CARD,
uploadedAt: new Date(),
});
updatePayload[
`requiredDocuments.${ClaimRequiredDocumentType.CAR_GREEN_CARD}`
] = {
fileId: docRef._id,
filePath: file.path,
fileName: file.filename,
uploaded: true,
uploadedAt: new Date(),
};
}
// 6. Update claim case with other parts, bank info and optional green card file
const updatedClaim = await this.claimCaseDbService.findByIdAndUpdate(
claimRequestId,
updatePayload,
);
if (!updatedClaim) {
@@ -3690,8 +3775,8 @@ export class ClaimRequestManagementService {
);
// 7. Mask sensitive data for response
const maskedSheba = shebaNumber.replace(/^(.{4})(.*)(.{4})$/, 'IR$1************$3');
const maskedNationalCode = nationalCode.replace(/^(.{2})(.*)(.{2})$/, '$1******$3');
const maskedSheba = `IR${shebaDigits.slice(0, 4)}************${shebaDigits.slice(-4)}`;
const maskedNationalCode = `${nationalCode.slice(0, 2)}******${nationalCode.slice(-2)}`;
// 8. Return response
return {