refactor: price calculate
All checks were successful
Spell Check / Spell Check with Typos (push) Successful in 4s

This commit is contained in:
Methapon2001 2025-09-10 11:39:39 +07:00
parent 0f0075fa94
commit 105e9dbf4b
3 changed files with 92 additions and 45 deletions

View file

@ -525,24 +525,22 @@ export class QuotationController extends Controller {
const p = product.find((p) => p.id === v.productId)!; const p = product.find((p) => p.id === v.productId)!;
const vatIncluded = body.agentPrice ? p.agentPriceVatIncluded : p.vatIncluded; const vatIncluded = body.agentPrice ? p.agentPriceVatIncluded : p.vatIncluded;
const vatCalc = body.agentPrice ? p.agentPriceCalcVat : p.calcVat;
const originalPrice = body.agentPrice ? p.agentPrice : p.price; const originalPrice = body.agentPrice ? p.agentPrice : p.price;
const finalPriceWithVat = precisionRound(
originalPrice + (vatIncluded ? 0 : originalPrice * VAT_DEFAULT),
);
const price = finalPriceWithVat; const price = vatIncluded ? originalPrice / (1 + VAT_DEFAULT) : originalPrice;
const pricePerUnit = price / (1 + VAT_DEFAULT); const priceWithVat = precisionRound(price * (1 + VAT_DEFAULT));
const vat = (body.agentPrice ? p.agentPriceCalcVat : p.calcVat)
? (pricePerUnit * v.amount - (v.discount || 0)) * VAT_DEFAULT const finalPrice = (vatCalc ? price : priceWithVat) * v.amount - (v.discount ?? 0);
: 0; const vat = vatCalc ? finalPrice - finalPrice / (1 + VAT_DEFAULT) : 0;
return { return {
order: i + 1, order: i + 1,
productId: v.productId, productId: v.productId,
workId: v.workId, workId: v.workId,
serviceId: v.serviceId, serviceId: v.serviceId,
pricePerUnit, pricePerUnit: vatCalc ? priceWithVat / (1 + VAT_DEFAULT) : price,
amount: v.amount, amount: v.amount,
discount: v.discount || 0, discount: v.discount || 0,
installmentNo: v.installmentNo, installmentNo: v.installmentNo,
@ -813,24 +811,22 @@ export class QuotationController extends Controller {
const p = product.find((p) => p.id === v.productId)!; const p = product.find((p) => p.id === v.productId)!;
const vatIncluded = record.agentPrice ? p.agentPriceVatIncluded : p.vatIncluded; const vatIncluded = record.agentPrice ? p.agentPriceVatIncluded : p.vatIncluded;
const vatCalc = record.agentPrice ? p.agentPriceCalcVat : p.calcVat;
const originalPrice = record.agentPrice ? p.agentPrice : p.price; const originalPrice = record.agentPrice ? p.agentPrice : p.price;
const finalPriceWithVat = precisionRound(
originalPrice + (vatIncluded ? 0 : originalPrice * VAT_DEFAULT),
);
const price = finalPriceWithVat; const price = vatIncluded ? originalPrice / (1 + VAT_DEFAULT) : originalPrice;
const pricePerUnit = price / (1 + VAT_DEFAULT); const priceWithVat = precisionRound(price * (1 + VAT_DEFAULT));
const vat = (record.agentPrice ? p.agentPriceCalcVat : p.calcVat)
? (pricePerUnit * v.amount - (v.discount || 0)) * VAT_DEFAULT const finalPrice = (vatCalc ? price : priceWithVat) * v.amount - (v.discount ?? 0);
: 0; const vat = vatCalc ? finalPrice - finalPrice / (1 + VAT_DEFAULT) : 0;
return { return {
order: i + 1, order: i + 1,
productId: v.productId, productId: v.productId,
workId: v.workId, workId: v.workId,
serviceId: v.serviceId, serviceId: v.serviceId,
pricePerUnit, pricePerUnit: vatCalc ? priceWithVat / (1 + VAT_DEFAULT) : price,
amount: v.amount, amount: v.amount,
discount: v.discount || 0, discount: v.discount || 0,
installmentNo: v.installmentNo, installmentNo: v.installmentNo,

View file

@ -430,20 +430,24 @@ export class DebitNoteController extends Controller {
const list = body.productServiceList.map((v, i) => { const list = body.productServiceList.map((v, i) => {
const p = product.find((p) => p.id === v.productId)!; const p = product.find((p) => p.id === v.productId)!;
const price = body.agentPrice ? p.agentPrice : p.price;
const pricePerUnit = p.vatIncluded ? price / (1 + VAT_DEFAULT) : price; const vatIncluded = body.agentPrice ? p.agentPriceVatIncluded : p.vatIncluded;
const vat = p.calcVat const vatCalc = body.agentPrice ? p.agentPriceCalcVat : p.calcVat;
? (pricePerUnit * (v.discount ? v.amount : 1) - (v.discount || 0)) *
VAT_DEFAULT * const originalPrice = body.agentPrice ? p.agentPrice : p.price;
(!v.discount ? v.amount : 1)
: 0; const price = vatIncluded ? originalPrice / (1 + VAT_DEFAULT) : originalPrice;
const priceWithVat = precisionRound(price * (1 + VAT_DEFAULT));
const finalPrice = (vatCalc ? price : priceWithVat) * v.amount - (v.discount ?? 0);
const vat = vatCalc ? finalPrice - finalPrice / (1 + VAT_DEFAULT) : 0;
return { return {
order: i + 1, order: i + 1,
productId: v.productId, productId: v.productId,
workId: v.workId, workId: v.workId,
serviceId: v.serviceId, serviceId: v.serviceId,
pricePerUnit, pricePerUnit: vatCalc ? priceWithVat / (1 + VAT_DEFAULT) : price,
amount: v.amount, amount: v.amount,
discount: v.discount || 0, discount: v.discount || 0,
installmentNo: v.installmentNo, installmentNo: v.installmentNo,
@ -673,20 +677,24 @@ export class DebitNoteController extends Controller {
} }
const list = body.productServiceList.map((v, i) => { const list = body.productServiceList.map((v, i) => {
const p = product.find((p) => p.id === v.productId)!; const p = product.find((p) => p.id === v.productId)!;
const price = body.agentPrice ? p.agentPrice : p.price;
const pricePerUnit = p.vatIncluded ? price / (1 + VAT_DEFAULT) : price; const vatIncluded = record.agentPrice ? p.agentPriceVatIncluded : p.vatIncluded;
const vat = p.calcVat const vatCalc = record.agentPrice ? p.agentPriceCalcVat : p.calcVat;
? (pricePerUnit * (v.discount ? v.amount : 1) - (v.discount || 0)) *
VAT_DEFAULT * const originalPrice = record.agentPrice ? p.agentPrice : p.price;
(!v.discount ? v.amount : 1)
: 0; const price = vatIncluded ? originalPrice / (1 + VAT_DEFAULT) : originalPrice;
const priceWithVat = precisionRound(price * (1 + VAT_DEFAULT));
const finalPrice = (vatCalc ? price : priceWithVat) * v.amount - (v.discount ?? 0);
const vat = vatCalc ? finalPrice - finalPrice / (1 + VAT_DEFAULT) : 0;
return { return {
order: i + 1, order: i + 1,
productId: v.productId, productId: v.productId,
workId: v.workId, workId: v.workId,
serviceId: v.serviceId, serviceId: v.serviceId,
pricePerUnit, pricePerUnit: vatCalc ? priceWithVat / (1 + VAT_DEFAULT) : price,
amount: v.amount, amount: v.amount,
discount: v.discount || 0, discount: v.discount || 0,
installmentNo: v.installmentNo, installmentNo: v.installmentNo,

View file

@ -1,6 +1,7 @@
import prisma from "../db"; import prisma from "../db";
import config from "../config.json"; import config from "../config.json";
import { CustomerType, PayCondition } from "@prisma/client"; import { CustomerType, PayCondition } from "@prisma/client";
import { convertTemplate } from "../utils/string-template";
if (!process.env.FLOW_ACCOUNT_URL) throw new Error("Require FLOW_ACCOUNT_URL"); if (!process.env.FLOW_ACCOUNT_URL) throw new Error("Require FLOW_ACCOUNT_URL");
if (!process.env.FLOW_ACCOUNT_CLIENT_ID) throw new Error("Require FLOW_ACCOUNT_CLIENT_ID"); if (!process.env.FLOW_ACCOUNT_CLIENT_ID) throw new Error("Require FLOW_ACCOUNT_CLIENT_ID");
@ -182,17 +183,14 @@ const flowAccountAPI = {
data.paymentDate = `${year}-${String(month).padStart(2, "0")}-${String(date).padStart(2, "0")}`; data.paymentDate = `${year}-${String(month).padStart(2, "0")}-${String(date).padStart(2, "0")}`;
} */ } */
const res = await fetch( const res = await fetch(api + "/tax-invoices/inline" + (withPayment ? "/with-payment" : ""), {
api + "/upgrade/receipts/inline" + (withPayment ? "/with-payment" : ""), method: "POST",
{ headers: {
method: "POST", ["Content-Type"]: `application/json`,
headers: { ["Authorization"]: `Bearer ${token}`,
["Content-Type"]: `application/json`,
["Authorization"]: `Bearer ${token}`,
},
body: JSON.stringify({ ...data, referenceDocument: [] }),
}, },
); body: JSON.stringify({ ...data, referenceDocument: [] }),
});
return { return {
ok: res.ok, ok: res.ok,
@ -232,6 +230,28 @@ const flowAccount = {
installments: true, installments: true,
quotation: { quotation: {
include: { include: {
paySplit: {
select: {
amount: true,
no: true,
},
},
worker: {
select: {
employee: {
select: {
namePrefix: true,
firstNameEN: true,
lastNameEN: true,
employeePassport: {
select: { number: true },
orderBy: { expireDate: "desc" },
take: 1,
},
},
},
},
},
registeredBranch: { registeredBranch: {
include: { include: {
province: true, province: true,
@ -305,6 +325,7 @@ const flowAccount = {
isVat: true, isVat: true,
useReceiptDeduction: false, useReceiptDeduction: false,
useInlineVat: true,
discounPercentage: 0, discounPercentage: 0,
discountAmount: quotation.totalDiscount, discountAmount: quotation.totalDiscount,
@ -325,7 +346,29 @@ const flowAccount = {
quotation.payCondition === "BillSplitCustom" || quotation.payCondition === "SplitCustom" quotation.payCondition === "BillSplitCustom" || quotation.payCondition === "SplitCustom"
? data.installments.reduce((a, c) => a + c.amount, 0) ? data.installments.reduce((a, c) => a + c.amount, 0)
: quotation.finalPrice, : quotation.finalPrice,
remark: quotation.remark
? convertTemplate(quotation.remark, {
"quotation-payment": {
paymentType: quotation.payCondition,
amount: quotation.finalPrice,
installments: quotation.paySplit.map((v) => ({ no: v.no, amount: v.amount })),
},
"quotation-labor": {
name: quotation.worker.map((v) =>
(
(v.employee.employeePassport.at(0)?.number
? v.employee.employeePassport.at(0)?.number + "_"
: "") +
v.employee.namePrefix +
"." +
v.employee.firstNameEN +
" " +
v.employee.lastNameEN
).toUpperCase(),
),
},
})
: null,
items: product.map((v) => ({ items: product.map((v) => ({
type: ProductAndServiceType.ProductNonInv, type: ProductAndServiceType.ProductNonInv,
name: v.product.name, name: v.product.name,