import { Prisma, Status } from "@prisma/client"; import { Body, Controller, Delete, Get, Path, Post, Put, Query, Request, Route, Security, Tags, } from "tsoa"; import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; import minio from "../services/minio"; if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); } const MINIO_BUCKET = process.env.MINIO_BUCKET; function imageLocation(id: string) { return `employee/profile-img-${id}`; } type CustomerBranchCreate = { customerId: string; status?: Status; branchNo: string; legalPersonNo: string; taxNo: string; name: string; nameEN: string; addressEN: string; address: string; zipCode: string; email: string; telephoneNo: string; longitude: string; latitude: string; registerName: string; registerDate: Date; authorizedCapital: string; subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; }; type CustomerBranchUpdate = { customerId?: string; status?: "ACTIVE" | "INACTIVE"; branchNo?: string; legalPersonNo?: string; taxNo?: string; name?: string; nameEN?: string; addressEN?: string; address?: string; zipCode?: string; email?: string; telephoneNo?: string; longitude?: string; latitude?: string; registerName?: string; registerDate?: Date; authorizedCapital?: string; subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; }; @Route("api/customer-branch") @Tags("Customer Branch") @Security("keycloak") export class CustomerBranchController extends Controller { @Get() async list( @Query() zipCode?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { OR: [ { nameEN: { contains: query }, zipCode }, { name: { contains: query }, zipCode }, { email: { contains: query }, zipCode }, ], } satisfies Prisma.BranchWhereInput; const [result, total] = await prisma.$transaction([ prisma.customerBranch.findMany({ include: { province: true, district: true, subDistrict: true, }, where, take: pageSize, skip: (page - 1) * pageSize, }), prisma.customerBranch.count({ where }), ]); return { result, page, pageSize, total }; } @Get("{branchId}/employee") async listEmployee( @Path() branchId: string, @Query() zipCode?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { AND: { customerBranchId: branchId }, OR: [ { firstName: { contains: query }, zipCode }, { firstNameEN: { contains: query }, zipCode }, { lastName: { contains: query }, zipCode }, { lastNameEN: { contains: query }, zipCode }, { email: { contains: query }, zipCode }, ], } satisfies Prisma.EmployeeWhereInput; const [result, total] = await prisma.$transaction([ prisma.employee.findMany({ include: { province: true, district: true, subDistrict: true, }, where, take: pageSize, skip: (page - 1) * pageSize, }), prisma.employee.count({ where }), ]); return { result: await Promise.all( result.map(async (v) => ({ ...v, profileImageUrl: await minio.presignedGetObject( MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60, ), })), ), page, pageSize, total, }; } @Post() async create(@Request() req: RequestWithUser, @Body() body: CustomerBranchCreate) { if (body.provinceId || body.districtId || body.subDistrictId || body.customerId) { const [province, district, subDistrict, customer] = 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 } }), prisma.customer.findFirst({ where: { id: body.customerId || undefined } }), ]); if (body.provinceId && !province) throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", "missing_or_invalid_parameter", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", "missing_or_invalid_parameter", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", "missing_or_invalid_parameter", ); if (body.customerId && !customer) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer cannot be found.", "missing_or_invalid_parameter", ); } const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; const record = await prisma.customerBranch.create({ include: { province: true, district: true, subDistrict: true, }, data: { ...rest, customer: { connect: { id: customerId } }, province: { connect: provinceId ? { id: provinceId } : undefined }, district: { connect: districtId ? { id: districtId } : undefined }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, createdBy: req.user.name, updateBy: req.user.name, }, }); await prisma.customer.updateMany({ where: { id: customerId, status: Status.CREATED }, data: { status: Status.ACTIVE }, }); this.setStatus(HttpStatus.CREATED); return record; } @Put("{branchId}") async editById( @Request() req: RequestWithUser, @Body() body: CustomerBranchUpdate, @Path() branchId: string, ) { if (body.provinceId || body.districtId || body.subDistrictId || body.customerId) { const [province, district, subDistrict, customer] = 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 } }), prisma.customer.findFirst({ where: { id: body.customerId || undefined } }), ]); if (body.provinceId && !province) throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", "missing_or_invalid_parameter", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", "missing_or_invalid_parameter", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", "missing_or_invalid_parameter", ); if (body.customerId && !customer) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer cannot be found.", "missing_or_invalid_parameter", ); } const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; if (!(await prisma.customerBranch.findUnique({ where: { id: branchId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); } const record = await prisma.customerBranch.update({ where: { id: branchId }, include: { province: true, district: true, subDistrict: true, }, data: { ...rest, customer: { connect: customerId ? { id: customerId } : undefined }, province: { connect: provinceId ? { id: provinceId } : undefined, disconnect: provinceId === null || undefined, }, district: { connect: districtId ? { id: districtId } : undefined, disconnect: districtId === null || undefined, }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined, disconnect: subDistrictId === null || undefined, }, createdBy: req.user.name, updateBy: req.user.name, }, }); this.setStatus(HttpStatus.CREATED); return record; } }