import { Body, Controller, Delete, Get, Path, Post, Put, Query, Request, Route, Security, Tags, } from "tsoa"; import prisma from "../db"; import { notFoundError } from "../utils/error"; import { TaskStatus } from "@prisma/client"; import { RequestWithUser } from "../interfaces/user"; @Route("/api/v1/task") @Tags("Task Order") export class TaskController extends Controller { @Get("stats") async getTaskOrderStats() { const task = await prisma.taskOrder.groupBy({ by: ["taskStatus"], _count: true, }); return task.reduce>( (a, c) => Object.assign(a, { [c.taskStatus]: c._count }), { [TaskStatus.Pending]: 0, [TaskStatus.InProgress]: 0, [TaskStatus.Validate]: 0, [TaskStatus.Complete]: 0, }, ); } @Get() @Security("keycloak") async getTaskOrderList( @Query() query: string = "", @Query() page = 1, @Query() pageSize = 30, @Query() taskStatus?: TaskStatus, ) { const [result, total] = await prisma.$transaction([ prisma.taskOrder.findMany({ where: { taskStatus, OR: [ { code: { contains: query, mode: "insensitive" } }, { taskName: { contains: query } }, { contactName: { contains: query } }, { contactTel: { contains: query } }, ], }, include: { institution: true, acceptedBy: true, createdBy: true, }, }), prisma.taskOrder.count(), ]); return { result, total, page, pageSize }; } @Get("{taskId}") @Security("keycloak") async getTaskOrder(@Path() taskId: string) { const record = await prisma.taskOrder.findFirst({ where: { id: taskId }, include: { taskList: { include: { requestWork: { include: { productService: true, }, }, }, }, institution: true, acceptedBy: true, createdBy: true, }, }); if (!record) throw notFoundError("Task Order"); return record; } @Post() @Security("keycloak") async createTaskOrderList( @Request() req: RequestWithUser, @Body() body: { taskName: string; contactName: string; contactTel: string; institutionId: string; requestWork: { requestWorkId: string; step: number }[]; }, ) { return await prisma.$transaction(async (tx) => { const last = await tx.runningNo.upsert({ where: { key: "TASK", }, create: { key: "TASK", value: 1, }, update: { value: { increment: 1 }, }, }); const current = new Date(); const year = `${current.getFullYear()}`.slice(-2).padStart(2, "0"); const month = `${current.getMonth() + 1}`.padStart(2, "0"); const code = `PO${year}${month}${last.value.toString().padStart(6, "0")}`; await tx.taskOrder.create({ include: { taskList: { include: { requestWork: true, }, }, institution: true, acceptedBy: true, createdBy: true, }, data: { ...body, code, createdByUserId: req.user.sub, taskList: { connect: body.requestWork.map((v) => ({ step_requestWorkId: v })), }, }, }); }); } @Put("{taskId}") async editTaskById( @Path() taskId: string, @Body() body: { taskName: string; taskStatus: TaskStatus; contactName: string; contactTel: string; institutionId: string; requestWork: { requestWorkId: string; step: number }[]; }, ) { const record = await prisma.taskOrder.findFirst({ where: { id: taskId }, include: { taskList: { include: { requestWork: true }, }, institution: true, acceptedBy: true, createdBy: true, }, }); await prisma.taskOrder.update({ where: { id: taskId }, include: { taskList: { include: { requestWork: true, }, }, institution: true, acceptedBy: true, createdBy: true, }, data: { ...body, taskList: { disconnect: record?.taskList .filter( (lhs) => !body.requestWork.find( (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, ), ) .map((v) => ({ step_requestWorkId: { requestWorkId: v.requestWorkId, step: v.step, }, })), connect: body.requestWork.map((v) => ({ step_requestWorkId: v })), }, }, }); } @Delete("{taskId}") async deleteTask(@Path() taskId: string) { await prisma.$transaction(async (tx) => { let record = await tx.taskOrder.deleteMany({ where: { id: taskId } }); if (record.count <= 0) throw notFoundError("Task Order"); }); } } @Route("/api/v1/task/{taskId}") @Tags("Task Order") export class TaskActionController extends Controller { @Post("accept") async acceptTaskOrder(@Request() req: RequestWithUser, @Path() taskId: string) { const record = await prisma.taskOrder.findFirst({ include: { taskList: { orderBy: { step: "asc" }, }, }, where: { id: taskId }, }); if (!record) throw notFoundError("Task Order"); return await prisma.$transaction(async (tx) => { await tx.taskOrder.update({ where: { id: taskId }, data: { taskStatus: "InProgress", acceptedByUserId: req.user.sub, }, }); await tx.requestWorkStepStatus.updateMany({ where: { taskOrderId: taskId }, data: { workStatus: "InProgress", }, }); await tx.requestData.updateMany({ where: { requestWork: { some: { stepStatus: { some: { taskOrderId: taskId }, }, }, }, }, data: { requestDataStatus: "InProgress" }, }); }); } }