foodbot-cart-calculations 1.0.0-dev.1
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/README.MD +41 -0
- package/calculations.js +148 -0
- package/functions/pointsCalculation.js +307 -0
- package/functions/promotionCalculation.js +1133 -0
- package/functions/taxCalculation.js +690 -0
- package/index.js +869 -0
- package/package.json +11 -0
package/README.MD
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# foodbot-cart-calculations
|
|
2
|
+
|
|
3
|
+
foodbot-cart-calculations package for cart calculations in which it performs discount distribution or loyalty points distibution and tax calculations distribution on order items. There are some required keys which will be used for distibute discount , loyalty points and calculate tax. This package will return promise so we have to wait for this , so we have to use await for this.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install foodbot-cart-calculations
|
|
9
|
+
|
|
10
|
+
Usage
|
|
11
|
+
|
|
12
|
+
const cartPackage = require('foodbot-cart-calculations');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
let json = {
|
|
16
|
+
restaurant_id: 'xxxx',
|
|
17
|
+
branch_id: 'xxxx',
|
|
18
|
+
tax_type: 2,
|
|
19
|
+
/*
|
|
20
|
+
.
|
|
21
|
+
.
|
|
22
|
+
.
|
|
23
|
+
.
|
|
24
|
+
*/
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Request Example
|
|
28
|
+
|
|
29
|
+
let finalJson= await cartPackage.calculateTax(json);
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// Response Example
|
|
34
|
+
|
|
35
|
+
console.log("final json " , finaJson);
|
|
36
|
+
{
|
|
37
|
+
"status":"success",
|
|
38
|
+
"status_code":"200",
|
|
39
|
+
"message":"Tax calculated successfully",
|
|
40
|
+
"data":/* json*/
|
|
41
|
+
}
|
package/calculations.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
const taxCalculation = require('./functions/taxCalculation');
|
|
2
|
+
const promoCalculation = require('./functions/promotionCalculation');
|
|
3
|
+
const pointsCalculation = require('./functions/pointsCalculation');
|
|
4
|
+
function applyDistribution(body) {
|
|
5
|
+
return new Promise(async (resolve, reject) => {
|
|
6
|
+
try {
|
|
7
|
+
body.discount = 0
|
|
8
|
+
let mainCart = body
|
|
9
|
+
let promotion = (body.promotion_applied && body.promotion_applied) ? body.promotion_applied : {};
|
|
10
|
+
let deliveryCost = (body.delivery_cost && body.delivery_cost) ? body.delivery_cost : 0;
|
|
11
|
+
|
|
12
|
+
if(body?.order_items?.delivery_discount) {
|
|
13
|
+
body.order_items.delivery_discount = 0
|
|
14
|
+
body.order_items.is_delivery_discount = false
|
|
15
|
+
}
|
|
16
|
+
if (body?.order_items?.service_discount) {
|
|
17
|
+
body.order_items.service_discount = 0;
|
|
18
|
+
body.order_items.is_service_discount = false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
promoCalculation.setPackageDefaultDiscount(body.order_items).then(res => {
|
|
22
|
+
promoCalculation.offerCalculation(res, promotion, deliveryCost).then(final => {
|
|
23
|
+
|
|
24
|
+
let taxSettings = (body.tax_settings && body.tax_settings.length > 0) ? body.tax_settings : []
|
|
25
|
+
let taxType = (body.tax_type) ? body.tax_type : 1
|
|
26
|
+
let currency = (body.currency) ? body.currency : "$"
|
|
27
|
+
final.points_redeem_message = ""
|
|
28
|
+
|
|
29
|
+
if (body.promotions_applied && body.promotions_applied) {
|
|
30
|
+
body.promotions_applied.discount = final.discount
|
|
31
|
+
body.promotions_applied.promotion_id = body.promotions_applied.offer_id
|
|
32
|
+
body.promotions_applied.promotion_type = body.promotions_applied.offer_discount_type
|
|
33
|
+
body.promotions_applied.discount_type = body.promotions_applied.oo_offer_type
|
|
34
|
+
body.promotion_applied = body.promotions_applied
|
|
35
|
+
}
|
|
36
|
+
mainCart.store_value = 0;
|
|
37
|
+
|
|
38
|
+
pointsCalculation.getPointsDiscount(final, body.loyalty_points_details, body.user_detais, body.delivery_cost, body.service_amount).then(pointsCal => {
|
|
39
|
+
if (typeof (final.store_value) == "undefined" || isNaN(final.store_value))
|
|
40
|
+
final.store_value = 0
|
|
41
|
+
if (body.loyalty_points_details && parseInt(body.loyalty_points_details.points_redeemed) == 0) {
|
|
42
|
+
// let message = i18n.__("kiosk_point_message_not_redeemed")
|
|
43
|
+
// message = message.replace(/{totalAmount}/g, currency + "" +body.loyalty_points_details.store_value);
|
|
44
|
+
// message = message.replace(/{payPoints}/g, currency + "" + final.point_discount_amount);
|
|
45
|
+
// final.points_redeem_message = message
|
|
46
|
+
|
|
47
|
+
final.item_details.forEach(function (v) {
|
|
48
|
+
delete v.points_discount;
|
|
49
|
+
if (v.item_modifiers) {
|
|
50
|
+
v.item_modifiers.forEach((mod) => {
|
|
51
|
+
delete mod.points_discount;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
} else {
|
|
57
|
+
let totalStoreValue = (body.loyalty_points_details && body.loyalty_points_details.store_value) ? body.loyalty_points_details.store_value : 0
|
|
58
|
+
mainCart.store_value = final.store_value;
|
|
59
|
+
final.points_discount = final.store_value;
|
|
60
|
+
// let message = i18n.__("kiosk_point_message_redeemed").replace(/{totalAmount}/g, currency + "" + totalStoreValue).replace(/{paidPoints}/g, currency + "" + final.store_value)
|
|
61
|
+
// final.points_redeem_message = message
|
|
62
|
+
}
|
|
63
|
+
taxCalculation.calculateTax2(final, taxSettings, taxType).then(taxData => {
|
|
64
|
+
taxData.sub_total = taxData.cartTotal;
|
|
65
|
+
mainCart.final_amount = parseFloat(taxData.cartTotal);
|
|
66
|
+
mainCart.cash_expected = parseFloat(taxData.cartTotal) ;
|
|
67
|
+
taxData.total_after_tax = taxData.cartTotal
|
|
68
|
+
if (body.tax_type == 2) {
|
|
69
|
+
taxData.sub_total = taxData.cartTotal - taxData.tax_amount
|
|
70
|
+
taxData.sub_total = parseFloat(taxData.sub_total).toFixed(2)
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
taxData.total_after_tax = parseFloat(taxData.cartTotal) + parseFloat(taxData.tax_amount)
|
|
74
|
+
taxData.total_after_tax = parseFloat(taxData.total_after_tax).toFixed(2);
|
|
75
|
+
|
|
76
|
+
mainCart.final_amount = parseFloat(taxData.cartTotal) + parseFloat(taxData.tax_amount);
|
|
77
|
+
mainCart.cash_expected = parseFloat(taxData.cartTotal) + parseFloat(taxData.tax_amount);
|
|
78
|
+
}
|
|
79
|
+
mainCart.order_items = taxData
|
|
80
|
+
|
|
81
|
+
let delivery_cost = body.delivery_cost ? body.delivery_cost : 0;
|
|
82
|
+
let service_amount = body.service_amount ? body.service_amount : 0;
|
|
83
|
+
// Adjust delivery cost based on delivery discount
|
|
84
|
+
if (final.is_delivery_discount) {
|
|
85
|
+
delivery_cost = Math.max(0, delivery_cost - final.delivery_discount);
|
|
86
|
+
body.delivery_cost = delivery_cost; // Update body accordingly
|
|
87
|
+
}
|
|
88
|
+
// Adjust service amount based on service discount
|
|
89
|
+
if (final.is_service_discount) {
|
|
90
|
+
service_amount = Math.max(0, service_amount - final.service_discount);
|
|
91
|
+
body.service_amount = service_amount;
|
|
92
|
+
}
|
|
93
|
+
//we took 2 value because in case of absolute we use tipValue
|
|
94
|
+
let tipValue = body.tip_value?body.tip_value:0;
|
|
95
|
+
let tipValueReq = body.tip_value?body.tip_value:0;
|
|
96
|
+
|
|
97
|
+
if (body.tip_type && body.tip_type == 'percentage') {
|
|
98
|
+
tipValue = (mainCart.final_amount * parseInt(tipValueReq)) / 100
|
|
99
|
+
tipValue = parseFloat(tipValue).toFixed(2)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
mainCart.tip_amount = parseFloat(tipValue).toFixed(2);
|
|
103
|
+
|
|
104
|
+
mainCart.final_amount = parseFloat(mainCart.final_amount) + parseFloat(delivery_cost) + parseFloat(service_amount);
|
|
105
|
+
mainCart.cash_expected = parseFloat(mainCart.cash_expected) + parseFloat(delivery_cost) + parseFloat(service_amount);
|
|
106
|
+
|
|
107
|
+
//In a case when calculation of order done from pos.
|
|
108
|
+
if (body.tip_type && body.tip_type == 'percentage' && body.isPos && body.isPos == 1) {
|
|
109
|
+
tipValue = (mainCart.final_amount * parseInt(tipValueReq)) / 100;
|
|
110
|
+
tipValue = parseFloat(tipValue).toFixed(2)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
taxData.total_after_tax = parseFloat(taxData.total_after_tax) + parseFloat(tipValue);
|
|
114
|
+
taxData.total_after_tax = parseFloat(taxData.total_after_tax).toFixed(2);
|
|
115
|
+
|
|
116
|
+
mainCart.final_amount = parseFloat(mainCart.final_amount) + parseFloat(tipValue);
|
|
117
|
+
mainCart.cash_expected = parseFloat(mainCart.cash_expected) + parseFloat(tipValue);
|
|
118
|
+
|
|
119
|
+
taxData.final_amount = parseFloat(taxData.final_amount).toFixed(2);
|
|
120
|
+
taxData.cash_expected = parseFloat(taxData.cash_expected).toFixed(2);
|
|
121
|
+
|
|
122
|
+
mainCart.order_items.discount = parseFloat(mainCart.order_items.discount) ;
|
|
123
|
+
mainCart.order_items.discount = parseFloat(mainCart.order_items.discount).toFixed(2)
|
|
124
|
+
|
|
125
|
+
mainCart.discount = mainCart.order_items.discount;
|
|
126
|
+
mainCart.order_items.total=parseFloat(mainCart.order_items.total).toFixed(2)
|
|
127
|
+
|
|
128
|
+
resolve(mainCart);
|
|
129
|
+
}).catch(err => {
|
|
130
|
+
reject(err);
|
|
131
|
+
})
|
|
132
|
+
}).catch(err => {
|
|
133
|
+
reject(err);
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
}).catch(err => {
|
|
137
|
+
reject(err);
|
|
138
|
+
})
|
|
139
|
+
}).catch(err => {
|
|
140
|
+
reject(err);
|
|
141
|
+
})
|
|
142
|
+
} catch (error) {
|
|
143
|
+
reject(error)
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = { applyDistribution }
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
function getPointsDiscount(cartObject, points, userDetails, deliveryCost = 0, serviceAmount = 0) {
|
|
2
|
+
return new Promise(function (resolve, reject) {
|
|
3
|
+
try {
|
|
4
|
+
let itemsTotal = 0
|
|
5
|
+
let carts = cartObject.item_details
|
|
6
|
+
let deliveryDiscount = 0;
|
|
7
|
+
let serviceDiscount = 0;
|
|
8
|
+
|
|
9
|
+
// reset old discounts
|
|
10
|
+
carts.forEach(function (v) {
|
|
11
|
+
delete v.points_discount_modifier;
|
|
12
|
+
delete v.points_discount;
|
|
13
|
+
delete v.point_discount_status;
|
|
14
|
+
|
|
15
|
+
if (v.item_modifiers)
|
|
16
|
+
v.item_modifiers.forEach((mod) => {
|
|
17
|
+
delete mod.points_discount;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (v.isPackage == 1) {
|
|
21
|
+
v.package_items.forEach(function (p) {
|
|
22
|
+
delete p.points_discount_modifier;
|
|
23
|
+
delete p.points_discount;
|
|
24
|
+
delete p.point_discount_status;
|
|
25
|
+
|
|
26
|
+
if (p.item_modifiers)
|
|
27
|
+
p.item_modifiers.forEach((pMod) => {
|
|
28
|
+
delete pMod.points_discount;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (p.modifiers)
|
|
32
|
+
p.modifiers.forEach((pMod) => {
|
|
33
|
+
delete pMod.points_discount;
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (!points) {
|
|
40
|
+
cartObject.delivery_discount = 0;
|
|
41
|
+
cartObject.service_discount = 0;
|
|
42
|
+
resolve(cartObject);
|
|
43
|
+
} else {
|
|
44
|
+
let pointsAmount = 0;
|
|
45
|
+
let count = 0;
|
|
46
|
+
let storeAmount = points.store_value ?? (points.original_store_value ?? 0);
|
|
47
|
+
let indexes = [];
|
|
48
|
+
|
|
49
|
+
if (points.redeem_categories && points.redeem_categories != '') {
|
|
50
|
+
itemsTotal = 0;
|
|
51
|
+
|
|
52
|
+
carts.forEach((element, index) => {
|
|
53
|
+
var ItemIndex = points.redeem_categories.findIndex((x) => x.category_id == element.category_id);
|
|
54
|
+
if (ItemIndex >= 0 || (points.redeem_categories && points.redeem_categories[0] && points.redeem_categories[0].category_id.toLowerCase() == 'all') && !element.event) {
|
|
55
|
+
let priceToal = parseFloat(element.item_price_with_modifier) * element.quantity;
|
|
56
|
+
let itemPrice = parseFloat(priceToal).toFixed(2);
|
|
57
|
+
|
|
58
|
+
if (element.promotion_discount) {
|
|
59
|
+
itemPrice = parseFloat(priceToal) - parseFloat(element.promotion_discount_modifier);
|
|
60
|
+
itemPrice = parseFloat(itemPrice).toFixed(2);
|
|
61
|
+
itemsTotal = parseFloat(itemPrice) + parseFloat(itemsTotal);
|
|
62
|
+
} else {
|
|
63
|
+
itemsTotal = parseFloat(itemsTotal) + parseFloat(priceToal);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (parseFloat(storeAmount) > parseFloat(itemPrice)) {
|
|
67
|
+
pointsAmount = parseFloat(pointsAmount) + parseFloat(itemPrice);
|
|
68
|
+
pointsAmount = parseFloat(pointsAmount).toFixed(2);
|
|
69
|
+
storeAmount = parseFloat(storeAmount) - parseFloat(itemPrice);
|
|
70
|
+
} else {
|
|
71
|
+
let storeValue = JSON.parse(JSON.stringify(storeAmount));
|
|
72
|
+
storeAmount = parseFloat(storeAmount) - parseFloat(storeAmount);
|
|
73
|
+
pointsAmount = parseFloat(pointsAmount) + parseFloat(storeValue);
|
|
74
|
+
pointsAmount = parseFloat(pointsAmount).toFixed(2);
|
|
75
|
+
}
|
|
76
|
+
if (points && points.points_redeemed && userDetails)
|
|
77
|
+
element.point_discount_status = true;
|
|
78
|
+
}
|
|
79
|
+
count++;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Apply points to service charge if enabled
|
|
83
|
+
if (points.enable_service_charge_usage === 1 && serviceAmount > 0 && storeAmount > 0) {
|
|
84
|
+
cartObject.is_service_discount = true;
|
|
85
|
+
if (parseFloat(storeAmount) >= parseFloat(serviceAmount)) {
|
|
86
|
+
serviceDiscount = parseFloat(serviceAmount);
|
|
87
|
+
pointsAmount = parseFloat(pointsAmount) + parseFloat(serviceAmount);
|
|
88
|
+
storeAmount = parseFloat(storeAmount) - parseFloat(serviceAmount);
|
|
89
|
+
} else {
|
|
90
|
+
serviceDiscount = parseFloat(storeAmount);
|
|
91
|
+
pointsAmount = parseFloat(pointsAmount) + parseFloat(storeAmount);
|
|
92
|
+
storeAmount = 0;
|
|
93
|
+
}
|
|
94
|
+
serviceDiscount = parseFloat(serviceDiscount).toFixed(2);
|
|
95
|
+
cartObject.service_discount = serviceDiscount;
|
|
96
|
+
} else {
|
|
97
|
+
cartObject.service_discount = 0;
|
|
98
|
+
cartObject.is_service_discount = false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Apply points to delivery if enabled
|
|
102
|
+
if (points.enable_delivery_points_usage === 1 && deliveryCost > 0 && storeAmount > 0) {
|
|
103
|
+
cartObject.is_delivery_discount = true;
|
|
104
|
+
if (parseFloat(storeAmount) >= parseFloat(deliveryCost)) {
|
|
105
|
+
deliveryDiscount = parseFloat(deliveryCost);
|
|
106
|
+
pointsAmount = parseFloat(pointsAmount) + parseFloat(deliveryCost);
|
|
107
|
+
storeAmount = parseFloat(storeAmount) - parseFloat(deliveryCost);
|
|
108
|
+
} else {
|
|
109
|
+
deliveryDiscount = parseFloat(storeAmount);
|
|
110
|
+
pointsAmount = parseFloat(pointsAmount) + parseFloat(storeAmount);
|
|
111
|
+
storeAmount = 0;
|
|
112
|
+
}
|
|
113
|
+
deliveryDiscount = parseFloat(deliveryDiscount).toFixed(2);
|
|
114
|
+
cartObject.delivery_discount = deliveryDiscount;
|
|
115
|
+
} else {
|
|
116
|
+
cartObject.delivery_discount = 0;
|
|
117
|
+
cartObject.is_delivery_discount = false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (count == carts.length) {
|
|
121
|
+
let singlePriceDiscount = pointsAmount / itemsTotal;
|
|
122
|
+
singlePriceDiscount = (itemsTotal && itemsTotal > 0)?parseFloat(singlePriceDiscount).toFixed(6):0;
|
|
123
|
+
|
|
124
|
+
let indexes = [];
|
|
125
|
+
let itemTotalDicount = 0;
|
|
126
|
+
|
|
127
|
+
carts.forEach((item, index) => {
|
|
128
|
+
item.points_discount = item.points_discount ? item.points_discount : 0;
|
|
129
|
+
item.points_discount_modifier = item.points_discount_modifier ? item.points_discount_modifier : 0;
|
|
130
|
+
|
|
131
|
+
// Replace the package items section (around line 120-170) with this corrected version:
|
|
132
|
+
|
|
133
|
+
if (item.isPackage == 1) {
|
|
134
|
+
if (item.point_discount_status) {
|
|
135
|
+
let promoDiscount = (item.promotion_discount) ? item.promotion_discount : 0;
|
|
136
|
+
let itemDiscount = ((item.item_price * item.quantity) - promoDiscount) * singlePriceDiscount;
|
|
137
|
+
itemDiscount = parseFloat(itemDiscount).toFixed(2);
|
|
138
|
+
|
|
139
|
+
// Cap item discount to not exceed actual item price
|
|
140
|
+
let maxItemDiscount = (item.item_price * item.quantity) - promoDiscount;
|
|
141
|
+
if (parseFloat(itemDiscount) > maxItemDiscount) {
|
|
142
|
+
itemDiscount = parseFloat(maxItemDiscount).toFixed(2);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (itemDiscount > 0)
|
|
146
|
+
indexes.push(index);
|
|
147
|
+
|
|
148
|
+
let totalPackageItemsDiscount = 0;
|
|
149
|
+
let totalPackageModifiersDiscount = 0;
|
|
150
|
+
|
|
151
|
+
item.package_items.forEach((packageItem, packageItemIndex) => {
|
|
152
|
+
let packageItemPromoDiscount = (packageItem.promotion_discount) ? packageItem.promotion_discount : 0;
|
|
153
|
+
packageItem.points_discount_modifier = 0;
|
|
154
|
+
|
|
155
|
+
// Calculate base package item price
|
|
156
|
+
let packageItemBasePrice = (packageItem.price * parseInt(item.quantity)) - parseFloat(packageItem.default_combo_discount || 0) - parseFloat(packageItemPromoDiscount);
|
|
157
|
+
|
|
158
|
+
// Ensure base price is not negative
|
|
159
|
+
if (packageItemBasePrice < 0) {
|
|
160
|
+
packageItemBasePrice = 0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Calculate discount for package item
|
|
164
|
+
let packageItemDiscount = (packageItemBasePrice * parseFloat(singlePriceDiscount));
|
|
165
|
+
packageItemDiscount = parseFloat(packageItemDiscount).toFixed(2);
|
|
166
|
+
|
|
167
|
+
// Cap package item discount to not exceed its actual price
|
|
168
|
+
if (parseFloat(packageItemDiscount) > packageItemBasePrice) {
|
|
169
|
+
packageItemDiscount = parseFloat(packageItemBasePrice).toFixed(2);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Ensure discount is not negative
|
|
173
|
+
if (parseFloat(packageItemDiscount) < 0) {
|
|
174
|
+
packageItemDiscount = "0.00";
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
packageItem.points_discount = packageItemDiscount;
|
|
178
|
+
totalPackageItemsDiscount = parseFloat(totalPackageItemsDiscount) + parseFloat(packageItemDiscount);
|
|
179
|
+
|
|
180
|
+
// Handle modifiers
|
|
181
|
+
if (packageItem.modifiers && packageItem.modifiers.length > 0) {
|
|
182
|
+
packageItem.modifiers.forEach((modi, modiIndex) => {
|
|
183
|
+
let modiPromoDiscount = (modi.promotion_discount) ? modi.promotion_discount : 0;
|
|
184
|
+
|
|
185
|
+
// Calculate modifier base price
|
|
186
|
+
let modiBasePrice = (parseFloat(modi.modifier_item_price) * parseInt(modi.quantity)) * item.quantity - modiPromoDiscount;
|
|
187
|
+
|
|
188
|
+
// Ensure modifier base price is not negative
|
|
189
|
+
if (modiBasePrice < 0) {
|
|
190
|
+
modiBasePrice = 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let modiItemAmount = (modiBasePrice * parseFloat(singlePriceDiscount));
|
|
194
|
+
modiItemAmount = parseFloat(modiItemAmount).toFixed(2);
|
|
195
|
+
|
|
196
|
+
// Cap modifier discount
|
|
197
|
+
if (parseFloat(modiItemAmount) > modiBasePrice) {
|
|
198
|
+
modiItemAmount = parseFloat(modiBasePrice).toFixed(2);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Ensure discount is not negative
|
|
202
|
+
if (parseFloat(modiItemAmount) < 0) {
|
|
203
|
+
modiItemAmount = "0.00";
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
modi.points_discount = modiItemAmount;
|
|
207
|
+
packageItem.points_discount_modifier = (parseFloat(packageItem.points_discount_modifier) + parseFloat(modi.points_discount)).toFixed(2);
|
|
208
|
+
totalPackageModifiersDiscount = parseFloat(totalPackageModifiersDiscount) + parseFloat(modiItemAmount);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Set main package item discounts to reflect total of package items
|
|
214
|
+
item.points_discount = parseFloat(totalPackageItemsDiscount).toFixed(2);
|
|
215
|
+
item.points_discount_modifier = parseFloat(totalPackageModifiersDiscount).toFixed(2);
|
|
216
|
+
|
|
217
|
+
// Add to cart-level total
|
|
218
|
+
itemTotalDicount = parseFloat(itemTotalDicount) + parseFloat(totalPackageItemsDiscount) + parseFloat(totalPackageModifiersDiscount);
|
|
219
|
+
itemTotalDicount = parseFloat(itemTotalDicount).toFixed(2);
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
if (item.point_discount_status) {
|
|
223
|
+
let promoDiscount = (item.promotion_discount) ? item.promotion_discount : 0;
|
|
224
|
+
|
|
225
|
+
// --- Base item discount ---
|
|
226
|
+
let basePrice = parseFloat(item.item_price) * item.quantity;
|
|
227
|
+
let baseDiscount = ((basePrice - promoDiscount) * singlePriceDiscount);
|
|
228
|
+
baseDiscount = parseFloat(baseDiscount).toFixed(2);
|
|
229
|
+
|
|
230
|
+
// cap base discount
|
|
231
|
+
if (parseFloat(baseDiscount) > basePrice) {
|
|
232
|
+
baseDiscount = basePrice.toFixed(2);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (parseFloat(baseDiscount) > 0) {
|
|
236
|
+
indexes.push(index);
|
|
237
|
+
}
|
|
238
|
+
item.points_discount = baseDiscount;
|
|
239
|
+
|
|
240
|
+
// --- Modifiers ---
|
|
241
|
+
let modsTotalDiscount = 0;
|
|
242
|
+
if (item.item_modifiers && item.item_modifiers.length > 0) {
|
|
243
|
+
item.item_modifiers.forEach((modi) => {
|
|
244
|
+
let modiBase = parseFloat(modi.modifier_item_price) * modi.quantity * item.quantity;
|
|
245
|
+
let modiDiscount = (modiBase * parseFloat(singlePriceDiscount));
|
|
246
|
+
modiDiscount = parseFloat(modiDiscount).toFixed(2);
|
|
247
|
+
|
|
248
|
+
// cap modifier
|
|
249
|
+
if (parseFloat(modiDiscount) > modiBase) {
|
|
250
|
+
modiDiscount = modiBase.toFixed(2);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
modi.points_discount = modiDiscount;
|
|
254
|
+
modsTotalDiscount = (parseFloat(modsTotalDiscount) + parseFloat(modiDiscount)).toFixed(2);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
item.points_discount_modifier = modsTotalDiscount;
|
|
258
|
+
|
|
259
|
+
// --- cap total item discount ---
|
|
260
|
+
let itemMax = parseFloat(item.item_price_with_modifier) * item.quantity;
|
|
261
|
+
let totalItemDiscount = parseFloat(item.points_discount) + parseFloat(item.points_discount_modifier);
|
|
262
|
+
if (totalItemDiscount > itemMax) {
|
|
263
|
+
let overflow = totalItemDiscount - itemMax;
|
|
264
|
+
if (parseFloat(item.points_discount_modifier) >= overflow) {
|
|
265
|
+
item.points_discount_modifier = (parseFloat(item.points_discount_modifier) - overflow).toFixed(2);
|
|
266
|
+
} else {
|
|
267
|
+
let leftover = overflow - parseFloat(item.points_discount_modifier);
|
|
268
|
+
item.points_discount_modifier = "0.00";
|
|
269
|
+
item.points_discount = (parseFloat(item.points_discount) - leftover).toFixed(2);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// add to cart-level total
|
|
274
|
+
itemTotalDicount = (parseFloat(itemTotalDicount) + parseFloat(item.points_discount) + parseFloat(item.points_discount_modifier)).toFixed(2);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
cartObject.item_details = carts
|
|
280
|
+
cartObject.store_value = pointsAmount
|
|
281
|
+
cartObject.point_discount_amount = pointsAmount
|
|
282
|
+
cartObject.delivery_discount = deliveryDiscount;
|
|
283
|
+
cartObject.service_discount = serviceDiscount;
|
|
284
|
+
|
|
285
|
+
resolve(cartObject);
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
cartObject.item_details = carts
|
|
289
|
+
cartObject.store_value = 0
|
|
290
|
+
cartObject.point_discount_amount = 0
|
|
291
|
+
cartObject.delivery_discount = 0;
|
|
292
|
+
cartObject.service_discount = 0;
|
|
293
|
+
|
|
294
|
+
resolve(cartObject);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
} catch (error) {
|
|
298
|
+
reject(error);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
module.exports = {
|
|
306
|
+
getPointsDiscount
|
|
307
|
+
}
|