1
0
forked from Yara724/api
Files
yara724-api/src/claim-request-management/claim-request-management.controller.ts
2026-05-30 08:59:57 +03:30

508 lines
15 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { extname, parse } from "node:path";
import {
BadRequestException,
Body,
Controller,
Get,
Param,
Patch,
Post,
Put,
Query,
UploadedFile,
UseGuards,
UseInterceptors,
} from "@nestjs/common";
import { FileInterceptor } from "@nestjs/platform-express";
import {
ApiBearerAuth,
ApiBody,
ApiConsumes,
ApiParam,
ApiQuery,
ApiTags,
ApiOperation,
} from "@nestjs/swagger";
import { diskStorage } from "multer";
import { ClaimAccessGuard } from "src/auth/guards/claim-access.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 { DEFAULT_MEDIA_MAX_BYTES } from "src/client/client.service";
import { ClaimRequestManagementService } from "./claim-request-management.service";
import { ClaimRequiredDocumentType } from "src/Types&Enums/claim-request-management/required-document-type.enum";
import { CarDamagePartDto, OtherCarDamagePartDto } from "./dto/car-part.dto";
import { UserCommentDto } from "./dto/user-comment.dto";
import { UserObjectionDto } from "./dto/user-objection.dto";
import { InPersonVisitDto } from "./dto/in-person-visit.dto";
import { UserRatingDto } from "./dto/user-rating.dto";
@Controller("claim-request-management")
@ApiTags("claim-request-management")
@Roles(RoleEnum.USER, RoleEnum.EXPERT, RoleEnum.DAMAGE_EXPERT)
@UseGuards(ClaimAccessGuard, RolesGuard)
@ApiBearerAuth()
export class ClaimRequestManagementController {
constructor(
private readonly claimRequestManagementService: ClaimRequestManagementService,
) {}
@ApiParam({ name: "blameId" })
@ApiOperation({ deprecated: true })
@Post("/:blameId")
async createClaimRequest(
@Param("blameId") requestId: string,
@CurrentUser() user,
) {
return await this.claimRequestManagementService.createClaimRequest(
requestId,
user.role === RoleEnum.USER ? user.sub : undefined,
user,
);
}
@ApiBody({ type: CarDamagePartDto })
@ApiOperation({ deprecated: true })
@Patch("/car-part-damage/:claimRequestID")
@ApiParam({ name: "claimRequestID" })
async carPartDamage(
@Param("claimRequestID") requestId: string,
@Body() body: CarDamagePartDto,
@CurrentUser() user,
) {
return await this.claimRequestManagementService.selectCarPartDamage(
requestId,
body,
user,
);
}
@ApiOperation({ deprecated: true })
@Get("/car-other-part")
async getCarOtherParts() {
const carOtherPart = await readFile(
`${process.cwd()}/src/static/car-part.json`,
"utf-8",
);
return carOtherPart;
}
@ApiBody({ type: OtherCarDamagePartDto })
@ApiParam({ name: "claimRequestID" })
@UseInterceptors(
FileInterceptor("file", {
limits: {
fileSize: DEFAULT_MEDIA_MAX_BYTES,
},
storage: diskStorage({
destination: "./files/car-green-cards",
filename: (req, file, callback) => {
const unique = Date.now();
const ex = extname(file.originalname);
const filename = `${file.originalname.split(" ")[0]}-${unique}${ex}`;
callback(null, filename);
},
}),
}),
)
@ApiConsumes("multipart/form-data")
@ApiOperation({ deprecated: true })
@Patch("/car-other-part-damage/:claimRequestID")
async carOtherPartDamage(
@Param("claimRequestID") requestId: string,
@UploadedFile() file,
@Body() body: OtherCarDamagePartDto,
@CurrentUser() user,
) {
return await this.claimRequestManagementService.selectCarOtherPartDamage(
requestId,
body,
file,
user,
);
}
@ApiOperation({ deprecated: true })
@Get("required-documents-status/:claimRequestID")
@ApiParam({ name: "claimRequestID" })
async getRequiredDocumentsStatus(@Param("claimRequestID") requestId: string) {
return await this.claimRequestManagementService.getRequiredDocumentsStatus(
requestId,
);
}
@ApiOperation({ deprecated: true })
@Get("car-part-image-required/:claimRequestID")
@ApiParam({ name: "claimRequestID" })
async getImageRequired(@Param("claimRequestID") requestId) {
return await this.claimRequestManagementService.getImageRequiredList(
requestId,
);
}
@ApiBody({
schema: {
type: "object",
properties: {
file: { type: "string", format: "binary" },
},
},
})
@UseInterceptors(
FileInterceptor("file", {
limits: { fileSize: DEFAULT_MEDIA_MAX_BYTES },
storage: diskStorage({
destination: "./files/claim-required-documents/",
filename: (req, file, callback) => {
const extension = extname(file.originalname);
const basename = parse(file.originalname).name;
const unique = Date.now();
const sanitizedBasename = basename
.replace(/\s/g, "_")
.replace(/[^\w\-_]/g, "")
.substring(0, 50);
const filename = `${sanitizedBasename}-${unique}${extension}`;
callback(null, filename);
},
}),
}),
)
@ApiConsumes("multipart/form-data")
@ApiParam({ name: "claimRequestID" })
@ApiQuery({
name: "documentType",
enum: ClaimRequiredDocumentType,
description: "Type of required document to upload",
})
@ApiOperation({ deprecated: true })
@Patch("upload-required-document/:claimRequestID")
async uploadRequiredDocument(
@Param("claimRequestID") requestId: string,
@Query("documentType") documentType: string,
@UploadedFile("file") file: Express.Multer.File,
@CurrentUser() user,
) {
if (!file) {
throw new BadRequestException("File is required");
}
return await this.claimRequestManagementService.uploadRequiredDocument(
requestId,
documentType as any,
file,
user,
);
}
@ApiBody({
schema: {
type: "object",
properties: {
file: { type: "string", format: "binary" },
},
},
})
@UseInterceptors(
FileInterceptor("file", {
limits: { fileSize: DEFAULT_MEDIA_MAX_BYTES },
storage: diskStorage({
destination: "./files/car-parts/",
filename: (req, file, callback) => {
const extension = extname(file.originalname);
const basename = parse(file.originalname).name;
const unique = Date.now();
// Sanitize filename: remove non-ASCII characters and special chars to avoid encoding issues
const sanitizedBasename = basename
.replace(/\s/g, "_")
.replace(/[^\w\-_]/g, "") // Remove all non-word characters except hyphens and underscores
.substring(0, 50); // Limit length
const filename = `${sanitizedBasename}-${unique}${extension}`;
callback(null, filename);
},
}),
}),
)
@ApiConsumes("multipart/form-data")
@ApiParam({ name: "claimRequestID" })
@ApiParam({
name: "partId",
description: "The ID of the specific car part being photographed.",
})
@ApiOperation({ deprecated: true })
@Patch("capture-car-part-damage/:claimRequestID/:partId")
async captureCarPartDamage(
@Param("partId") partId: string,
@Param("claimRequestID") requestId: string,
@UploadedFile("file") file: Express.Multer.File,
) {
if (!file) {
throw new BadRequestException("Image file is required.");
}
return await this.claimRequestManagementService.setDamageImage(
requestId,
partId,
file,
);
}
@ApiBody({
schema: {
type: "object",
properties: {
file: { type: "string", format: "binary" },
},
},
})
@UseInterceptors(
FileInterceptor("file", {
limits: { fileSize: DEFAULT_MEDIA_MAX_BYTES },
storage: diskStorage({
destination: "./files/car-capture-videos/",
filename: (req, file, callback) => {
const unique = Date.now();
const ex = extname(file.originalname);
const filename = `claim-video-${unique}${ex}`;
callback(null, filename);
},
}),
}),
)
@ApiConsumes("multipart/form-data")
@ApiParam({ name: "claimRequestID" })
@ApiOperation({ deprecated: true })
@Patch("car-capture/:claimRequestID")
async captureVideoCapture(
@Param("claimRequestID") requestId: string,
@UploadedFile("file") file: Express.Multer.File,
) {
return await this.claimRequestManagementService.setVideoCapture(
requestId,
file,
);
}
@ApiOperation({ deprecated: true })
@Get("requests/")
async getRequest(@CurrentUser() currentUser) {
return await this.claimRequestManagementService.myRequests(currentUser);
}
@ApiOperation({ deprecated: true })
@Get("request/:claimRequestId")
@ApiParam({ name: "claimRequestId" })
myRequests(@Param("claimRequestId") requestId: string, @CurrentUser() user) {
return this.claimRequestManagementService.requestDetails(requestId, user);
}
@ApiOperation({ deprecated: true })
@Put("request/reply/:claimRequestId")
@ApiParam({ name: "claimRequestId" })
@UseInterceptors(
FileInterceptor("file", {
limits: {
fileSize: DEFAULT_MEDIA_MAX_BYTES,
},
storage: diskStorage({
destination: "./files/claim-sign",
filename: (req, file, callback) => {
const unique = Date.now();
const ex = extname(file.originalname);
const filename = `${file.originalname.split(" ")[0]}-${unique}${ex}`;
callback(null, filename);
},
}),
}),
)
@ApiBody({
type: UserCommentDto,
description: "if partId null , you can upload video capture",
})
@ApiConsumes("multipart/form-data")
@ApiParam({ name: "claimRequestId" })
async submitReply(
@Param("claimRequestId") requestId,
@Body() body,
@UploadedFile() file: Express.Multer.File,
@CurrentUser() user,
) {
// return await this.claimRequestManagementService.submitUserReply(
// requestId,
// body,
// file,
// user,
// );
}
@ApiOperation({ deprecated: true })
@Put("request/resend/:claimRequestId/objection")
@ApiParam({ name: "claimRequestId" })
@ApiConsumes("application/json")
@ApiBody({
type: UserObjectionDto,
description: "Objection details with optional new parts",
})
async handleUserObjection(
@Param("claimRequestId") claimRequestId: string,
@Body() userObjectionDto: UserObjectionDto,
) {
return await this.claimRequestManagementService.handleUserObjectionAndParts(
claimRequestId,
userObjectionDto,
);
}
@ApiOperation({ deprecated: true })
@Patch("request/resend/:claimRequestId")
@ApiConsumes("multipart/form-data")
@ApiParam({ name: "claimRequestId" })
@ApiQuery({ name: "fields", enum: ["resendDocuments", "resendCarParts"] })
@ApiQuery({ name: "partId", required: false })
@ApiQuery({ name: "documentName", required: false })
@ApiQuery({ name: "side", required: false })
@ApiBody({
schema: {
type: "object",
properties: {
file: {
type: "string",
format: "binary",
},
},
},
})
@UseInterceptors(
FileInterceptor("file", {
storage: diskStorage({
destination: "./files/claim-resend-documents",
filename: (req, file, callback) => {
const unique = Date.now();
const ext = extname(file.originalname);
const filename = `${file.originalname.split(" ")[0]}-${unique}${ext}`;
callback(null, filename);
},
}),
limits: { fileSize: DEFAULT_MEDIA_MAX_BYTES },
}),
)
async uploadDocuments(
@Param("claimRequestId") claimId: string,
@Query() query: string,
@UploadedFile() file: Express.Multer.File,
@CurrentUser() user,
) {
return await this.claimRequestManagementService.resendFiles(
claimId,
file,
query,
user,
);
}
/**
* User satisfaction rating for a completed claim file.
* Only the damaged user (claim owner) can rate their claim after it is closed.
*/
@ApiOperation({ deprecated: true })
@Put("request/:claimRequestId/user-rating")
@ApiParam({ name: "claimRequestId" })
@ApiBody({ type: UserRatingDto })
async addUserRating(
@Param("claimRequestId") claimRequestId: string,
@Body() ratingDto: UserRatingDto,
@CurrentUser() user,
) {
return await this.claimRequestManagementService.addUserRating(
claimRequestId,
user,
ratingDto,
);
}
@ApiOperation({ deprecated: true })
@Patch("request/reply/:claimRequestId/:partId/upload-factor")
@ApiConsumes("multipart/form-data")
@ApiParam({ name: "claimRequestId" })
@ApiParam({ name: "partId" })
@ApiBody({
schema: {
type: "object",
properties: {
file: {
type: "string",
format: "binary",
},
},
},
})
@UseInterceptors(
FileInterceptor("file", {
storage: diskStorage({
destination: "./files/claim-factors",
filename: (req, file, callback) => {
const unique = Date.now();
const filename = `-${unique}-${file.originalname}`;
callback(null, filename);
},
}),
limits: { fileSize: DEFAULT_MEDIA_MAX_BYTES },
}),
)
async uploadFactorForPart(
@Param("claimRequestId") claimId: string,
@Param("partId") partId: string,
@UploadedFile() file: Express.Multer.File,
@CurrentUser() user,
) {
return await this.claimRequestManagementService.uploadClaimFactor(
claimId,
partId,
file,
user,
);
}
@ApiBody({ type: InPersonVisitDto })
@ApiParam({ name: "id" })
@ApiOperation({ deprecated: true })
@Patch(":id/visit")
async inPersonVisit(
@Param("id") requestId: string,
@Body() body: InPersonVisitDto,
@CurrentUser() actor,
) {
// Pass the branchId from the body to the service
return await this.claimRequestManagementService.inPersonVisit(
requestId,
body.branchId,
actor,
);
}
@ApiOperation({ deprecated: true })
@Get("branches/:insuranceId")
async insuranceBranches(@Param("insuranceId") insuranceId: string) {
return await this.claimRequestManagementService.retrieveInsuranceBranches(
insuranceId,
);
}
@ApiOperation({ deprecated: true })
@Get("fanavaran-submit/:claimRequestId")
@ApiParam({ name: "claimRequestId" })
async fanavaranSubmit(@Param("claimRequestId") claimRequestId: string) {
return await this.claimRequestManagementService.fanavaranSubmit(
claimRequestId,
);
}
@ApiOperation({ deprecated: true })
@Post("fanavaran-submit/:claimRequestId")
@ApiParam({ name: "claimRequestId" })
async submitToFanavaran(@Param("claimRequestId") claimRequestId: string) {
return await this.claimRequestManagementService.submitToFanavaran(
claimRequestId,
);
}
}