import { Body, Controller, Delete, Get, Middlewares, Path, Post, Put, Request, Route, Security, Tags, } from "tsoa"; import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import { permissionCheck } from "../middlewares/employee"; import { notFoundError, relationError } from "../utils/error"; import { connectOrNot } from "../utils/relation"; const MANAGE_ROLES = [ "system", "head_of_admin", "admin", "head_of_accountant", "accountant", "head_of_sale", ]; function globalAllow(user: RequestWithUser["user"]) { const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; return allowList.some((v) => user.roles?.includes(v)); } type EmployeeCheckupPayload = { checkupType?: string | null; checkupResult?: string | null; provinceId?: string | null; hospitalName?: string | null; remark?: string | null; medicalBenefitScheme?: string | null; insuranceCompany?: string | null; coverageStartDate?: Date | null; coverageExpireDate?: Date | null; }; @Route("api/v1/employee/{employeeId}/checkup") @Tags("Employee Checkup") @Middlewares(permissionCheck(globalAllow)) export class EmployeeCheckupController extends Controller { @Get() @Security("keycloak") async list(@Path() employeeId: string) { return prisma.employeeCheckup.findMany({ include: { createdBy: true, updatedBy: true, }, orderBy: { createdAt: "asc" }, where: { employeeId }, }); } @Get("{checkupId}") @Security("keycloak") async getById(@Path() employeeId: string, @Path() checkupId: string) { const record = await prisma.employeeCheckup.findFirst({ include: { createdBy: true, updatedBy: true, }, where: { id: checkupId, employeeId }, }); if (!record) throw notFoundError("Employee Other Info"); return record; } @Post() @Security("keycloak", MANAGE_ROLES) async create( @Request() req: RequestWithUser, @Path() employeeId: string, @Body() body: EmployeeCheckupPayload, ) { if (body.provinceId) { const [province] = await prisma.$transaction([ prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), prisma.employee.findFirst({ where: { id: employeeId } }), ]); if (body.provinceId && !province) throw relationError("Province"); } const { provinceId, ...rest } = body; const record = await prisma.employeeCheckup.create({ include: { province: true, createdBy: true, updatedBy: true }, data: { ...rest, province: connectOrNot(provinceId), employee: { connect: { id: employeeId } }, createdBy: { connect: { id: req.user.sub } }, updatedBy: { connect: { id: req.user.sub } }, }, }); this.setStatus(HttpStatus.CREATED); return record; } @Put("{checkupId}") @Security("keycloak", MANAGE_ROLES) async editById( @Request() req: RequestWithUser, @Path() employeeId: string, @Path() checkupId: string, @Body() body: EmployeeCheckupPayload, ) { if (body.provinceId || employeeId) { const [province] = await prisma.$transaction([ prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), ]); if (body.provinceId && !province) throw relationError("Province"); } const { provinceId, ...rest } = body; const checkup = await prisma.employeeCheckup.findUnique({ where: { id: checkupId, employeeId }, }); if (!checkup) throw notFoundError("Employee Other Info"); const record = await prisma.employeeCheckup.update({ include: { province: true, createdBy: true, updatedBy: true }, where: { id: checkupId, employeeId }, data: { ...rest, province: { connect: provinceId ? { id: provinceId } : undefined }, updatedBy: { connect: { id: req.user.sub } }, }, }); this.setStatus(HttpStatus.CREATED); return record; } @Delete("{checkupId}") @Security("keycloak", MANAGE_ROLES) async deleteById(@Path() employeeId: string, @Path() checkupId: string) { const record = await prisma.employeeCheckup.findFirst({ where: { id: checkupId, employeeId } }); if (!record) throw notFoundError("Employee Checkup"); return await prisma.employeeCheckup.delete({ include: { createdBy: true, updatedBy: true }, where: { id: checkupId, employeeId }, }); } }