feat: add worker to quotation after accepted
This commit is contained in:
parent
98c42464eb
commit
d961d9c039
1 changed files with 85 additions and 104 deletions
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue