feat: task order (#7)

* feat: add task order table

* refactor: update relation field

* feat: basic task endpoints

* feat: add filter by work status

* refactor: update relation

---------

Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
This commit is contained in:
Methapon Metanipat 2024-12-02 11:42:24 +07:00 committed by GitHub
parent ea337bd364
commit c7f69666f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 284 additions and 1 deletions

View file

@ -480,6 +480,8 @@ model User {
paymentCreated Payment[]
notificationReceive Notification[] @relation("NotificationReceiver")
notificationRead Notification[]
taskOrderCreated TaskOrder[] @relation("TaskOrderCreatedByUser")
taskOrderAccepted TaskOrder[]
}
model UserResponsibleArea {
@ -981,6 +983,8 @@ model Institution {
subDistrictId String
selectedImage String?
taskOrder TaskOrder[]
}
model WorkflowTemplate {
@ -1449,5 +1453,38 @@ model RequestWorkStepStatus {
attributes Json?
taskOrder TaskOrder? @relation(fields: [taskOrderId], references: [id])
taskOrderId String?
@@id([step, requestWorkId])
}
enum TaskStatus {
Pending
InProgress
Validate
Complete
}
model TaskOrder {
id String @id @default(cuid())
code String
taskName String
taskStatus TaskStatus @default(Pending)
taskList RequestWorkStepStatus[]
contactName String
contactTel String
institution Institution @relation(fields: [institutionId], references: [id])
institutionId String
acceptedBy User? @relation(fields: [acceptedByUserId], references: [id])
acceptedByUserId String?
createdAt DateTime @default(now())
createdBy User @relation(name: "TaskOrderCreatedByUser", fields: [createdByUserId], references: [id])
createdByUserId String
}

View file

@ -1,7 +1,12 @@
import { Body, Controller, Get, Path, Put, Query, Request, Route, Security, Tags } from "tsoa";
import { RequestWithUser } from "../interfaces/user";
import prisma from "../db";
import { Prisma, RequestDataStatus, RequestWorkStatus } from "@prisma/client";
import {
Prisma,
RequestDataStatus,
RequestWorkStatus,
RequestWorkStepStatus,
} from "@prisma/client";
import { createPermCondition } from "../services/permission";
import { queryOrNot } from "../utils/relation";
import { notFoundError } from "../utils/error";
@ -161,8 +166,10 @@ export class RequestListController extends Controller {
@Query() page: number = 1,
@Query() pageSize: number = 30,
@Query() requestDataId?: string,
@Query() workStatus?: RequestWorkStatus,
) {
const where = {
stepStatus: { some: { workStatus } },
request: {
id: requestDataId,
quotation: {

View file

@ -0,0 +1,239 @@
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()
@Security("keycloak")
async getTaskOrderList(@Query() query: string, @Query() page = 1, @Query() pageSize = 30) {
const [result, total] = await prisma.$transaction([
prisma.taskOrder.findMany({
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()
async createTaskOrderList(
@Request() req: RequestWithUser,
@Body()
body: {
taskName: string;
taskStatus: TaskStatus;
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: {
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" },
});
});
}
}