diff --git a/prisma/migrations/20240409040419_update/migration.sql b/prisma/migrations/20240409040419_update/migration.sql new file mode 100644 index 0000000..f43823a --- /dev/null +++ b/prisma/migrations/20240409040419_update/migration.sql @@ -0,0 +1,5 @@ +-- CreateEnum +CREATE TYPE "UserType" AS ENUM ('USER', 'MESSENGER', 'DELEGATE', 'AGENCY'); + +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "code" DROP NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9896ee5..cc45b79 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -73,7 +73,7 @@ enum Status { model Branch { id String @id @default(uuid()) - code String @default(uuid()) + code String taxNo String name String nameEN String @@ -143,12 +143,19 @@ model BranchUser { updatedAt DateTime @updatedAt } +enum UserType { + USER + MESSENGER + DELEGATE + AGENCY +} + model User { id String @id @default(uuid()) keycloakId String - code String @default(uuid()) + code String? firstName String firstNameEN String lastName String @@ -177,7 +184,7 @@ model User { startDate DateTime? retireDate DateTime? - userType String + userType UserType userRole String discountCondition String? @@ -203,7 +210,7 @@ model User { model Customer { id String @id @default(uuid()) - code String @default(uuid()) + code String customerType String customerName String customerNameEN String diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index 503d215..c96e5a2 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -1,4 +1,4 @@ -import { Prisma, Status } from "@prisma/client"; +import { Prisma, Status, UserType } from "@prisma/client"; import { Body, Controller, @@ -71,10 +71,23 @@ export class BranchUserController extends Controller { @Path() branchId: string, @Body() body: BranchUserBody, ) { - const user = await prisma.user.findMany({ - include: { branch: true }, - where: { id: { in: body.user } }, - }); + 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( @@ -84,21 +97,55 @@ export class BranchUserController extends Controller { ); } - await prisma.user.updateMany({ - where: { id: { in: body.user }, status: Status.CREATED }, - data: { status: Status.ACTIVE }, - }); + 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, + })), + }), + ]); - await 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.user.findFirst({ + orderBy: { createdAt: "desc" }, + where: { + userType: g, + code: { startsWith: `${branch.code.slice(2, 5).padEnd(3, "0")}` }, + }, + }); + + const code = (idx: number) => + `${branch.code.slice(4).padEnd(3, "0")}${g !== "USER" ? g.charAt(0) : ""}${(+(last?.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() diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 672f7cb..5c6d1d1 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -12,7 +12,7 @@ import { Security, Tags, } from "tsoa"; -import { Prisma, Status } from "@prisma/client"; +import { Prisma, Status, UserType } from "@prisma/client"; import prisma from "../db"; import minio from "../services/minio"; @@ -31,7 +31,7 @@ type UserCreate = { keycloakId: string; - userType: string; + userType: UserType; userRole: string; firstName: string; @@ -40,7 +40,6 @@ type UserCreate = { lastNameEN: string; gender: string; - code?: string; registrationNo?: string; startDate?: Date; retireDate?: Date; @@ -66,7 +65,7 @@ type UserCreate = { type UserUpdate = { status?: "ACTIVE" | "INACTIVE"; - userType?: string; + userType?: UserType; userRole?: string; firstName?: string; @@ -75,7 +74,6 @@ type UserUpdate = { lastNameEN?: string; gender?: string; - code?: string; registrationNo?: string; startDate?: Date; retireDate?: Date; @@ -108,7 +106,7 @@ function imageLocation(id: string) { export class UserController extends Controller { @Get() async getUser( - @Query() userType?: string, + @Query() userType?: UserType, @Query() zipCode?: string, @Query() query: string = "", @Query() page: number = 1, @@ -276,10 +274,36 @@ export class UserController extends Controller { const { provinceId, districtId, subDistrictId, ...rest } = body; + const user = await prisma.user.findFirst({ + where: { id: userId }, + }); + + if (!user) { + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + } + + const lastUserOfType = + body.userType && + body.userType !== user.userType && + user.code && + (await prisma.user.findFirst({ + orderBy: { createdAt: "desc" }, + where: { + userType: body.userType, + code: { startsWith: `${user.code?.slice(0, 3)}` }, + }, + })); + + console.log(lastUserOfType); + const record = await prisma.user.update({ include: { province: true, district: true, subDistrict: true }, data: { ...rest, + code: + (lastUserOfType && + `${user.code?.slice(0, 3)}${body.userType !== "USER" ? body.userType?.charAt(0) : ""}${(+(lastUserOfType?.code?.slice(-4) || 0) + 1).toString().padStart(4, "0")}`) || + undefined, province: { connect: provinceId ? { id: provinceId } : undefined, disconnect: provinceId === null || undefined, @@ -296,9 +320,7 @@ export class UserController extends Controller { }, where: { id: userId }, }); - if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found."); - } + return Object.assign(record, { profileImageUrl: await minio.presignedGetObject( MINIO_BUCKET,