import { Body, Controller, Delete, Get, Put, Path, Post, Query, Request, Route, Security, Tags, } from "tsoa"; import { Prisma, Status } from "@prisma/client"; import prisma from "../../db"; import { RequestWithUser } from "../../interfaces/user"; import HttpError from "../../interfaces/http-error"; import HttpStatus from "../../interfaces/http-status"; type ProductGroupCreate = { name: string; detail: string; remark: string; }; type ProductGroupUpdate = { name?: string; detail?: string; remark?: string; }; @Route("api/v1/product-group") @Tags("Product Group") @Security("keycloak") export class ProductGroup extends Controller { @Get("stats") async getProductGroupStats() { return await prisma.productGroup.count(); } @Get() async getProductGroup(@Query() query: string = "", @Query() status?: Status) { const filterStatus = (val?: Status) => { if (!val) return {}; return val !== Status.CREATED && val !== Status.ACTIVE ? { status: val } : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; }; const where = { OR: [ { name: { contains: query }, ...filterStatus(status) }, { detail: { contains: query }, ...filterStatus(status) }, ], } satisfies Prisma.ProductGroupWhereInput; return prisma.productGroup.findMany({ orderBy: { createdAt: "asc" }, where }); } @Get("{groupId}") async getProductGroupById(@Path() groupId: string) { const record = await prisma.productGroup.findFirst({ where: { id: groupId }, }); if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); return record; } @Post() async createProductGroup(@Request() req: RequestWithUser, @Body() body: ProductGroupCreate) { const record = await prisma.$transaction( async (tx) => { const last = await tx.runningNo.upsert({ where: { key: `PRODGRP`, }, create: { key: `PRODGRP`, value: 1, }, update: { value: { increment: 1 } }, }); return await tx.productGroup.create({ data: { ...body, code: `G${last.value.toString().padStart(2, "0")}`, createdBy: req.user.name, updateBy: req.user.name, }, }); }, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, ); this.setStatus(HttpStatus.CREATED); return record; } @Put("{groupId}") async editProductGroup( @Request() req: RequestWithUser, @Body() body: ProductGroupUpdate, @Path() groupId: string, ) { if (!(await prisma.productGroup.findUnique({ where: { id: groupId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); } const record = await prisma.productGroup.update({ data: { ...body, updateBy: req.user.name }, where: { id: groupId }, }); return record; } @Delete("{groupId}") async deleteProductGroup(@Path() groupId: string) { const record = await prisma.productGroup.findFirst({ where: { id: groupId } }); if (!record) { throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); } if (record.status !== Status.CREATED) { throw new HttpError(HttpStatus.FORBIDDEN, "Product group is in used.", "productGroupInUsed"); } return await prisma.productGroup.delete({ where: { id: groupId } }); } }