washday-sdk 0.0.160 → 0.0.162
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/utils/orders/calculateTotalTaxesIncluded.js +33 -21
- package/dist/utils/orders/calculateTotalTaxesOverPrice.js +24 -34
- package/dist/utils/orders/helpers.js +17 -27
- package/package.json +1 -1
- package/src/utils/orders/calculateOrderTotal.test.js +541 -8
- package/src/utils/orders/calculateTotalTaxesIncluded.ts +44 -28
- package/src/utils/orders/calculateTotalTaxesOverPrice.ts +29 -36
- package/src/utils/orders/helpers.ts +128 -144
|
@@ -2,20 +2,25 @@ import { getProductTaxesPercentage } from "./helpers";
|
|
|
2
2
|
export const calculateTotalTaxesIncluded = (order, selectedCustomer, storeSettings, storeDiscounts, appliedOrderDiscounts, discountCodeObj) => {
|
|
3
3
|
const productTableImports = [...order.products, ...order.buyAndGetProducts].map((current) => {
|
|
4
4
|
var _a, _b;
|
|
5
|
+
const qty = current.qty || 0;
|
|
6
|
+
const taxPercentage = getProductTaxesPercentage(current, storeSettings);
|
|
7
|
+
const taxFactor = 1 + taxPercentage / 100;
|
|
8
|
+
// Convert extraAmount from gross to net (assume extraAmount is not discounted)
|
|
9
|
+
const extraAmountGross = current.extraAmount || 0;
|
|
10
|
+
const extraAmountNet = extraAmountGross / taxFactor;
|
|
11
|
+
// Get the product’s gross price (excluding extraAmount)
|
|
12
|
+
const productGrossPrice = order.express ? current.expressPrice : current.price;
|
|
13
|
+
// Convert product gross price to net
|
|
14
|
+
const unitNetPrice = productGrossPrice / taxFactor;
|
|
15
|
+
// Determine discount percentage (if any) – discount is applied only on product net price.
|
|
5
16
|
let discPercentageInteger = 0;
|
|
6
17
|
let productPercentageDiscount = 0;
|
|
7
18
|
let customerDiscount = 0;
|
|
8
|
-
let qty = current.qty || 0;
|
|
9
|
-
const extraAmountPerUnit = current.extraAmount / qty;
|
|
10
|
-
const prodPrice = (order.express ? current.expressPrice : current.price) + extraAmountPerUnit;
|
|
11
19
|
if (!order.discountCode) {
|
|
12
20
|
const discountsToApply = storeDiscounts.filter((discount) => discount.products.includes(current._id) && discount.isActive);
|
|
13
21
|
customerDiscount = ((_a = selectedCustomer === null || selectedCustomer === void 0 ? void 0 : selectedCustomer.customer) === null || _a === void 0 ? void 0 : _a.discount) || 0;
|
|
14
22
|
productPercentageDiscount = discountsToApply.reduce((prev, next) => {
|
|
15
|
-
|
|
16
|
-
return prev + next.value;
|
|
17
|
-
}
|
|
18
|
-
return prev;
|
|
23
|
+
return next.type === 'percentage' ? prev + next.value : prev;
|
|
19
24
|
}, 0);
|
|
20
25
|
discPercentageInteger = +((productPercentageDiscount + customerDiscount) / 100).toFixed(2);
|
|
21
26
|
discountsToApply.forEach((discount) => (appliedOrderDiscounts[discount._id] = discount));
|
|
@@ -37,22 +42,29 @@ export const calculateTotalTaxesIncluded = (order, selectedCustomer, storeSettin
|
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const
|
|
45
|
+
// Calculate discount on product net price only.
|
|
46
|
+
const discountAmountPerUnit = discPercentageInteger ? unitNetPrice * discPercentageInteger : 0;
|
|
47
|
+
const discountedUnitNetPrice = unitNetPrice - discountAmountPerUnit;
|
|
48
|
+
// Reapply VAT to get discounted product gross price.
|
|
49
|
+
const discountedUnitGrossPrice = discountedUnitNetPrice * taxFactor;
|
|
50
|
+
// Now, calculate the final totals:
|
|
51
|
+
// For the product part:
|
|
52
|
+
const productNetTotalWithoutDiscount = unitNetPrice * qty;
|
|
53
|
+
const productNetTotalWithDiscount = discountedUnitNetPrice * qty;
|
|
54
|
+
// Add the extraAmount net (since it is not discounted):
|
|
55
|
+
const totalNetWithoutDiscount = productNetTotalWithoutDiscount + extraAmountNet;
|
|
56
|
+
const totalNetWithDiscount = productNetTotalWithDiscount + extraAmountNet;
|
|
57
|
+
// Reapply VAT to both totals:
|
|
58
|
+
const productLineImportTotal = +(totalNetWithoutDiscount * taxFactor).toFixed(2);
|
|
59
|
+
const productLineTotalWithDiscount = +(totalNetWithDiscount * taxFactor).toFixed(2);
|
|
60
|
+
// Calculate the taxes as the difference between gross and net:
|
|
61
|
+
const totalTaxesApplied = +(productLineImportTotal - totalNetWithoutDiscount).toFixed(2);
|
|
62
|
+
const lineDiscount = +(discountAmountPerUnit * qty).toFixed(2);
|
|
51
63
|
return {
|
|
52
64
|
product: current,
|
|
53
|
-
qty
|
|
54
|
-
productLineImportTotal
|
|
55
|
-
productLineTotalWithDiscount
|
|
65
|
+
qty,
|
|
66
|
+
productLineImportTotal, // original gross total (no discount)
|
|
67
|
+
productLineTotalWithDiscount, // gross total after discount on product (extra not discounted)
|
|
56
68
|
productLineTaxesTotal: totalTaxesApplied,
|
|
57
69
|
lineDiscountAmount: lineDiscount
|
|
58
70
|
};
|
|
@@ -7,24 +7,16 @@ export const calculateTotalTaxesOverPrice = (order, selectedCustomer, storeSetti
|
|
|
7
7
|
let productPercentageDiscount = 0;
|
|
8
8
|
let customerDiscount = 0;
|
|
9
9
|
let qty = current.qty;
|
|
10
|
-
//
|
|
11
|
-
const
|
|
12
|
-
|
|
10
|
+
// Precio base sin impuestos y sin extraAmount
|
|
11
|
+
const productBasePrice = order.express ? current.expressPrice : current.price;
|
|
12
|
+
// Calcular descuentos solo sobre el producto
|
|
13
13
|
if (!order.discountCode) {
|
|
14
|
-
//IF ORDER HAS A DISCOUNT CODE WE DON'T APPLY ANY OTHER DISCOUNT (AUTOMATICALLY OR CUSTOMER DISCOUNT)
|
|
15
|
-
//THIS WILL GET THE DISCOUNTS OF THE CURRENT PRODUCT
|
|
16
|
-
// get store discounts if product applies and customer discount
|
|
17
14
|
const discountsToApply = storeDiscounts.filter((discount) => discount.products.includes(current._id) && discount.isActive);
|
|
18
15
|
customerDiscount = ((_a = selectedCustomer === null || selectedCustomer === void 0 ? void 0 : selectedCustomer.customer) === null || _a === void 0 ? void 0 : _a.discount) || 0;
|
|
19
|
-
productPercentageDiscount = discountsToApply.reduce((
|
|
20
|
-
|
|
21
|
-
// for now we just sum percetange type discounts
|
|
22
|
-
return prev + next.value;
|
|
23
|
-
}
|
|
24
|
-
return prev;
|
|
16
|
+
productPercentageDiscount = discountsToApply.reduce((acc, discount) => {
|
|
17
|
+
return discount.type === 'percentage' ? acc + discount.value : acc;
|
|
25
18
|
}, 0);
|
|
26
19
|
discPercentageInteger = +((productPercentageDiscount + customerDiscount) / 100).toFixed(2);
|
|
27
|
-
discountsToApply.forEach((discount) => (appliedOrderDiscounts[discount._id] = discount)); // it will do this for every product, if two products has the same discount it will just overwrite
|
|
28
20
|
}
|
|
29
21
|
else {
|
|
30
22
|
if (discountCodeObj.type === DiscountCodeTypes.PERCENTAGE) {
|
|
@@ -35,32 +27,30 @@ export const calculateTotalTaxesOverPrice = (order, selectedCustomer, storeSetti
|
|
|
35
27
|
: 0;
|
|
36
28
|
}
|
|
37
29
|
}
|
|
38
|
-
if (discountCodeObj.type === DiscountCodeTypes.BUY_X_GET_Y) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
discPercentageInteger = +(discountValue / 100).toFixed(2);
|
|
30
|
+
else if (discountCodeObj.type === DiscountCodeTypes.BUY_X_GET_Y) {
|
|
31
|
+
const condition = discountCodeObj.buyAndGetConditions[0];
|
|
32
|
+
if (condition.getDiscountType === BuyAndGetConditionsTypes.PERCENTAGE && current.isBuyAndGetProduct) {
|
|
33
|
+
discPercentageInteger = +(condition.discountValue / 100).toFixed(2);
|
|
43
34
|
}
|
|
44
35
|
}
|
|
45
36
|
}
|
|
46
|
-
//
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let prodLinePriceWithDiscount = +(qty * prodPriceWithDiscountPerUnit).toFixed(2);
|
|
37
|
+
// Calcular descuento solo sobre el producto
|
|
38
|
+
const productDiscount = productBasePrice * discPercentageInteger;
|
|
39
|
+
const discountedProductPrice = productBasePrice - productDiscount;
|
|
40
|
+
// Calcular subtotal: se aplica el descuento al producto, y luego se suma el extraAmount (que se cobra completo)
|
|
41
|
+
const subtotal = (discountedProductPrice * qty) + current.extraAmount;
|
|
42
|
+
// Calcular impuestos sobre el subtotal final
|
|
43
|
+
const taxPercentage = getProductTaxesPercentage(current, storeSettings) / 100;
|
|
44
|
+
const taxes = subtotal * taxPercentage;
|
|
45
|
+
// Resultados finales
|
|
46
|
+
const totalTaxesApplied = +(taxes).toFixed(2);
|
|
47
|
+
const lineDiscount = +(productDiscount * qty).toFixed(2);
|
|
48
|
+
// Se suma el extraAmount a la parte del producto descontado para obtener el valor total a cobrar de la línea
|
|
49
|
+
const prodLinePriceWithDiscount = +(((discountedProductPrice * qty) + current.extraAmount)).toFixed(2);
|
|
60
50
|
return {
|
|
61
51
|
product: current,
|
|
62
|
-
qty
|
|
63
|
-
productLineImportTotal:
|
|
52
|
+
qty,
|
|
53
|
+
productLineImportTotal: (productBasePrice * qty) + current.extraAmount,
|
|
64
54
|
productLineTotalWithDiscount: prodLinePriceWithDiscount,
|
|
65
55
|
productLineTaxesTotal: totalTaxesApplied,
|
|
66
56
|
lineDiscountAmount: lineDiscount
|
|
@@ -56,42 +56,37 @@ export const getCreditApplied = (selectedCustomer, orderTotal) => {
|
|
|
56
56
|
return Math.min(customerCredit, orderTotal);
|
|
57
57
|
};
|
|
58
58
|
export const applyDiscountToProducts = (discountCode, productsArr, isExpress, storeDiscounts = [], selectedCustomer = { discount: 0 }) => {
|
|
59
|
-
var _a, _b;
|
|
60
59
|
if (!discountCode) {
|
|
61
|
-
|
|
60
|
+
// Caso sin discountCode: se aplican descuentos automáticos solo sobre el precio del producto
|
|
62
61
|
return {
|
|
63
62
|
newOrderProds: productsArr.map((prod) => {
|
|
64
63
|
const discountsToApply = storeDiscounts.filter((discount) => discount.products.includes(prod._id) && discount.isActive);
|
|
65
64
|
const customerDiscount = (selectedCustomer === null || selectedCustomer === void 0 ? void 0 : selectedCustomer.discount) / 100 || 0;
|
|
66
65
|
const productPercentageDiscount = discountsToApply.reduce((prev, next) => {
|
|
67
66
|
if (next.type === 'percentage') {
|
|
68
|
-
// for now we just sum percetange type discounts
|
|
69
67
|
return prev + next.value / 100;
|
|
70
68
|
}
|
|
71
69
|
return prev;
|
|
72
70
|
}, 0);
|
|
73
71
|
const prodPrice = isExpress ? prod.expressPrice : prod.price;
|
|
74
|
-
|
|
75
|
-
const discountAmount = +((productPercentageDiscount + customerDiscount) *
|
|
76
|
-
(prodPrice + extraAmountPerUnit)).toFixed(2);
|
|
72
|
+
// Se remueve el extraAmountPerUnit para que el descuento se aplique solo sobre prodPrice
|
|
73
|
+
const discountAmount = +((productPercentageDiscount + customerDiscount) * prodPrice).toFixed(2);
|
|
77
74
|
return Object.assign(Object.assign({}, prod), { discountAmount: discountAmount });
|
|
78
75
|
}),
|
|
79
76
|
buyAndGetProds: []
|
|
80
77
|
};
|
|
81
78
|
}
|
|
82
|
-
//
|
|
83
|
-
let newOrderProds = productsArr.map((prod) => {
|
|
84
|
-
|
|
85
|
-
});
|
|
86
|
-
//THIS ARRAY ALSO INCLUDES PRODUCTS OF FREE_ITEM discount code type
|
|
79
|
+
// Reiniciar los descuentos en los productos
|
|
80
|
+
let newOrderProds = productsArr.map((prod) => (Object.assign(Object.assign({}, prod), { discountAmount: 0 })));
|
|
81
|
+
// Array para productos de descuento BUY_X_GET_Y o FREE_ITEM
|
|
87
82
|
const buyAndGetProds = [];
|
|
88
83
|
if (discountCode && discountCode.type === DiscountCodeTypes.PERCENTAGE) {
|
|
89
84
|
const percentageDiscount = discountCode.value / 100;
|
|
90
85
|
if (discountCode.applyToAllProducts) {
|
|
91
86
|
newOrderProds = newOrderProds.map((prod) => {
|
|
92
87
|
const prodPrice = isExpress ? prod.expressPrice : prod.price;
|
|
93
|
-
|
|
94
|
-
const discountAmount = +(percentageDiscount *
|
|
88
|
+
// Aplica descuento solo sobre prodPrice (no se incluye extraAmountPerUnit)
|
|
89
|
+
const discountAmount = +(percentageDiscount * prodPrice).toFixed(2);
|
|
95
90
|
return Object.assign(Object.assign({}, prod), { discountAmount: discountAmount });
|
|
96
91
|
});
|
|
97
92
|
}
|
|
@@ -101,8 +96,7 @@ export const applyDiscountToProducts = (discountCode, productsArr, isExpress, st
|
|
|
101
96
|
if (prodIdx !== -1) {
|
|
102
97
|
let prodObj = newOrderProds[prodIdx];
|
|
103
98
|
const prodPrice = isExpress ? prodObj.expressPrice : prodObj.price;
|
|
104
|
-
const
|
|
105
|
-
const discountAmount = +(percentageDiscount * (prodPrice + extraAmountPerUnit)).toFixed(2);
|
|
99
|
+
const discountAmount = +(percentageDiscount * prodPrice).toFixed(2);
|
|
106
100
|
prodObj.discountAmount = discountAmount;
|
|
107
101
|
newOrderProds[prodIdx] = prodObj;
|
|
108
102
|
}
|
|
@@ -113,9 +107,7 @@ export const applyDiscountToProducts = (discountCode, productsArr, isExpress, st
|
|
|
113
107
|
const discountAmount = discountCode.value;
|
|
114
108
|
if (!discountCode.applyOnceOnOrder) {
|
|
115
109
|
if (discountCode.applyToAllProducts) {
|
|
116
|
-
newOrderProds = newOrderProds.map((prod) => {
|
|
117
|
-
return Object.assign(Object.assign({}, prod), { discountAmount: discountAmount });
|
|
118
|
-
});
|
|
110
|
+
newOrderProds = newOrderProds.map((prod) => (Object.assign(Object.assign({}, prod), { discountAmount: discountAmount })));
|
|
119
111
|
}
|
|
120
112
|
else {
|
|
121
113
|
for (let discountProduct of discountCode.products) {
|
|
@@ -137,7 +129,7 @@ export const applyDiscountToProducts = (discountCode, productsArr, isExpress, st
|
|
|
137
129
|
let buyConditionFulfilledCounter = 0;
|
|
138
130
|
for (let prodCondition of buyConditions) {
|
|
139
131
|
const orderProd = productsArr.find((ordProd) => ordProd._id === prodCondition.buyProduct._id);
|
|
140
|
-
//
|
|
132
|
+
// Nota: Aquí solo se verifica una condición de producto
|
|
141
133
|
if (orderProd) {
|
|
142
134
|
let qty = orderProd.qty || orderProd.quantity;
|
|
143
135
|
buyConditionFulfilledCounter = Math.floor(qty / prodCondition.qty);
|
|
@@ -145,15 +137,14 @@ export const applyDiscountToProducts = (discountCode, productsArr, isExpress, st
|
|
|
145
137
|
}
|
|
146
138
|
if (buyConditionFulfilledCounter) {
|
|
147
139
|
for (let prodCondition of getConditions) {
|
|
148
|
-
//
|
|
140
|
+
// Se utiliza solo el precio del producto (sin extraAmount) para calcular el descuento
|
|
149
141
|
const prodPrice = isExpress
|
|
150
142
|
? prodCondition.getProduct.expressPrice
|
|
151
143
|
: prodCondition.getProduct.price;
|
|
152
|
-
const extraAmountPerUnit = ((_a = prodCondition.getProduct) === null || _a === void 0 ? void 0 : _a.extraAmount) / ((_b = prodCondition.getProduct) === null || _b === void 0 ? void 0 : _b.qty) || 0 || 0;
|
|
153
144
|
const percentageDiscount = discountValue / 100;
|
|
154
145
|
const discountAmount = discountType === BuyAndGetConditionsTypes.FREE
|
|
155
|
-
? prodPrice
|
|
156
|
-
: +(percentageDiscount *
|
|
146
|
+
? prodPrice
|
|
147
|
+
: +(percentageDiscount * prodPrice).toFixed(2);
|
|
157
148
|
buyAndGetProds.push(Object.assign(Object.assign({}, prodCondition.getProduct), { qty: buyConditionFulfilledCounter * prodCondition.qty, quantity: buyConditionFulfilledCounter * prodCondition.qty, discountAmount: discountAmount, isBuyAndGetProduct: true }));
|
|
158
149
|
}
|
|
159
150
|
}
|
|
@@ -162,10 +153,9 @@ export const applyDiscountToProducts = (discountCode, productsArr, isExpress, st
|
|
|
162
153
|
const freeProductsSettinggs = discountCode.freeProductSetting[0];
|
|
163
154
|
const freeProduct = freeProductsSettinggs.product;
|
|
164
155
|
const prodPrice = isExpress ? freeProduct.expressPrice : freeProduct.price;
|
|
165
|
-
|
|
166
|
-
const discountAmount = prodPrice
|
|
167
|
-
buyAndGetProds.push(Object.assign(Object.assign({}, freeProduct), { qty: freeProductsSettinggs.qty, quantity: freeProductsSettinggs.qty, discountAmount: discountAmount, isBuyAndGetProduct: true, isFreeItem: true
|
|
168
|
-
}));
|
|
156
|
+
// Para free item, se asume que el producto es gratuito, es decir, se descuenta el precio del producto
|
|
157
|
+
const discountAmount = prodPrice;
|
|
158
|
+
buyAndGetProds.push(Object.assign(Object.assign({}, freeProduct), { qty: freeProductsSettinggs.qty, quantity: freeProductsSettinggs.qty, discountAmount: discountAmount, isBuyAndGetProduct: true, isFreeItem: true }));
|
|
169
159
|
}
|
|
170
160
|
return { newOrderProds, buyAndGetProds };
|
|
171
161
|
};
|