From d0e207de7e9e5a1727812ff19a74fa598e895c33 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:23:41 +0700 Subject: [PATCH] feat: add quotation structure --- prisma/schema.prisma | 127 +++++++++++++++++++++++- src/controllers/quotation-controller.ts | 108 ++++++++++++++++++++ 2 files changed, 231 insertions(+), 4 deletions(-) create mode 100644 src/controllers/quotation-controller.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6431837..28d6c2b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -375,6 +375,8 @@ model User { productTypeUpdated ProductType[] @relation("ProductTypeUpdatedByUser") productCreated Product[] @relation("ProductCreatedByUser") productUpdated Product[] @relation("ProductUpdatedByUser") + quotationCreated Quotation[] @relation("QuotationCreatedByUser") + quotationUpdated Quotation[] @relation("QuotationUpdatedByUser") } enum CustomerType { @@ -405,7 +407,8 @@ model Customer { updatedBy User? @relation(name: "CustomerUpdatedByUser", fields: [updatedByUserId], references: [id], onDelete: SetNull) updatedByUserId String? - branch CustomerBranch[] + branch CustomerBranch[] + quotation Quotation[] } model CustomerBranch { @@ -462,7 +465,8 @@ model CustomerBranch { updatedBy User? @relation(name: "CustomerBranchUpdatedByUser", fields: [updatedByUserId], references: [id], onDelete: SetNull) updatedByUserId String? - employee Employee[] + employee Employee[] + quotation Quotation[] } model Employee { @@ -528,7 +532,8 @@ model Employee { employeeWork EmployeeWork[] employeeOtherInfo EmployeeOtherInfo[] - editHistory EmployeeHistory[] + editHistory EmployeeHistory[] + quotationWorker QuotationWorker[] } model EmployeeHistory { @@ -691,7 +696,8 @@ model Product { registeredBranchId String? registeredBranch Branch? @relation(fields: [registeredBranchId], references: [id]) - workProduct WorkProduct[] + workProduct WorkProduct[] + quotationServiceWorkProduct QuotationServiceWorkProduct[] createdAt DateTime @default(now()) createdBy User? @relation(name: "ProductCreatedByUser", fields: [createdByUserId], references: [id], onDelete: SetNull) @@ -767,3 +773,116 @@ model WorkProduct { @@id([workId, productId]) } + +enum PayCondition { + Full + Split + BillFull + BillSplit +} + +model Quotation { + id String @id @default(uuid()) + + customerId String + customer Customer @relation(fields: [customerId], references: [id]) + + customerBranchId String + customerBranch CustomerBranch @relation(fields: [customerBranchId], references: [id]) + + code String + date DateTime @default(now()) + payCondition PayCondition + + paySplitCount Int? + paySplit QuotationPaySplit[] + + payBillDate DateTime? + + workerCount Int + worker QuotationWorker[] + + service QuotationService[] + + urgent Boolean @default(false) + + totalPrice Float + totalDiscount Float + vat Int + vatExcluded Int + + createdAt DateTime @default(now()) + createdBy User? @relation(name: "QuotationCreatedByUser", fields: [createdByUserId], references: [id], onDelete: SetNull) + createdByUserId String? + updatedAt DateTime @updatedAt + updatedBy User? @relation(name: "QuotationUpdatedByUser", fields: [updatedByUserId], references: [id], onDelete: SetNull) + updatedByUserId String? +} + +model QuotationPaySplit { + id String @id @default(uuid()) + + no Int + date DateTime + + quotation Quotation? @relation(fields: [quotationId], references: [id]) + quotationId String? +} + +model QuotationWorker { + id String @id @default(uuid()) + + no Int + code String + employee Employee @relation(fields: [employeeId], references: [id]) + employeeId String + quotation Quotation @relation(fields: [quotationId], references: [id]) + quotationId String +} + +model QuotationService { + id String @id @default(uuid()) + + code String + name String + detail String + attributes Json? + + status Status @default(CREATED) + statusOrder Int @default(0) + + work QuotationServiceWork[] + + quotation Quotation @relation(fields: [quotationId], references: [id]) + quotationId String +} + +model QuotationServiceWork { + id String @id @default(uuid()) + + order Int + name String + attributes Json? + + status Status @default(CREATED) + statusOrder Int @default(0) + + service QuotationService @relation(fields: [serviceId], references: [id]) + serviceId String + + productOnWork QuotationServiceWorkProduct[] +} + +model QuotationServiceWorkProduct { + order Int + work QuotationServiceWork @relation(fields: [workId], references: [id]) + workId String + product Product @relation(fields: [productId], references: [id], onDelete: Cascade) + productId String + + amount Int + discount Float + pricePerUnit Float + + @@id([workId, productId]) +} diff --git a/src/controllers/quotation-controller.ts b/src/controllers/quotation-controller.ts new file mode 100644 index 0000000..77dd9c7 --- /dev/null +++ b/src/controllers/quotation-controller.ts @@ -0,0 +1,108 @@ +import { PayCondition, Status } from "@prisma/client"; +import { + Body, + Controller, + Delete, + Get, + Path, + Post, + Put, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { RequestWithUser } from "../interfaces/user"; + +type QuotationCreate = { + status?: Status; + + payCondition: PayCondition; + + paySplitCount?: number; + paySplit?: Date[]; + + payBillDate?: number; + + workerCount: number; + workerId: string[]; // EmployeeId + + urgent?: boolean; + + service: { + id: string; + // Other fields will come from original data + work?: { + // Name field will come from original data + product: { + id: string; + amount: number; + discount: number; + pricePerUnit: number; + }[]; + }[]; + }; +}; + +type QuotationUpdate = { + status?: "ACTIVE" | "INACTIVE"; + + payCondition: PayCondition; + + paySplitCount?: number; + paySplit?: Date[]; + + payBillDate?: number; + + workerCount: number; + workerId: string[]; // EmployeeId + + urgent?: boolean; + + service: { + id: string; + // Other fields will come from original data + work?: { + // Name field will come from original data + product: { + id: string; + amount: number; + discount: number; + pricePerUnit: number; + }[]; + }[]; + }; +}; + +@Route("/api/v1/quotation") +@Tags("Quotation") +export class QuotationController extends Controller { + @Get("{quotationId}") + @Security("keycloak") + async getQuotationById( + @Path() quotationId: string, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) {} + + @Get() + @Security("keycloak") + async getQuotationList(@Query() page: number = 1, @Query() pageSize: number = 30) {} + + @Post() + @Security("keycloak") + async createQuotation(@Request() req: RequestWithUser, @Body() body: QuotationCreate) {} + + @Put("{quotationId}") + @Security("keycloak") + async editQuotation( + @Request() req: RequestWithUser, + @Path() quotationId: string, + @Body() body: QuotationUpdate, + ) {} + + @Delete("{quotationId}") + @Security("keycloak") + async deleteQuotationById(@Request() req: RequestWithUser, @Path() quotationId: string) {} +}