jws-backend/src/controllers/work/work-controller.ts

312 lines
6.8 KiB
TypeScript
Raw Normal View History

2024-06-12 09:01:22 +07:00
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 WorkCreate = {
2024-06-14 15:49:05 +07:00
order: number;
2024-06-12 09:01:22 +07:00
name: string;
productId: string[];
2024-06-13 15:47:11 +07:00
attributes?: {
[key: string]: any;
};
2024-06-12 09:01:22 +07:00
};
type WorkUpdate = {
2024-06-14 15:49:05 +07:00
order?: number;
2024-06-12 09:01:22 +07:00
name?: string;
productId?: string[];
2024-06-13 15:47:11 +07:00
attributes?: {
[key: string]: any;
};
2024-06-12 09:01:22 +07:00
};
@Route("api/v1/work")
@Tags("Work")
@Security("keycloak")
export class WorkController extends Controller {
@Get()
async getWork(
2024-06-20 15:32:15 +07:00
@Query() baseOnly?: boolean,
2024-06-12 09:01:22 +07:00
@Query() query: string = "",
@Query() page: number = 1,
@Query() pageSize: number = 30,
) {
const where = {
2024-06-20 15:32:15 +07:00
OR: [{ name: { contains: query }, serviceId: baseOnly ? null : undefined }],
2024-06-12 09:01:22 +07:00
} satisfies Prisma.WorkWhereInput;
const [result, total] = await prisma.$transaction([
prisma.work.findMany({
include: {
productOnWork: {
include: {
product: true,
},
orderBy: {
order: "asc",
},
},
},
2024-06-12 09:01:22 +07:00
orderBy: { createdAt: "asc" },
where,
take: pageSize,
skip: (page - 1) * pageSize,
}),
prisma.work.count({ where }),
]);
return { result, page, pageSize, total };
}
@Get("{workId}")
async getWorkById(@Path() workId: string) {
const record = await prisma.work.findFirst({
where: { id: workId },
});
2024-06-14 15:49:05 +07:00
if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound");
2024-06-12 09:01:22 +07:00
return record;
}
2024-06-12 09:01:22 +07:00
@Get("{workId}/product")
async getProductOfWork(
@Path() workId: string,
@Query() query: string = "",
@Query() page: number = 1,
@Query() pageSize: number = 30,
) {
const where = {
AND: [
{
workProduct: { some: { workId } },
2024-06-12 09:01:22 +07:00
},
{
OR: [{ name: { contains: query } }],
},
],
} satisfies Prisma.ProductWhereInput;
const [result, total] = await prisma.$transaction([
prisma.product.findMany({
where,
take: pageSize,
skip: (page - 1) * pageSize,
}),
prisma.product.count({
where,
}),
]);
return { result, page, pageSize, total };
}
@Post()
async createWork(@Request() req: RequestWithUser, @Body() body: WorkCreate) {
const { productId, ...payload } = body;
const exist = await prisma.work.findFirst({
include: {
productOnWork: {
include: {
product: true,
},
},
},
where: {
productOnWork: {
every: {
productId: { in: productId },
},
},
NOT: {
OR: [
{
productOnWork: {
some: {
productId: { notIn: productId },
},
},
},
{
productOnWork: {
none: {},
},
},
],
},
},
});
if (exist) return exist;
const productList = await prisma.product.findMany({
where: { id: { in: productId } },
2024-06-12 09:01:22 +07:00
});
if (productList.length !== productId.length) {
2024-06-14 15:49:05 +07:00
throw new HttpError(HttpStatus.BAD_REQUEST, "Some product not found.", "someProductBadReq");
2024-06-12 09:01:22 +07:00
}
const record = await prisma.work.create({
include: {
productOnWork: {
include: {
product: true,
},
orderBy: {
order: "asc",
},
},
},
2024-06-12 09:01:22 +07:00
data: {
...payload,
productOnWork: {
createMany: {
data: productId.map((v, i) => ({
order: i + 1,
productId: v,
2024-07-01 13:24:02 +07:00
createdByUserId: req.user.sub,
updatedByUserId: req.user.sub,
})),
},
},
2024-07-01 13:24:02 +07:00
createdByUserId: req.user.sub,
updatedByUserId: req.user.sub,
2024-06-12 09:01:22 +07:00
},
});
await prisma.product.updateMany({
where: { id: { in: body.productId }, status: Status.CREATED },
2024-06-12 09:01:22 +07:00
data: { status: Status.ACTIVE },
});
this.setStatus(HttpStatus.CREATED);
return record;
}
@Put("{workId}")
async editWork(
2024-06-12 09:01:22 +07:00
@Request() req: RequestWithUser,
@Body() body: WorkUpdate,
@Path() workId: string,
) {
const { productId, ...payload } = body;
2024-06-12 09:01:22 +07:00
if (!(await prisma.work.findUnique({ where: { id: workId } }))) {
2024-06-14 05:43:32 +00:00
throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound");
2024-06-12 09:01:22 +07:00
}
const exist = await prisma.work.findFirst({
include: {
productOnWork: {
include: {
product: true,
},
},
},
where: {
productOnWork: {
every: {
productId: { in: productId },
},
},
NOT: {
OR: [
{ id: workId },
{
productOnWork: {
some: {
productId: { notIn: productId },
},
},
},
{
productOnWork: {
none: {},
},
},
],
},
},
});
if (exist) return exist;
2024-06-12 09:01:22 +07:00
const record = await prisma.work.update({
include: {
productOnWork: {
include: {
product: true,
},
orderBy: {
order: "asc",
},
},
},
2024-06-12 09:01:22 +07:00
where: { id: workId },
data: {
...payload,
productOnWork: productId
? {
deleteMany: {
productId: { notIn: productId },
},
upsert: productId.map((v, i) => ({
where: {
workId_productId: {
workId,
productId: v,
},
},
update: { order: i + 1 },
create: {
order: i + 1,
productId: v,
2024-07-01 13:24:02 +07:00
createdByUserId: req.user.sub,
updatedByUserId: req.user.sub,
},
})),
}
: undefined,
2024-07-01 13:24:02 +07:00
updatedByUserId: req.user.sub,
},
2024-06-12 09:01:22 +07:00
});
return record;
}
@Delete("{workId}")
async deleteWork(@Path() workId: string) {
const record = await prisma.work.findFirst({ where: { id: workId } });
if (!record) {
2024-06-14 05:43:32 +00:00
throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound");
2024-06-12 09:01:22 +07:00
}
if (record.status !== Status.CREATED) {
2024-06-14 05:43:32 +00:00
throw new HttpError(HttpStatus.FORBIDDEN, "Work is in used.", "workInUsed");
2024-06-12 09:01:22 +07:00
}
return await prisma.work.delete({ where: { id: workId } });
}
}