feat: structure input before insert to database
This commit is contained in:
parent
1cf1915209
commit
0319990232
1 changed files with 175 additions and 6 deletions
|
|
@ -26,7 +26,7 @@ type QuotationCreate = {
|
||||||
paySplitCount?: number;
|
paySplitCount?: number;
|
||||||
paySplit?: Date[];
|
paySplit?: Date[];
|
||||||
|
|
||||||
payBillDate?: number;
|
payBillDate?: Date;
|
||||||
|
|
||||||
workerCount: number;
|
workerCount: number;
|
||||||
// EmployeeId or Create new employee
|
// EmployeeId or Create new employee
|
||||||
|
|
@ -65,12 +65,12 @@ type QuotationCreate = {
|
||||||
id: string;
|
id: string;
|
||||||
// Other fields will come from original data
|
// Other fields will come from original data
|
||||||
work: {
|
work: {
|
||||||
|
id: string;
|
||||||
// Name field will come from original data
|
// Name field will come from original data
|
||||||
product: {
|
product: {
|
||||||
id: string;
|
id: string;
|
||||||
amount: number;
|
amount: number;
|
||||||
discount: number;
|
discount: number;
|
||||||
pricePerUnit: number;
|
|
||||||
}[];
|
}[];
|
||||||
}[];
|
}[];
|
||||||
}[];
|
}[];
|
||||||
|
|
@ -84,7 +84,7 @@ type QuotationUpdate = {
|
||||||
paySplitCount?: number;
|
paySplitCount?: number;
|
||||||
paySplit?: Date[];
|
paySplit?: Date[];
|
||||||
|
|
||||||
payBillDate?: number;
|
payBillDate?: Date;
|
||||||
|
|
||||||
workerCount: number;
|
workerCount: number;
|
||||||
// EmployeeId or Create new employee
|
// EmployeeId or Create new employee
|
||||||
|
|
@ -123,12 +123,12 @@ type QuotationUpdate = {
|
||||||
id: string;
|
id: string;
|
||||||
// Other fields will come from original data
|
// Other fields will come from original data
|
||||||
work: {
|
work: {
|
||||||
|
id: string;
|
||||||
// Name field will come from original data
|
// Name field will come from original data
|
||||||
product: {
|
product: {
|
||||||
id: string;
|
id: string;
|
||||||
amount: number;
|
amount: number;
|
||||||
discount: number;
|
discount: number;
|
||||||
pricePerUnit: number;
|
|
||||||
}[];
|
}[];
|
||||||
}[];
|
}[];
|
||||||
}[];
|
}[];
|
||||||
|
|
@ -197,7 +197,168 @@ export class QuotationController extends Controller {
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@Security("keycloak")
|
@Security("keycloak")
|
||||||
async createQuotation(@Request() req: RequestWithUser, @Body() body: QuotationCreate) {}
|
async createQuotation(@Request() req: RequestWithUser, @Body() body: QuotationCreate) {
|
||||||
|
const existingEmployee = body.worker.filter((v) => typeof v === "string");
|
||||||
|
const serviceIdList = body.service.map((v) => v.id);
|
||||||
|
const productIdList = body.service.flatMap((a) =>
|
||||||
|
a.work.flatMap((b) => b.product.map((c) => c.id)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const [customer, customerBranch, employee, service, product] = await prisma.$transaction([
|
||||||
|
prisma.customer.findUnique({
|
||||||
|
where: { id: body.customerId },
|
||||||
|
}),
|
||||||
|
prisma.customerBranch.findUnique({
|
||||||
|
include: { customer: true },
|
||||||
|
where: { id: body.customerBranchId },
|
||||||
|
}),
|
||||||
|
prisma.employee.findMany({
|
||||||
|
where: { id: { in: existingEmployee } },
|
||||||
|
}),
|
||||||
|
prisma.service.findMany({
|
||||||
|
include: {
|
||||||
|
work: true,
|
||||||
|
},
|
||||||
|
where: { id: { in: serviceIdList } },
|
||||||
|
}),
|
||||||
|
prisma.product.findMany({
|
||||||
|
where: { id: { in: productIdList } },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!customer)
|
||||||
|
throw new HttpError(
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
"Customer cannot be found.",
|
||||||
|
"relationCustomerNotFound",
|
||||||
|
);
|
||||||
|
if (!customerBranch)
|
||||||
|
throw new HttpError(
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
"Customer Branch cannot be found.",
|
||||||
|
"relationCustomerBranchNotFound",
|
||||||
|
);
|
||||||
|
|
||||||
|
const { service: _service, worker: _worker, ...rest } = body;
|
||||||
|
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
const nonExistEmployee = body.worker.filter((v) => typeof v !== "string");
|
||||||
|
const lastEmployee = await tx.runningNo.upsert({
|
||||||
|
where: {
|
||||||
|
key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`,
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
update: { value: { increment: nonExistEmployee.length } },
|
||||||
|
});
|
||||||
|
const newEmployee = await Promise.all(
|
||||||
|
nonExistEmployee.map(async (v, i) =>
|
||||||
|
tx.employee.create({
|
||||||
|
data: {
|
||||||
|
...v,
|
||||||
|
code: `${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${(lastEmployee.value + i).toString().padStart(4, "0")}`,
|
||||||
|
customerBranchId: customerBranch.id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const sortedEmployeeId: string[] = [];
|
||||||
|
|
||||||
|
while (body.worker.length > 0) {
|
||||||
|
const popExist = body.worker.shift();
|
||||||
|
if (typeof popExist === "string") sortedEmployeeId.push(popExist);
|
||||||
|
else {
|
||||||
|
const popNew = newEmployee.shift();
|
||||||
|
popNew && sortedEmployeeId.push(popNew.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const price = { totalPrice: 0, totalDiscount };
|
||||||
|
const restructureService = body.service.flatMap((a) => {
|
||||||
|
const currentService = service.find((b) => b.id === a.id);
|
||||||
|
|
||||||
|
if (!currentService) return []; // should not possible
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: currentService.id,
|
||||||
|
name: currentService.name,
|
||||||
|
code: currentService.code,
|
||||||
|
detail: currentService.detail,
|
||||||
|
work: a.work.flatMap((c) => {
|
||||||
|
const currentWork = currentService.work.find((d) => d.id === c.id);
|
||||||
|
|
||||||
|
if (!currentWork) return []; // should not possible
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: currentWork.id,
|
||||||
|
order: currentWork.order,
|
||||||
|
name: currentWork.name,
|
||||||
|
product: c.product.flatMap((e) => {
|
||||||
|
const currentProduct = product.find((f) => f.id === e.id);
|
||||||
|
|
||||||
|
if (!currentProduct) return []; // should not possible
|
||||||
|
|
||||||
|
return { ...e, pricePerUnit: currentProduct.price };
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const quotation = await tx.quotation.create({
|
||||||
|
data: {
|
||||||
|
...rest,
|
||||||
|
statusOrder: +(rest.status === "INACTIVE"),
|
||||||
|
code: "",
|
||||||
|
worker: {
|
||||||
|
createMany: {
|
||||||
|
data: sortedEmployeeId.map((v, i) => ({
|
||||||
|
no: i,
|
||||||
|
code: "",
|
||||||
|
employeeId: v,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
service: {
|
||||||
|
createMany: {
|
||||||
|
data: body.service.flatMap((a) => {
|
||||||
|
const src = service.find((b) => b.id == a.id);
|
||||||
|
return src
|
||||||
|
? {
|
||||||
|
id: a.id,
|
||||||
|
name: src.name,
|
||||||
|
code: src.code,
|
||||||
|
detail: src.detail,
|
||||||
|
}
|
||||||
|
: []; // should not be possible to not found.
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
totalPrice,
|
||||||
|
totalDiscount,
|
||||||
|
vatExcluded: 0,
|
||||||
|
vat: 0,
|
||||||
|
paySplit: {
|
||||||
|
createMany: {
|
||||||
|
data: (rest.paySplit || []).map((v, i) => ({
|
||||||
|
no: i + 1,
|
||||||
|
date: v,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// await tx.quotationServiceWork.createMany({
|
||||||
|
// data: service.flatMap((a) =>
|
||||||
|
// a.work.map((b) => ({ id: b.id, order: b.order, name: b.name, serviceId: a.id })),
|
||||||
|
// ),
|
||||||
|
// });
|
||||||
|
|
||||||
|
throw new Error("Test Quotation Structure");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Put("{quotationId}")
|
@Put("{quotationId}")
|
||||||
@Security("keycloak")
|
@Security("keycloak")
|
||||||
|
|
@ -205,7 +366,15 @@ export class QuotationController extends Controller {
|
||||||
@Request() req: RequestWithUser,
|
@Request() req: RequestWithUser,
|
||||||
@Path() quotationId: string,
|
@Path() quotationId: string,
|
||||||
@Body() body: QuotationUpdate,
|
@Body() body: QuotationUpdate,
|
||||||
) {}
|
) {
|
||||||
|
const record = await prisma.quotation.findUnique({
|
||||||
|
where: { id: quotationId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!record) {
|
||||||
|
throw new HttpError(HttpStatus.NOT_FOUND, "Quotation not found.", "quotationNotFound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Delete("{quotationId}")
|
@Delete("{quotationId}")
|
||||||
@Security("keycloak")
|
@Security("keycloak")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue