import { Prisma, Status, UserType } from "@prisma/client"; import { Body, Controller, Delete, Get, Path, Post, Query, Request, Route, Security, Tags, } from "tsoa"; import prisma from "../db"; import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; import { RequestWithUser } from "../interfaces/user"; type BranchUserBody = { user: string[] }; @Route("api/branch/{branchId}/user") @Tags("Branch User") @Security("keycloak") export class BranchUserController extends Controller { @Get() async getBranchUser( @Path() branchId: string, @Query() zipCode?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { OR: [ { user: { firstName: { contains: query }, zipCode }, branchId }, { user: { firstNameEN: { contains: query }, zipCode }, branchId }, { user: { lastName: { contains: query }, zipCode }, branchId }, { user: { lastNameEN: { contains: query }, zipCode }, branchId }, { user: { email: { contains: query }, zipCode }, branchId }, { user: { telephoneNo: { contains: query }, zipCode }, branchId }, ], } satisfies Prisma.BranchUserWhereInput; const [result, total] = await prisma.$transaction([ prisma.branchUser.findMany({ orderBy: { user: { createdAt: "asc" } }, include: { user: { include: { province: true, district: true, subDistrict: true, }, }, }, where, take: pageSize, skip: (page - 1) * pageSize, }), prisma.branchUser.count({ where }), ]); return { result: result.map((v) => v.user), page, pageSize, total }; } @Post() async createBranchUser( @Request() req: RequestWithUser, @Path() branchId: string, @Body() body: BranchUserBody, ) { const [branch, user] = await prisma.$transaction([ prisma.branch.findUnique({ where: { id: branchId }, }), prisma.user.findMany({ include: { branch: true }, where: { id: { in: body.user } }, }), ]); if (!branch) { throw new HttpError( HttpStatus.BAD_REQUEST, "Branch cannot be found.", "missing_or_invalid_parameter", ); } if (user.length !== body.user.length) { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more user cannot be found.", "missing_or_invalid_parameter", ); } await prisma.$transaction([ prisma.user.updateMany({ where: { id: { in: body.user }, status: Status.CREATED }, data: { status: Status.ACTIVE }, }), prisma.branchUser.createMany({ data: user .filter((a) => !a.branch.some((b) => b.branchId === branchId)) .map((v) => ({ branchId, userId: v.id, createdBy: req.user.name, updateBy: req.user.name, })), }), ]); const group: Record = { USER: [], AGENCY: [], DELEGATE: [], MESSENGER: [], }; for (const u of user) group[u.userType].push(u.id); for (const g of Object.values(UserType)) { if (group[g].length === 0) continue; const last = await prisma.branchUser.findFirst({ orderBy: { createdAt: "desc" }, include: { user: true }, where: { branchId, user: { userType: g, code: { startsWith: `${branch.code.slice(4).padEnd(3, "0")}` }, }, }, }); const code = (idx: number) => `${branch.code.slice(4).padEnd(3, "0")}${g !== "USER" ? g.charAt(0) : ""}${(+(last?.user.code?.slice(-4) || 0) + idx + 1).toString().padStart(4, "0")}`; await prisma.$transaction( group[g].map((v, i) => prisma.user.updateMany({ where: { id: v, code: null }, data: { code: code(i) }, }), ), ); } } @Delete() async deleteBranchUser(@Path() branchId: string, @Body() body: BranchUserBody) { await prisma.$transaction( body.user.map((v) => prisma.branchUser.deleteMany({ where: { branchId, userId: v } })), ); await prisma.user.updateMany({ where: { branch: { none: {} }, }, data: { code: null }, }); } @Delete("{userId}") async deleteBranchUserById(@Path() branchId: string, @Path() userId: string) { await prisma.branchUser.deleteMany({ where: { branchId, userId }, }); await prisma.user.updateMany({ where: { id: userId, branch: { none: {} }, }, data: { code: null }, }); } } type UserBranchBody = { branch: string[] }; @Route("api/user/{userId}/branch") @Tags("Branch User") @Security("keycloak") export class UserBranchController extends Controller { @Get() async getUserBranch( @Path() userId: string, @Query() zipCode?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { OR: [ { branch: { name: { contains: query }, zipCode }, userId }, { branch: { nameEN: { contains: query }, zipCode }, userId }, ], } satisfies Prisma.BranchUserWhereInput; const [result, total] = await prisma.$transaction([ prisma.branchUser.findMany({ orderBy: { branch: { createdAt: "asc" } }, include: { branch: { include: { province: true, district: true, subDistrict: true, }, }, }, where, take: pageSize, skip: (page - 1) * pageSize, }), prisma.branchUser.count({ where }), ]); return { result: result.map((v) => v.branch), page, pageSize, total }; } @Post() async createUserBranch( @Request() req: RequestWithUser, @Path() userId: string, @Body() body: UserBranchBody, ) { const branch = await prisma.branch.findMany({ include: { user: true }, where: { id: { in: body.branch } }, }); if (branch.length !== body.branch.length) { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more branch cannot be found.", "missing_or_invalid_parameter", ); } await prisma.branch.updateMany({ where: { id: { in: body.branch }, status: Status.CREATED }, data: { status: Status.ACTIVE }, }); await prisma.branchUser.createMany({ data: branch .filter((a) => !a.user.some((b) => b.userId === userId)) .map((v) => ({ branchId: v.id, userId, createdBy: req.user.name, updateBy: req.user.name, })), }); this.setStatus(HttpStatus.CREATED); } @Delete() async deleteUserBranch(@Path() userId: string, @Body() body: UserBranchBody) { await prisma.$transaction( body.branch.map((v) => prisma.branchUser.deleteMany({ where: { userId, branchId: v } })), ); await prisma.user.updateMany({ where: { branch: { none: {} }, }, data: { code: null }, }); } @Delete("{branchId}") async deleteUserBranchById(@Path() branchId: string, @Path() userId: string) { await prisma.branchUser.deleteMany({ where: { branchId, userId }, }); await prisma.user.updateMany({ where: { id: userId, branch: { none: {} }, }, data: { code: null }, }); } }