From 3821bf36efc730e34c1be90a6c5b4a8de71f7088 Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Sun, 9 Aug 2026 10:36:45 +0330 Subject: [PATCH] YARA-1216 --- .../dto/create-request-management.dto.ts | 27 ++++++++ .../file-maker-blame-v4.controller.ts | 15 +++-- .../request-management.service.ts | 67 +++++++++++++++++++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/request-management/dto/create-request-management.dto.ts b/src/request-management/dto/create-request-management.dto.ts index 06f72a3..5b48b7a 100644 --- a/src/request-management/dto/create-request-management.dto.ts +++ b/src/request-management/dto/create-request-management.dto.ts @@ -87,6 +87,33 @@ export class DescriptionDto { lightCondition?: LightCondition; } +/** + * V4 FileMaker description step (THIRD_PARTY and CAR_BODY alike). + * Accident date and time are required for all file types in V4 so the + * front-end can display them consistently regardless of blame type. + */ +export class DescriptionV4Dto { + @ApiProperty({ description: "Accident description" }) + @IsString() + @IsNotEmpty() + desc: string; + + @ApiProperty({ + description: "Date of the accident (required for all V4 files)", + example: "2025-12-08", + }) + @IsNotEmpty() + accidentDate: Date; + + @ApiProperty({ + description: "Time of the accident (required for all V4 files)", + example: "14:30", + }) + @IsString() + @IsNotEmpty() + accidentTime: string; +} + /** * THIRD_PARTY description step: only desc is accepted. */ diff --git a/src/request-management/file-maker-blame-v4.controller.ts b/src/request-management/file-maker-blame-v4.controller.ts index e3a7ba3..cf96baa 100644 --- a/src/request-management/file-maker-blame-v4.controller.ts +++ b/src/request-management/file-maker-blame-v4.controller.ts @@ -33,7 +33,7 @@ import { SendPartyOtpDto, VerifyPartyOtpDto } from "./dto/party-otp.dto"; import { RunInquiriesV3Dto, RunInquiriesVinV3Dto } from "./dto/run-inquiries-v3.dto"; import { CarBodyFormDto, - DescriptionDto, + DescriptionV4Dto, LocationDto, } from "./dto/create-request-management.dto"; import { RequestManagementService } from "./request-management.service"; @@ -260,15 +260,20 @@ export class FileMakerBlameV4Controller { @Post("add-detail-description/:requestId") @ApiParam({ name: "requestId" }) - @ApiBody({ type: DescriptionDto }) - @ApiOperation({ summary: "Add description for current party" }) + @ApiBody({ type: DescriptionV4Dto }) + @ApiOperation({ + summary: "Add description for current party (V4)", + description: + "Saves description, accidentDate, and accidentTime on the party statement. " + + "accidentDate and accidentTime are required for all V4 files (THIRD_PARTY and CAR_BODY alike).", + }) async addDescription( @Param("requestId") requestId: string, - @Body() body: DescriptionDto, + @Body() body: DescriptionV4Dto, @CurrentUser() fileMaker: any, @Body("partyRole") partyRole?: string, ) { - return this.requestManagementService.addPartyDescriptionV3( + return this.requestManagementService.addPartyDescriptionV4( requestId, fileMaker, body, diff --git a/src/request-management/request-management.service.ts b/src/request-management/request-management.service.ts index 1e8e2be..05de3ff 100644 --- a/src/request-management/request-management.service.ts +++ b/src/request-management/request-management.service.ts @@ -57,6 +57,7 @@ import { AutoCloseRequestService } from "src/utils/cron/cron.service"; import { SmsOrchestrationService } from "src/sms-orchestration/sms-orchestration.service"; import { DescriptionDto, + DescriptionV4Dto, LocationDto, RequestManagementDtoRs, } from "./dto/create-request-management.dto"; @@ -10260,6 +10261,72 @@ export class RequestManagementService { return { requestId: req._id, publicId: req.publicId, partyRole: role }; } + /** + * V4 description step. + * + * Identical to {@link addPartyDescriptionV3} but additionally requires + * `accidentDate` and `accidentTime` for all blame types (THIRD_PARTY and + * CAR_BODY alike) and persists them on `party.statement`. This lets the + * front-end display the accident time consistently for every V4 file without + * branching on blame type. + */ + async addPartyDescriptionV4( + requestId: string, + actor: any, + 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); + + 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 (!Array.isArray(req.history)) req.history = []; + req.history.push({ + type: "V4_PARTY_DESCRIPTION_SAVED", + actor: { + actorId: new Types.ObjectId(actor.sub), + actorName: `${actor.firstName || ""} ${actor.lastName || ""}`.trim(), + actorType: "field_expert", + }, + metadata: { + partyRole: role, + accidentDate: body.accidentDate, + accidentTime: body.accidentTime, + }, + } as any); + + await (req as any).save(); + return { requestId: req._id, publicId: req.publicId, partyRole: role }; + } + async carBodyAccidentTypeFormV3( requestId: string, body: CarBodyFormDto,