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