import { Body, Controller, Delete, Get, Middlewares, Path, Post, Put, Route, Security, Tags, } from "tsoa"; import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import { connectOrDisconnect, connectOrNot } from "../utils/relation"; import { notFoundError, relationError } from "../utils/error"; import { permissionCheck } from "../middlewares/customer-branch"; import { deleteFile, fileLocation } from "../utils/minio"; const MANAGE_ROLES = [ "system", "head_of_admin", "admin", "head_of_accountant", "accountant", "head_of_sale", "sale", ]; function globalAllow(user: RequestWithUser["user"]) { const allowList = ["system", "head_of_admin", "admin", "head_of_accountant", "head_of_sale"]; return allowList.some((v) => user.roles?.includes(v)); } type CustomerBranchCitizenPayload = { citizenId: string; birthDate?: Date; namePrefix?: string; firstName: string; firstNameEN?: string; middleName?: string; middleNameEN?: string; lastName: string; lastNameEN?: string; issueDate: Date; expireDate: Date; nationality: string; religion: string; gender: string; address?: string; addressEN?: string; soi?: string; soiEN?: string; moo?: string; mooEN?: string; street?: string; streetEN?: string; provinceId?: string; districtId?: string; subDistrictId?: string; }; @Route("api/v1/customer-branch/{branchId}/citizen") @Tags("Customer Branch Citizen") @Middlewares(permissionCheck(globalAllow)) export class CustomerBranchCitizenController extends Controller { @Get() @Security("keycloak") async list(@Path() branchId: string) { return prisma.customerBranchCitizen.findMany({ orderBy: { createdAt: "asc" }, where: { customerBranchId: branchId }, }); } @Get("{citizenId}") @Security("keycloak") async getById(@Path() branchId: string, @Path() citizenId: string) { const record = await prisma.customerBranchCitizen.findFirst({ where: { id: citizenId, customerBranchId: branchId }, }); if (!record) throw notFoundError("Citizen"); return record; } @Post() @Security("keycloak", MANAGE_ROLES) async create(@Path() branchId: string, @Body() body: CustomerBranchCitizenPayload) { const { provinceId, districtId, subDistrictId, ...rest } = body; const [province, district, subDistrict] = await prisma.$transaction([ prisma.province.findFirst({ where: { id: body.provinceId ?? undefined } }), prisma.district.findFirst({ where: { id: body.districtId ?? undefined } }), prisma.subDistrict.findFirst({ where: { id: body.subDistrictId ?? undefined } }), ]); if (body.provinceId && !province) throw relationError("Province"); if (body.districtId && !district) throw relationError("District"); if (body.subDistrictId && !subDistrict) throw relationError("SubDistrict"); const record = await prisma.customerBranchCitizen.create({ data: { ...rest, province: connectOrNot(provinceId), district: connectOrNot(districtId), subDistrict: connectOrNot(subDistrictId), customerBranch: { connect: { id: branchId } }, }, }); this.setStatus(HttpStatus.CREATED); return record; } @Put("{citizenId}") @Security("keycloak", MANAGE_ROLES) async editById( @Path() branchId: string, @Path() citizenId: string, @Body() body: CustomerBranchCitizenPayload, ) { const { provinceId, districtId, subDistrictId, ...rest } = body; const [province, district, subDistrict, citizen] = await prisma.$transaction([ prisma.province.findUnique({ where: { id: body.provinceId ?? undefined } }), prisma.district.findUnique({ where: { id: body.districtId ?? undefined } }), prisma.subDistrict.findUnique({ where: { id: body.subDistrictId ?? undefined } }), prisma.customerBranchCitizen.findUnique({ where: { id: citizenId, customerBranchId: branchId }, }), ]); if (body.provinceId && !province) throw relationError("Province"); if (body.districtId && !district) throw relationError("District"); if (body.subDistrictId && !subDistrict) throw relationError("SubDistrict"); if (!citizen) throw notFoundError("Citizen"); const record = await prisma.customerBranchCitizen.update({ where: { id: citizenId, customerBranchId: branchId }, data: { ...rest, province: connectOrDisconnect(provinceId), district: connectOrDisconnect(districtId), subDistrict: connectOrDisconnect(subDistrictId), }, }); this.setStatus(HttpStatus.CREATED); return record; } @Delete("{citizenId}") @Security("keycloak", MANAGE_ROLES) async deleteById(@Path() branchId: string, @Path() citizenId: string) { const record = await prisma.customerBranchCitizen.findFirst({ where: { id: citizenId, customerBranchId: branchId }, }); if (!record) throw notFoundError("Citizen"); await deleteFile(fileLocation.customerBranch.citizen(branchId, citizenId)); return await prisma.customerBranchCitizen.delete({ where: { id: citizenId, customerBranchId: branchId }, }); } }