From 53453e37db4cdd898c161910fae977b6759df85e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 6 Jan 2025 14:59:59 +0700 Subject: [PATCH] refactor: store credit note value in database --- prisma/schema.prisma | 2 + src/controllers/08-credit-note-controller.ts | 112 ++++++++++++++++++- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d9e16d1..1f269d9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1584,6 +1584,8 @@ model CreditNote { creditNoteStatus CreditNoteStatus @default(Pending) + value Float @default(0) + quotation Quotation @relation(fields: [quotationId], references: [id], onDelete: Cascade) quotationId String diff --git a/src/controllers/08-credit-note-controller.ts b/src/controllers/08-credit-note-controller.ts index e37365e..a6c977b 100644 --- a/src/controllers/08-credit-note-controller.ts +++ b/src/controllers/08-credit-note-controller.ts @@ -25,7 +25,7 @@ import { import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; import { notFoundError } from "../utils/error"; -import { Prisma } from "@prisma/client"; +import { CreditNoteStatus, Prisma } from "@prisma/client"; import { queryOrNot } from "../utils/relation"; import { RequestWorkStatus } from "../generated/kysely/types"; @@ -217,6 +217,15 @@ export class CreditNoteController extends Controller { id: { in: body.requestWorkId }, }, include: { + stepStatus: true, + productService: { + include: { + product: true, + work: { + include: { productOnWork: true }, + }, + }, + }, request: { include: { quotation: { @@ -237,6 +246,21 @@ export class CreditNoteController extends Controller { requestWork.map((item) => permissionCheck(req.user, item.request.quotation.registeredBranch)), ); + const value = requestWork.reduce((a, c) => { + const serviceChargeStepCount = c.productService.work?.productOnWork.find( + (v) => v.productId === c.productService.productId, + )?.stepCount; + + const successCount = c.stepStatus.filter((v) => v.workStatus === "Completed").length; + + if (serviceChargeStepCount && successCount) { + return ( + a + c.productService.product.price - c.productService.product.serviceCharge * successCount + ); + } + return a + c.productService.product.price; + }, 0); + const record = await prisma.creditNote.create({ include: { requestWork: { @@ -247,6 +271,7 @@ export class CreditNoteController extends Controller { quotation: true, }, data: { + value, requestWork: { connect: body.requestWorkId.map((v) => ({ id: v, @@ -297,16 +322,49 @@ export class CreditNoteController extends Controller { }, id: { in: body.requestWorkId }, }, + include: { + stepStatus: true, + productService: { + include: { + product: true, + work: { + include: { productOnWork: true }, + }, + }, + }, + request: { + include: { + quotation: { + include: { + registeredBranch: { include: branchRelationPermInclude(req.user) }, + }, + }, + }, + }, + }, }); if (requestWork.length !== body.requestWorkId.length) { throw new HttpError(HttpStatus.BAD_REQUEST, "Not Match", "reqNotMet"); } + const value = requestWork.reduce((a, c) => { + const serviceChargeStepCount = c.productService.work?.productOnWork.find( + (v) => v.productId === c.productService.productId, + )?.stepCount; + + const successCount = c.stepStatus.filter((v) => v.workStatus === "Completed").length; + + if (serviceChargeStepCount && successCount) { + return ( + a + c.productService.product.price - c.productService.product.serviceCharge * successCount + ); + } + return a + c.productService.product.price; + }, 0); + const record = await prisma.creditNote.update({ - where: { - id: creditNoteId, - }, + where: { id: creditNoteId }, include: { requestWork: { include: { @@ -316,6 +374,7 @@ export class CreditNoteController extends Controller { quotation: true, }, data: { + value, requestWork: { disconnect: creditNoteData.requestWork .map((item) => ({ @@ -354,3 +413,48 @@ export class CreditNoteController extends Controller { return await prisma.creditNote.delete({ where: { id: creditNoteId } }); } } + +@Route("api/v1/credit-note/{creditNoteId}") +@Tags("Credit Note") +export class CreditNoteActionController extends Controller { + async #checkPermission(user: RequestWithUser["user"], id: string) { + const creditNoteData = await prisma.creditNote.findFirst({ + where: { id }, + include: { + requestWork: true, + quotation: { + include: { + registeredBranch: { include: branchRelationPermInclude(user) }, + }, + }, + }, + }); + if (!creditNoteData) throw notFoundError("Credit Note"); + await permissionCheck(user, creditNoteData.quotation.registeredBranch); + return creditNoteData; + } + + @Post("status") + @Security("keycloak", MANAGE_ROLES) + async updateStatus( + @Request() req: RequestWithUser, + @Path() creditNoteId: string, + @Body() body: CreditNoteStatus, + ) { + await this.#checkPermission(req.user, creditNoteId); + return await prisma.creditNote.update({ + where: { id: creditNoteId }, + include: { + requestWork: { + include: { + request: true, + }, + }, + quotation: true, + }, + data: { + creditNoteStatus: body, + }, + }); + } +}