import { Body, Controller, Get, Param, Patch, Put, UseGuards } from "@nestjs/common"; import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiPropertyOptional, ApiTags, } from "@nestjs/swagger"; import { IsOptional, IsString } from "class-validator"; import { LocalActorAuthGuard } from "src/auth/guards/actor-local.guard"; import { RolesGuard } from "src/auth/guards/role.guard"; import { Roles } from "src/decorators/roles.decorator"; import { CurrentUser } from "src/decorators/user.decorator"; import { RoleEnum } from "src/Types&Enums/role.enum"; import { ExpertClaimService } from "./expert-claim.service"; import { SubmitExpertReplyV2Dto } from "./dto/expert-claim-v2.dto"; import { UpdateClaimDamagedPartsV2Dto } from "./dto/update-claim-damaged-parts-v2.dto"; class InPersonVisitV2Dto { @ApiPropertyOptional({ example: 'Paint damage requires physical inspection' }) @IsOptional() @IsString() note?: string; } @ApiTags("expert-claim-panel (v2)") @Controller("v2/expert-claim") @ApiBearerAuth() @UseGuards(LocalActorAuthGuard, RolesGuard) @Roles(RoleEnum.DAMAGE_EXPERT) export class ExpertClaimV2Controller { constructor(private readonly expertClaimService: ExpertClaimService) {} @Get("requests") @ApiOperation({ summary: "List available claim requests for damage expert", description: "Returns claims that are WAITING_FOR_DAMAGE_EXPERT and not locked by another expert, plus this expert's own locked/in-progress claims.", }) async getClaimListV2(@CurrentUser() actor) { return await this.expertClaimService.getClaimListV2(actor); } @Get("request/:claimRequestId") @ApiOperation({ summary: "Get claim request detail for damage expert", description: "Returns full claim details including captured images, required documents status, and damage selections. Claim must have status WAITING_FOR_DAMAGE_EXPERT. If locked, only the locking expert can access it.", }) @ApiParam({ name: "claimRequestId" }) async getClaimDetailV2( @Param("claimRequestId") claimRequestId: string, @CurrentUser() actor, ) { return await this.expertClaimService.getClaimDetailV2(claimRequestId, actor); } @Put("lock/:claimRequestId") @ApiOperation({ summary: "Lock a claim request for review", description: "Claim must have status WAITING_FOR_DAMAGE_EXPERT. Locking sets status to EXPERT_REVIEWING and claimStatus to UNDER_REVIEW. Only one expert can lock a claim at a time.", }) @ApiParam({ name: "claimRequestId" }) async lockClaimRequestV2( @Param("claimRequestId") claimRequestId: string, @CurrentUser() actor, ) { return await this.expertClaimService.lockClaimRequestV2(claimRequestId, actor); } @Put("reply/submit/:claimRequestId") @ApiOperation({ summary: "Submit expert damage assessment reply", description: "Claim must be locked by this expert (status EXPERT_REVIEWING). Submitting unlocks the claim. If any part has factorNeeded=true the claim moves to EXPERT_COST_EVALUATION; otherwise moves to INSURER_REVIEW. Total payment cap is 30,000,000.", }) @ApiParam({ name: "claimRequestId" }) @ApiBody({ type: SubmitExpertReplyV2Dto }) async submitExpertReplyV2( @Param("claimRequestId") claimRequestId: string, @Body() body: SubmitExpertReplyV2Dto, @CurrentUser() actor, ) { return await this.expertClaimService.submitExpertReplyV2(claimRequestId, body, actor); } @Patch(":claimRequestId/visit") @ApiOperation({ summary: "Request in-person visit for claim", description: "Expert decides the user must come in person. Claim must be locked by this expert. Sets claimStatus to NEEDS_REVISION and unlocks the claim so the user is informed.", }) @ApiParam({ name: "claimRequestId" }) @ApiBody({ type: InPersonVisitV2Dto, required: false }) async requestInPersonVisitV2( @Param("claimRequestId") claimRequestId: string, @Body() body: InPersonVisitV2Dto, @CurrentUser() actor, ) { return await this.expertClaimService.requestInPersonVisitV2( claimRequestId, actor, body?.note, ); } @Patch("request/:claimRequestId/damaged-parts") @ApiOperation({ summary: "Edit selected damaged parts (V2)", description: "Damage expert can modify selected damaged parts while claim is in EXPERT_REVIEWING and locked by the same expert.", }) @ApiParam({ name: "claimRequestId" }) @ApiBody({ type: UpdateClaimDamagedPartsV2Dto }) async updateClaimDamagedPartsV2( @Param("claimRequestId") claimRequestId: string, @Body() body: UpdateClaimDamagedPartsV2Dto, @CurrentUser() actor, ) { return await this.expertClaimService.updateClaimDamagedPartsV2( claimRequestId, body, actor, ); } }