forked from Yara724/api
513 lines
15 KiB
TypeScript
513 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,
|
|
);
|
|
}
|
|
}
|