feat: add worker to quotation after accepted

This commit is contained in:
Methapon2001 2024-12-03 09:57:00 +07:00
parent 98c42464eb
commit d961d9c039

View file

@ -27,6 +27,8 @@ import { isUsedError, notFoundError, relationError } from "../utils/error";
import { precisionRound } from "../utils/arithmetic"; import { precisionRound } from "../utils/arithmetic";
import { queryOrNot } from "../utils/relation"; import { queryOrNot } from "../utils/relation";
import { deleteFile, fileLocation, getFile, getPresigned, listFile, setFile } from "../utils/minio"; import { deleteFile, fileLocation, getFile, getPresigned, listFile, setFile } from "../utils/minio";
import HttpError from "../interfaces/http-error";
import HttpStatus from "../interfaces/http-status";
type QuotationCreate = { type QuotationCreate = {
registeredBranchId: string; registeredBranchId: string;
@ -813,113 +815,76 @@ export class QuotationController extends Controller {
where: { id: quotationId }, where: { id: quotationId },
}); });
} }
}
@Post("{quotationId}/worker") @Route("api/v1/quotation/{quotationId}")
@Security("keycloak", MANAGE_ROLES) @Tags("Quotation")
export class QuotationActionController extends Controller {
@Post("add-worker")
async addWorker( async addWorker(
@Request() req: RequestWithUser, @Request() req: RequestWithUser,
@Path() quotationId: string, @Path() quotationId: string,
@Body() @Body()
body: { body: {
workerId: string; workerId: string;
productServiceListId: string[]; productServiceId: string[];
}[], }[],
) { ) {
return await prisma.$transaction(async (tx) => { const ids = {
let record = await tx.quotation.findFirst({ employee: body.map((v) => v.workerId),
include: { productService: body
_count: { .flatMap((v) => v.productServiceId)
select: { paySplit: true }, .filter((lhs, i, a) => a.findIndex((rhs) => lhs === rhs) === i),
}, };
customerBranch: {
include: { const [quotation, employee, productService] = await prisma.$transaction(
customer: { async (tx) =>
include: { await Promise.all([
registeredBranch: { include: branchRelationPermInclude(req.user) }, tx.quotation.findFirst({
},
},
},
},
worker: true,
productServiceList: {
include: { include: {
worker: true, worker: true,
work: true, _count: {
service: true, select: {
product: true, worker: true,
},
},
},
where: { id: quotationId },
});
if (!record) throw notFoundError("Quotation");
let quotation = record;
const paymentSum = await tx.payment.aggregate({
_sum: { amount: true },
where: {
invoice: {
quotationId: quotation.id,
payment: { paymentStatus: "PaymentSuccess" },
},
},
});
body = body.filter((a) => !quotation.worker.find((b) => b.employeeId === a.workerId));
if (!paymentSum._sum.amount) {
return await tx.quotation.update({
include: {
_count: {
select: { paySplit: true },
},
customerBranch: {
include: {
customer: {
include: {
registeredBranch: { include: branchRelationPermInclude(req.user) },
},
}, },
}, },
}, },
worker: true, where: { id: quotationId },
productServiceList: { }),
include: { tx.employee.findMany({
worker: true, where: { id: { in: ids.employee } },
work: true, take: ids.employee.length + 1, // NOTE: Do not find further as it should be equal to input
service: true, }),
product: true, tx.quotationProductServiceList.findMany({
}, where: { id: { in: ids.productService }, quotationId },
}, take: ids.productService.length + 1, // NOTE: Do not find further as it should be equal to input
}, }),
where: { id: quotationId }, ]),
data: { );
worker: {
createMany: { if (!quotation) throw relationError("Quotation");
data: body.map((v, i) => ({ if (ids.employee.length !== employee.length) throw relationError("Worker");
employeeId: v.workerId, if (ids.productService.length !== productService.length) throw relationError("Product");
no: quotation.worker.length + i + 1, if (quotation._count.worker >= (quotation.workerMax || 0)) {
})), throw new HttpError(
}, HttpStatus.PRECONDITION_FAILED,
}, "Worker exceed current quotation max worker.",
productServiceList: { "QuotationWorkerExceed",
update: quotation.productServiceList.map((a) => ({ );
where: { id: a.id }, }
data: {
worker: { await prisma.$transaction(async (tx) => {
createMany: { await tx.quotationProductServiceWorker.createMany({
data: body data: body
.filter((b) => b.productServiceListId.includes(a.id)) .filter((lhs) => !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId))
.map((val) => ({ employeeId: val.workerId })), .flatMap((lhs) =>
}, lhs.productServiceId.map((rhs) => ({
}, employeeId: lhs.workerId,
}, productServiceId: rhs,
})), })),
}, ),
}, skipDuplicates: true,
}); });
}
const current = new Date(); const current = new Date();
const year = `${current.getFullYear()}`.slice(-2).padStart(2, "0"); const year = `${current.getFullYear()}`.slice(-2).padStart(2, "0");
@ -935,21 +900,37 @@ export class QuotationController extends Controller {
}, },
update: { value: { increment: quotation.worker.length } }, update: { value: { increment: quotation.worker.length } },
}); });
console.log(quotation.worker);
await tx.quotation.update({ await tx.quotation.update({
where: { id: quotationId }, where: { id: quotationId },
data: { data: {
requestData: { worker: {
create: body.map((v, i) => ({ createMany: {
code: `TR${year}${month}${(lastRequest.value - quotation.worker.length + i + 1).toString().padStart(6, "0")}`, data: body
employeeId: v.workerId, .filter((lhs) => !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId))
requestWork: { .map((v, i) => ({
create: v.productServiceListId no: quotation._count.worker + i + 1,
.filter((a) => quotation.productServiceList.find((b) => a === b.id)) employeeId: v.workerId,
.map((v) => ({ productServiceId: v })), })),
}, },
})),
}, },
requestData:
quotation.quotationStatus === "PaymentInProcess" ||
quotation.quotationStatus === "PaymentSuccess"
? {
create: body
.filter(
(lhs) => !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId),
)
.map((v, i) => ({
code: `TR${year}${month}${(lastRequest.value - quotation._count.worker + i + 1).toString().padStart(6, "0")}`,
employeeId: v.workerId,
requestWork: {
create: v.productServiceId.map((v) => ({ productServiceId: v })),
},
})),
}
: undefined,
}, },
}); });
}); });