washday-sdk 0.0.160 → 0.0.161
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 +28 -19
- 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 +39 -24
- package/src/utils/orders/calculateTotalTaxesOverPrice.ts +29 -36
- package/src/utils/orders/helpers.ts +128 -144
|
@@ -5,17 +5,24 @@ export const calculateTotalTaxesIncluded = (order, selectedCustomer, storeSettin
|
|
|
5
5
|
let discPercentageInteger = 0;
|
|
6
6
|
let productPercentageDiscount = 0;
|
|
7
7
|
let customerDiscount = 0;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
8
|
+
const qty = current.qty || 0;
|
|
9
|
+
// ExtraAmount se trata de forma separada: se conserva su valor bruto, pero se convierte a neto
|
|
10
|
+
const extraAmount = current.extraAmount; // valor bruto (con impuestos incluidos)
|
|
11
|
+
// Obtener la tasa de impuesto (por ejemplo, 16%) y convertirla a decimal:
|
|
12
|
+
const taxPercentage = getProductTaxesPercentage(current, storeSettings);
|
|
13
|
+
const taxPercentageInteger = taxPercentage / 100;
|
|
14
|
+
// Convertir extraAmount a valor neto
|
|
15
|
+
const extraAmountNet = extraAmount / (1 + taxPercentageInteger);
|
|
16
|
+
// Precio del producto (con impuestos incluidos) SIN incluir extraAmount
|
|
17
|
+
const productGrossPrice = order.express ? current.expressPrice : current.price;
|
|
18
|
+
// Extraer el precio neto del producto
|
|
19
|
+
const unitNetPrice = productGrossPrice / (1 + taxPercentageInteger);
|
|
20
|
+
// Calcular el porcentaje de descuento (aplicable solo sobre el precio neto del producto)
|
|
11
21
|
if (!order.discountCode) {
|
|
12
22
|
const discountsToApply = storeDiscounts.filter((discount) => discount.products.includes(current._id) && discount.isActive);
|
|
13
23
|
customerDiscount = ((_a = selectedCustomer === null || selectedCustomer === void 0 ? void 0 : selectedCustomer.customer) === null || _a === void 0 ? void 0 : _a.discount) || 0;
|
|
14
24
|
productPercentageDiscount = discountsToApply.reduce((prev, next) => {
|
|
15
|
-
|
|
16
|
-
return prev + next.value;
|
|
17
|
-
}
|
|
18
|
-
return prev;
|
|
25
|
+
return next.type === 'percentage' ? prev + next.value : prev;
|
|
19
26
|
}, 0);
|
|
20
27
|
discPercentageInteger = +((productPercentageDiscount + customerDiscount) / 100).toFixed(2);
|
|
21
28
|
discountsToApply.forEach((discount) => (appliedOrderDiscounts[discount._id] = discount));
|
|
@@ -37,22 +44,24 @@ export const calculateTotalTaxesIncluded = (order, selectedCustomer, storeSettin
|
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
|
-
|
|
41
|
-
const taxPercentageInteger = taxPercentage / 100;
|
|
42
|
-
const unitPrice = prodPrice / (1 + taxPercentageInteger);
|
|
47
|
+
// Aplicar el descuento sobre el precio neto del producto
|
|
43
48
|
const discountAmountPerUnit = discPercentageInteger
|
|
44
|
-
?
|
|
49
|
+
? unitNetPrice * discPercentageInteger
|
|
45
50
|
: (current.discountAmount || 0) / (1 + taxPercentageInteger);
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
+
const discountedUnitNetPrice = unitNetPrice - discountAmountPerUnit;
|
|
52
|
+
// Calcular los importes netos:
|
|
53
|
+
const productNetImportWithoutDiscount = (unitNetPrice * qty) + extraAmountNet;
|
|
54
|
+
const productNetImportWithDiscount = (discountedUnitNetPrice * qty) + extraAmountNet;
|
|
55
|
+
// Para obtener los valores brutos (con impuestos), se multiplica por (1 + taxPercentageInteger)
|
|
56
|
+
const productGrossImportWithoutDiscount = productNetImportWithoutDiscount * (1 + taxPercentageInteger);
|
|
57
|
+
// La parte de impuestos es la diferencia entre el bruto y el neto
|
|
58
|
+
const totalTaxesApplied = +((productGrossImportWithoutDiscount - productNetImportWithoutDiscount)).toFixed(2);
|
|
59
|
+
const lineDiscount = +(discountAmountPerUnit * qty).toFixed(2);
|
|
51
60
|
return {
|
|
52
61
|
product: current,
|
|
53
|
-
qty
|
|
54
|
-
productLineImportTotal:
|
|
55
|
-
productLineTotalWithDiscount:
|
|
62
|
+
qty,
|
|
63
|
+
productLineImportTotal: +productNetImportWithoutDiscount.toFixed(2), // valor neto sin descuento
|
|
64
|
+
productLineTotalWithDiscount: +productNetImportWithDiscount.toFixed(2), // valor neto con descuento
|
|
56
65
|
productLineTaxesTotal: totalTaxesApplied,
|
|
57
66
|
lineDiscountAmount: lineDiscount
|
|
58
67
|
};
|
|
@@ -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
|
};
|