refactor: update quotation
This commit is contained in:
parent
353d372dd8
commit
8ae8ec7002
2 changed files with 73 additions and 58 deletions
|
|
@ -1,8 +1,3 @@
|
|||
{
|
||||
"branch": {
|
||||
"maxHeadOfficeBranch": 10
|
||||
},
|
||||
"personnel": {
|
||||
"type": ["USER", "MESSENGER", "DELEGATE", "AGENCY"]
|
||||
}
|
||||
"vat": 0.07
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { PayCondition, Prisma, Status } from "@prisma/client";
|
||||
import config from "../config.json";
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
|
|
@ -63,6 +64,7 @@ type QuotationCreate = {
|
|||
urgent?: boolean;
|
||||
|
||||
agentPrice?: boolean;
|
||||
discount?: number;
|
||||
|
||||
productServiceList: {
|
||||
serviceId?: string;
|
||||
|
|
@ -74,12 +76,7 @@ type QuotationCreate = {
|
|||
* @minimum 0
|
||||
*/
|
||||
discount?: number;
|
||||
pricePerUnit?: number;
|
||||
/**
|
||||
* @maximum 1
|
||||
* @minimum 0
|
||||
*/
|
||||
vat?: number;
|
||||
workerIndex?: number[];
|
||||
}[];
|
||||
};
|
||||
|
||||
|
|
@ -122,6 +119,8 @@ type QuotationUpdate = {
|
|||
|
||||
urgent?: boolean;
|
||||
|
||||
discount?: number;
|
||||
|
||||
productServiceList?: {
|
||||
serviceId?: string;
|
||||
workId?: string;
|
||||
|
|
@ -132,15 +131,12 @@ type QuotationUpdate = {
|
|||
* @minimum 0
|
||||
*/
|
||||
discount: number;
|
||||
pricePerUnit?: number;
|
||||
/**
|
||||
* @maximum 1
|
||||
* @minimum 0
|
||||
*/
|
||||
vat?: number;
|
||||
workerIndex?: number[];
|
||||
}[];
|
||||
};
|
||||
|
||||
const VAT_DEFAULT = config.vat;
|
||||
|
||||
const MANAGE_ROLES = [
|
||||
"system",
|
||||
"head_of_admin",
|
||||
|
|
@ -150,7 +146,6 @@ const MANAGE_ROLES = [
|
|||
"head_of_sale",
|
||||
"sale",
|
||||
];
|
||||
const VAT_DEFAULT = 0.07;
|
||||
|
||||
function globalAllow(user: RequestWithUser["user"]) {
|
||||
const allowList = ["system", "head_of_admin", "head_of_account", "head_of_sale"];
|
||||
|
|
@ -322,28 +317,38 @@ export class QuotationController extends Controller {
|
|||
update: { value: { increment: 1 } },
|
||||
});
|
||||
|
||||
const list = body.productServiceList.map((v, i) => ({
|
||||
order: i + 1,
|
||||
productId: v.productId,
|
||||
workId: v.workId,
|
||||
serviceId: v.serviceId,
|
||||
pricePerUnit:
|
||||
product.find((p) => p.id === v.productId)?.[body.agentPrice ? "agentPrice" : "price"] ||
|
||||
0,
|
||||
amount: v.amount,
|
||||
discount: v.discount || 0,
|
||||
vat: v.vat || VAT_DEFAULT,
|
||||
}));
|
||||
const list = body.productServiceList.map((v, i) => {
|
||||
const p = product.find((p) => p.id === v.productId)!;
|
||||
const price = body.agentPrice ? p.agentPrice : p.price;
|
||||
const pricePerUnit = p.vatIncluded ? precisionRound(price / 1 + VAT_DEFAULT) : price;
|
||||
const vat = precisionRound(p.vatIncluded ? price - pricePerUnit : price * VAT_DEFAULT);
|
||||
|
||||
return {
|
||||
order: i + 1,
|
||||
productId: v.productId,
|
||||
workId: v.workId,
|
||||
serviceId: v.serviceId,
|
||||
pricePerUnit:
|
||||
product.find((p) => p.id === v.productId)?.[body.agentPrice ? "agentPrice" : "price"] ||
|
||||
0,
|
||||
amount: v.amount,
|
||||
discount: v.discount || 0,
|
||||
vat,
|
||||
worker: {
|
||||
create: sortedEmployeeId
|
||||
.filter((_, i) => !v.workerIndex || i in v.workerIndex)
|
||||
.map((employeeId) => ({ employeeId })),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const price = list.reduce(
|
||||
(a, c) => {
|
||||
const price = precisionRound(c.pricePerUnit * c.amount);
|
||||
const discount = precisionRound(price - (c.discount || 0));
|
||||
const vat = precisionRound((price - discount) * c.vat);
|
||||
const multiply = precisionRound(c.pricePerUnit * c.amount);
|
||||
|
||||
a.totalPrice = precisionRound(a.totalPrice + price);
|
||||
a.totalDiscount = precisionRound(a.totalDiscount + discount);
|
||||
a.vat = precisionRound(a.vat + vat);
|
||||
a.totalPrice = precisionRound(a.totalPrice + multiply);
|
||||
a.totalDiscount = precisionRound(a.totalDiscount + c.discount);
|
||||
a.vat = precisionRound(a.vat + c.vat);
|
||||
a.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat);
|
||||
|
||||
return a;
|
||||
|
|
@ -352,7 +357,8 @@ export class QuotationController extends Controller {
|
|||
totalPrice: 0,
|
||||
totalDiscount: 0,
|
||||
vat: 0,
|
||||
finalPrice: 0,
|
||||
discount: body.discount,
|
||||
finalPrice: -(body.discount || 0),
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -397,7 +403,9 @@ export class QuotationController extends Controller {
|
|||
})),
|
||||
},
|
||||
},
|
||||
productServiceList: { create: list },
|
||||
productServiceList: {
|
||||
create: list,
|
||||
},
|
||||
createdByUserId: req.user.sub,
|
||||
updatedByUserId: req.user.sub,
|
||||
},
|
||||
|
|
@ -517,28 +525,39 @@ export class QuotationController extends Controller {
|
|||
}
|
||||
}
|
||||
|
||||
const list = body.productServiceList?.map((v, i) => ({
|
||||
order: i + 1,
|
||||
productId: v.productId,
|
||||
workId: v.workId,
|
||||
serviceId: v.serviceId,
|
||||
pricePerUnit:
|
||||
product.find((p) => p.id === v.productId)?.[record.agentPrice ? "agentPrice" : "price"] ||
|
||||
0,
|
||||
amount: v.amount,
|
||||
discount: v.discount || 0,
|
||||
vat: v.vat || VAT_DEFAULT,
|
||||
}));
|
||||
const list = body.productServiceList?.map((v, i) => {
|
||||
const p = product.find((p) => p.id === v.productId)!;
|
||||
const price = record.agentPrice ? p.agentPrice : p.price;
|
||||
const pricePerUnit = p.vatIncluded ? precisionRound(price / 1 + VAT_DEFAULT) : price;
|
||||
const vat = precisionRound(p.vatIncluded ? price - pricePerUnit : price * VAT_DEFAULT);
|
||||
|
||||
return {
|
||||
order: i + 1,
|
||||
productId: v.productId,
|
||||
workId: v.workId,
|
||||
serviceId: v.serviceId,
|
||||
pricePerUnit:
|
||||
product.find((p) => p.id === v.productId)?.[
|
||||
record.agentPrice ? "agentPrice" : "price"
|
||||
] || 0,
|
||||
amount: v.amount,
|
||||
discount: v.discount || 0,
|
||||
vat,
|
||||
worker: {
|
||||
create: sortedEmployeeId
|
||||
.filter((_, i) => !v.workerIndex || i in v.workerIndex)
|
||||
.map((employeeId) => ({ employeeId })),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const price = list?.reduce(
|
||||
(a, c) => {
|
||||
const price = precisionRound(c.pricePerUnit * c.amount);
|
||||
const discount = precisionRound(price - (c.discount || 0));
|
||||
const vat = precisionRound((price - discount) * c.vat);
|
||||
const multiply = precisionRound(c.pricePerUnit * c.amount);
|
||||
|
||||
a.totalPrice = precisionRound(a.totalPrice + price);
|
||||
a.totalDiscount = precisionRound(a.totalDiscount + discount);
|
||||
a.vat = precisionRound(a.vat + vat);
|
||||
a.totalPrice = precisionRound(a.totalPrice + multiply);
|
||||
a.totalDiscount = precisionRound(a.totalDiscount + c.discount);
|
||||
a.vat = precisionRound(a.vat + c.vat);
|
||||
a.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat);
|
||||
|
||||
return a;
|
||||
|
|
@ -547,7 +566,8 @@ export class QuotationController extends Controller {
|
|||
totalPrice: 0,
|
||||
totalDiscount: 0,
|
||||
vat: 0,
|
||||
finalPrice: 0,
|
||||
discount: body.discount,
|
||||
finalPrice: -(body.discount || 0),
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue