diff --git a/prisma/migrations/20241009080435_add_request_list_tables/migration.sql b/prisma/migrations/20241009080435_add_request_list_tables/migration.sql new file mode 100644 index 0000000..0baeb93 --- /dev/null +++ b/prisma/migrations/20241009080435_add_request_list_tables/migration.sql @@ -0,0 +1,29 @@ +-- CreateTable +CREATE TABLE "RequestData" ( + "id" TEXT NOT NULL, + "employeeId" TEXT NOT NULL, + "quotationId" TEXT NOT NULL, + + CONSTRAINT "RequestData_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RequestWork" ( + "id" TEXT NOT NULL, + "requestDataId" TEXT NOT NULL, + "productServiceId" TEXT NOT NULL, + + CONSTRAINT "RequestWork_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "RequestData" ADD CONSTRAINT "RequestData_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RequestData" ADD CONSTRAINT "RequestData_quotationId_fkey" FOREIGN KEY ("quotationId") REFERENCES "Quotation"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RequestWork" ADD CONSTRAINT "RequestWork_requestDataId_fkey" FOREIGN KEY ("requestDataId") REFERENCES "RequestData"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RequestWork" ADD CONSTRAINT "RequestWork_productServiceId_fkey" FOREIGN KEY ("productServiceId") REFERENCES "QuotationProductServiceList"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f2ab6c1..f9afa06 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -734,6 +734,7 @@ model Employee { editHistory EmployeeHistory[] quotationWorker QuotationWorker[] quotationProductServiceWorker QuotationProductServiceWorker[] + requestData RequestData[] } model EmployeeHistory { @@ -1119,6 +1120,8 @@ model Quotation { discount Float @default(0) finalPrice Float + requestData RequestData[] + createdAt DateTime @default(now()) createdBy User? @relation(name: "QuotationCreatedByUser", fields: [createdByUserId], references: [id], onDelete: SetNull) createdByUserId String? @@ -1170,7 +1173,8 @@ model QuotationProductServiceList { serviceId String? service Service? @relation(fields: [serviceId], references: [id]) - worker QuotationProductServiceWorker[] + worker QuotationProductServiceWorker[] + RequestWork RequestWork[] } model QuotationProductServiceWorker { @@ -1182,3 +1186,25 @@ model QuotationProductServiceWorker { @@id([productServiceId, employeeId]) } + +model RequestData { + id String @id @default(cuid()) + + employee Employee @relation(fields: [employeeId], references: [id]) + employeeId String + + quotation Quotation @relation(fields: [quotationId], references: [id]) + quotationId String + + requestWork RequestWork[] +} + +model RequestWork { + id String @id @default(cuid()) + + request RequestData @relation(fields: [requestDataId], references: [id]) + requestDataId String + + productService QuotationProductServiceList @relation(fields: [productServiceId], references: [id]) + productServiceId String +} diff --git a/src/controllers/05-quotation-payment-controller.ts b/src/controllers/05-quotation-payment-controller.ts index 7918d77..1918438 100644 --- a/src/controllers/05-quotation-payment-controller.ts +++ b/src/controllers/05-quotation-payment-controller.ts @@ -51,16 +51,41 @@ export class QuotationPayment extends Controller { @Post("confirm") async confirmPayment(@Path("quotationId") id: string) { const record = await prisma.quotation.findUnique({ + include: { + worker: true, + productServiceList: { + include: { + worker: true, + work: true, + service: true, + product: true, + }, + }, + }, where: { id }, }); if (!record) throw notFoundError("Quotation"); - await prisma.quotation.update({ - where: { id }, - data: { quotationStatus: "PaymentSuccess" }, + await prisma.$transaction(async (tx) => { + await tx.quotation.update({ + where: { id }, + data: { + quotationStatus: "PaymentSuccess", + requestData: { + create: record.worker.map((v) => ({ + employeeId: v.employeeId, + requestWork: { + create: record.productServiceList.flatMap((item) => + item.worker.findIndex((w) => w.employeeId === v.employeeId) !== -1 + ? { productServiceId: item.id } + : [], + ), + }, + })), + }, + }, + }); }); - - // TODO: Generate request list (Work) by match product with worker (Employee) } } diff --git a/src/controllers/06-request-list-controller.ts b/src/controllers/06-request-list-controller.ts new file mode 100644 index 0000000..cbd2918 --- /dev/null +++ b/src/controllers/06-request-list-controller.ts @@ -0,0 +1,43 @@ +import { Controller, Delete, Get, Path, Put, Query, Request, Route, Security, Tags } from "tsoa"; +import { RequestWithUser } from "../interfaces/user"; +import prisma from "../db"; + +@Route("api/v1/request-list") +@Tags("Request List") +export class RequestListController extends Controller { + @Get() + @Security("keycloak") + async getRequest( + @Request() req: RequestWithUser, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + return await prisma.requestWork.findMany({ + include: { request: true }, + take: pageSize, + skip: (page - 1) * pageSize, + }); + } + + @Get("{requestId}") + async getRequestById(@Path() requestId: string) { + return await prisma.requestWork.findFirst({ + include: { request: true }, + where: { id: requestId }, + }); + } + + /** @todo */ + @Put("{requestId}") + async updateRequestById(@Request() req: RequestWithUser, @Path() requestId: string) { + return {}; + } + + /** @todo */ + @Delete("{requestId}") + async deleteRequestById(@Request() req: RequestWithUser, @Path() requestId: string) { + return {}; + } +} + +export class RequestListAttachmentController extends Controller {} diff --git a/src/utils/minio.ts b/src/utils/minio.ts index 6eba4db..2fdcf1f 100644 --- a/src/utils/minio.ts +++ b/src/utils/minio.ts @@ -93,4 +93,8 @@ export const fileLocation = { quotation: { payment: (quotationId: string) => `quotation/payment-${quotationId}`, }, + request: { + attachment: (requestId: string, name?: string) => + `request/attachment-${requestId}/${name || ""}`, + }, };