forked from Yara724/api
Fixed YARA-1217
This commit is contained in:
@@ -20,8 +20,6 @@ export enum ClaimRequiredDocumentType {
|
||||
GUILTY_CAR_CARD_FRONT = "guilty_car_card_front",
|
||||
GUILTY_CAR_CARD_BACK = "guilty_car_card_back",
|
||||
GUILTY_METAL_PLATE = "guilty_metal_plate",
|
||||
/** V4 FileMaker flow only: one photo of the guilty party's car. */
|
||||
GUILTY_CAR_PHOTO = "guilty_car_photo",
|
||||
}
|
||||
|
||||
export enum CarAngle {
|
||||
|
||||
@@ -460,7 +460,6 @@ export class ClaimRequestManagementService {
|
||||
isCarBody: boolean,
|
||||
assumeUploadedKey?: string,
|
||||
skipMetalPlate?: boolean,
|
||||
requiresGuiltyCarPhoto?: boolean,
|
||||
): boolean {
|
||||
for (const k of this.v3PreCaptureDocumentKeys(isCarBody)) {
|
||||
if (skipMetalPlate && OPTIONAL_CAPTURE_PHASE_DOC_KEYS_V4V5.includes(k as any)) continue;
|
||||
@@ -478,15 +477,6 @@ export class ClaimRequestManagementService {
|
||||
: this.isRequiredDocumentUploadedOnClaim(claimCase, g);
|
||||
if (!ok) return false;
|
||||
}
|
||||
// V4 THIRD_PARTY only: require one photo of the guilty party's car.
|
||||
if (requiresGuiltyCarPhoto && !isCarBody) {
|
||||
const k = ClaimRequiredDocumentType.GUILTY_CAR_PHOTO;
|
||||
const ok =
|
||||
k === assumeUploadedKey
|
||||
? true
|
||||
: this.isRequiredDocumentUploadedOnClaim(claimCase, k);
|
||||
if (!ok) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -495,7 +485,6 @@ export class ClaimRequestManagementService {
|
||||
isCarBody: boolean,
|
||||
assumeUploadedKey?: string,
|
||||
skipMetalPlate?: boolean,
|
||||
requiresGuiltyCarPhoto?: boolean,
|
||||
): number {
|
||||
let n = 0;
|
||||
for (const k of this.v3PreCaptureDocumentKeys(isCarBody)) {
|
||||
@@ -514,15 +503,6 @@ export class ClaimRequestManagementService {
|
||||
: this.isRequiredDocumentUploadedOnClaim(claimCase, g);
|
||||
if (!ok) n++;
|
||||
}
|
||||
// V4 THIRD_PARTY only: one photo of the guilty party's car.
|
||||
if (requiresGuiltyCarPhoto && !isCarBody) {
|
||||
const k = ClaimRequiredDocumentType.GUILTY_CAR_PHOTO;
|
||||
const ok =
|
||||
k === assumeUploadedKey
|
||||
? true
|
||||
: this.isRequiredDocumentUploadedOnClaim(claimCase, k);
|
||||
if (!ok) n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -9093,7 +9073,7 @@ export class ClaimRequestManagementService {
|
||||
file: Express.Multer.File,
|
||||
currentUserId: string,
|
||||
actor?: { sub: string; role?: string },
|
||||
options?: { v3InPersonFlow?: boolean; skipMetalPlate?: boolean; requiresFileMakerApproval?: boolean; requiresGuiltyCarPhoto?: boolean },
|
||||
options?: { v3InPersonFlow?: boolean; skipMetalPlate?: boolean; requiresFileMakerApproval?: boolean },
|
||||
): Promise<UploadRequiredDocumentV2ResponseDto> {
|
||||
try {
|
||||
const claimCase = await this.claimCaseDbService.findById(claimRequestId);
|
||||
@@ -9326,7 +9306,6 @@ export class ClaimRequestManagementService {
|
||||
isCarBodyUpload,
|
||||
body.documentKey,
|
||||
options?.skipMetalPlate,
|
||||
options?.requiresGuiltyCarPhoto,
|
||||
);
|
||||
|
||||
allDocumentsUploaded = options?.v3InPersonFlow
|
||||
@@ -9342,7 +9321,6 @@ export class ClaimRequestManagementService {
|
||||
isCarBodyUpload,
|
||||
body.documentKey,
|
||||
options?.skipMetalPlate,
|
||||
options?.requiresGuiltyCarPhoto,
|
||||
)
|
||||
: this.countRemainingV2OwnerDocuments(
|
||||
claimCase,
|
||||
@@ -9439,14 +9417,10 @@ export class ClaimRequestManagementService {
|
||||
: null;
|
||||
const isCarBodyRecheck = blameForRecheck?.type === BlameRequestType.CAR_BODY;
|
||||
const skipMetalPlateRecheck = !!(blameForRecheck as any)?.isMadeByFileMaker;
|
||||
// V4 = isMadeByFileMaker + requiresFileMakerApproval is false on the claim.
|
||||
const requiresGuiltyCarPhotoRecheck =
|
||||
!!(blameForRecheck as any)?.isMadeByFileMaker &&
|
||||
!(afterWrite as any).requiresFileMakerApproval;
|
||||
const allDoneNow =
|
||||
afterWrite.status === ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS &&
|
||||
afterWrite.workflow?.currentStep === ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS &&
|
||||
this.allV3PreCaptureDocumentsComplete(afterWrite, isCarBodyRecheck, undefined, skipMetalPlateRecheck, requiresGuiltyCarPhotoRecheck);
|
||||
this.allV3PreCaptureDocumentsComplete(afterWrite, isCarBodyRecheck, undefined, skipMetalPlateRecheck);
|
||||
|
||||
if (allDoneNow) {
|
||||
// Atomic conditional update: only succeeds when status is still
|
||||
@@ -11279,37 +11253,6 @@ export class ClaimRequestManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
// V4 only (isMadeByFileMaker + NOT requiresFileMakerApproval) and THIRD_PARTY:
|
||||
// inject one photo of the guilty party's car into the pre-capture document list.
|
||||
const isV4 =
|
||||
!!(blame as any)?.isMadeByFileMaker &&
|
||||
!(claimCase as any)?.requiresFileMakerApproval;
|
||||
const isCarBodyBlame = blame?.type === BlameRequestType.CAR_BODY || (blame as any)?.type === "CAR_BODY";
|
||||
if (isV4 && !isCarBodyBlame) {
|
||||
const guiltyCarPhotoKey = ClaimRequiredDocumentType.GUILTY_CAR_PHOTO;
|
||||
const alreadyPresent = base.requiredDocuments.some(
|
||||
(d) => d.key === guiltyCarPhotoKey,
|
||||
);
|
||||
if (!alreadyPresent) {
|
||||
const docData = (claimCase.requiredDocuments as any)?.get?.(guiltyCarPhotoKey)
|
||||
?? (claimCase.requiredDocuments as any)?.[guiltyCarPhotoKey];
|
||||
base = {
|
||||
...base,
|
||||
requiredDocuments: [
|
||||
...base.requiredDocuments,
|
||||
{
|
||||
key: guiltyCarPhotoKey,
|
||||
label_fa: "عکس خودرو مقصر",
|
||||
label_en: "Guilty Party Car Photo",
|
||||
category: "guilty_party",
|
||||
uploaded: !!docData?.uploaded,
|
||||
preferUploadDuringCapture: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const step = claimCase.workflow?.currentStep;
|
||||
const capturePartDone = this.claimV3StepCompleted(
|
||||
claimCase,
|
||||
@@ -11454,23 +11397,13 @@ export class ClaimRequestManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
// V4 = isMadeByFileMaker + requiresFileMakerApproval is false.
|
||||
const requiresGuiltyCarPhoto =
|
||||
!!(blame as any).isMadeByFileMaker &&
|
||||
!(claimCase as any).requiresFileMakerApproval;
|
||||
|
||||
return this.uploadRequiredDocumentV2(
|
||||
claimRequestId,
|
||||
body,
|
||||
file,
|
||||
currentUserId,
|
||||
actor,
|
||||
{
|
||||
v3InPersonFlow: true,
|
||||
skipMetalPlate,
|
||||
requiresFileMakerApproval: !!(claimCase as any).requiresFileMakerApproval,
|
||||
requiresGuiltyCarPhoto,
|
||||
},
|
||||
{ v3InPersonFlow: true, skipMetalPlate, requiresFileMakerApproval: !!(claimCase as any).requiresFileMakerApproval },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11528,7 +11461,33 @@ export class ClaimRequestManagementService {
|
||||
"Select outer parts after accident fields and required documents.",
|
||||
);
|
||||
|
||||
return this.selectOuterPartsV2(claimRequestId, body, currentUserId, actor);
|
||||
const result = await this.selectOuterPartsV2(claimRequestId, body, currentUserId, actor);
|
||||
|
||||
// V4 THIRD_PARTY only: append a synthetic "guilty damage area" entry to
|
||||
// damage.selectedParts so the FileReviewer must capture one photo of the
|
||||
// guilty party's damaged spot during the CAPTURE_PART_DAMAGES phase.
|
||||
// selectOuterPartsV2 uses $set on damage.selectedParts, so we append here
|
||||
// with a separate $push after the V2 write completes.
|
||||
const isV4 =
|
||||
!!(blame as any)?.isMadeByFileMaker &&
|
||||
!(refreshed as any)?.requiresFileMakerApproval;
|
||||
const isCarBodyBlame =
|
||||
blame?.type === BlameRequestType.CAR_BODY ||
|
||||
(blame as any)?.type === "CAR_BODY";
|
||||
if (isV4 && !isCarBodyBlame) {
|
||||
await this.claimCaseDbService.findByIdAndUpdate(claimRequestId, {
|
||||
$push: {
|
||||
"damage.selectedParts": {
|
||||
id: null,
|
||||
name: "guilty_damage_area",
|
||||
side: "",
|
||||
label_fa: "تصویر نقطه آسیبدیده مقصر",
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async selectOtherPartsV3(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsString, MaxLength } from "class-validator";
|
||||
import { IsNotEmpty, IsOptional, IsString, MaxLength } from "class-validator";
|
||||
import { Types } from "mongoose";
|
||||
import { AddPlateDto } from "src/profile/dto/user/AddPlateDto";
|
||||
import { StepsEnum } from "src/Types&Enums/blame-request-management/steps.enum";
|
||||
@@ -98,20 +98,24 @@ export class DescriptionV4Dto {
|
||||
@IsNotEmpty()
|
||||
desc: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: "Date of the accident (required for all V4 files)",
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"Date of the accident. Required for the first (guilty) party; " +
|
||||
"optional for the second (damaged) party.",
|
||||
example: "2025-12-08",
|
||||
})
|
||||
@IsNotEmpty()
|
||||
accidentDate: Date;
|
||||
@IsOptional()
|
||||
accidentDate?: Date;
|
||||
|
||||
@ApiProperty({
|
||||
description: "Time of the accident (required for all V4 files)",
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"Time of the accident. Required for the first (guilty) party; " +
|
||||
"optional for the second (damaged) party.",
|
||||
example: "14:30",
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
accidentTime: string;
|
||||
accidentTime?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10280,37 +10280,35 @@ export class RequestManagementService {
|
||||
body: DescriptionV4Dto,
|
||||
partyRole?: string,
|
||||
) {
|
||||
if (
|
||||
body.accidentDate == null ||
|
||||
body.accidentDate === ("" as any)
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
"accidentDate is required for V4 files.",
|
||||
);
|
||||
}
|
||||
if (
|
||||
!body.accidentTime ||
|
||||
!String(body.accidentTime).trim()
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
"accidentTime is required for V4 files.",
|
||||
);
|
||||
}
|
||||
|
||||
const req = await this.blameRequestDbService.findById(requestId);
|
||||
if (!req) throw new NotFoundException("Request not found");
|
||||
await this.verifyExpertAccessForBlameV2(req, actor);
|
||||
const role = this.resolvePartyRoleV3(req, partyRole);
|
||||
this.assertBlameV3PartyDetailPhase(req, role);
|
||||
|
||||
// accidentDate and accidentTime are only required for the first (guilty)
|
||||
// party — the second (damaged) party can skip them.
|
||||
if (role === PartyRole.FIRST) {
|
||||
if (body.accidentDate == null || body.accidentDate === ("" as any)) {
|
||||
throw new BadRequestException(
|
||||
"accidentDate is required for the first party in V4 files.",
|
||||
);
|
||||
}
|
||||
if (!body.accidentTime || !String(body.accidentTime).trim()) {
|
||||
throw new BadRequestException(
|
||||
"accidentTime is required for the first party in V4 files.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const idx = this.getPartyIndex(req, role);
|
||||
if (idx === -1) throw new BadRequestException(`${role} party not found`);
|
||||
|
||||
const party = req.parties[idx];
|
||||
if (!party.statement) party.statement = {} as any;
|
||||
party.statement.description = body.desc;
|
||||
party.statement.accidentDate = body.accidentDate as any;
|
||||
party.statement.accidentTime = body.accidentTime;
|
||||
if (body.accidentDate != null) party.statement.accidentDate = body.accidentDate as any;
|
||||
if (body.accidentTime) party.statement.accidentTime = body.accidentTime;
|
||||
|
||||
if (!Array.isArray(req.history)) req.history = [];
|
||||
req.history.push({
|
||||
|
||||
Reference in New Issue
Block a user