foodbot-cart-calculations 1.0.47 → 1.0.49

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/calculations.js CHANGED
@@ -8,10 +8,15 @@ function applyDistribution(body) {
8
8
  let mainCart = body
9
9
  let promotion = (body.promotion_applied && body.promotion_applied) ? body.promotion_applied : {};
10
10
  let deliveryCost = (body.delivery_cost && body.delivery_cost) ? body.delivery_cost : 0;
11
-
12
- if(body?.order_items?.delivery_discount)
11
+
12
+ if(body?.order_items?.delivery_discount) {
13
13
  body.order_items.delivery_discount = 0
14
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
+ }
15
20
 
16
21
  promoCalculation.setPackageDefaultDiscount(body.order_items).then(res => {
17
22
  promoCalculation.offerCalculation(res, promotion, deliveryCost).then(final => {
@@ -29,9 +34,9 @@ function applyDistribution(body) {
29
34
  body.promotion_applied = body.promotions_applied
30
35
  }
31
36
  mainCart.store_value = 0;
32
-
33
- pointsCalculation.getPointsDiscount(final, body.loyalty_points_details, body.user_detais).then(pointsCal => {
34
-
37
+ const originalDeliveryDiscount = final.delivery_discount;
38
+ const originalIsDeliveryDiscount = final.is_delivery_discount;
39
+ pointsCalculation.getPointsDiscount(final, body.loyalty_points_details, body.user_detais, body.delivery_cost, body.service_amount).then(pointsCal => {
35
40
  if (typeof (final.store_value) == "undefined" || isNaN(final.store_value))
36
41
  final.store_value = 0
37
42
  if (body.loyalty_points_details && parseInt(body.loyalty_points_details.points_redeemed) == 0) {
@@ -73,23 +78,36 @@ function applyDistribution(body) {
73
78
  mainCart.cash_expected = parseFloat(taxData.cartTotal) + parseFloat(taxData.tax_amount);
74
79
  }
75
80
  mainCart.order_items = taxData
76
-
81
+
77
82
  let delivery_cost = body.delivery_cost ? body.delivery_cost : 0;
83
+ let service_amount = body.service_amount ? body.service_amount : 0;
84
+
78
85
  // Adjust delivery cost based on delivery discount
79
- if (final.is_delivery_discount) {
80
- delivery_cost = Math.max(0, delivery_cost - final.delivery_discount);
81
- body.delivery_cost = delivery_cost; // Update body accordingly
86
+ if (originalIsDeliveryDiscount) {
87
+ delivery_cost = Math.max(0, delivery_cost - parseFloat(originalDeliveryDiscount));
88
+ body.delivery_cost = delivery_cost;
89
+ mainCart.order_items.delivery_discount = parseFloat(originalDeliveryDiscount);
90
+ mainCart.order_items.is_delivery_discount = true;
91
+ console.log("✅ Applied delivery discount:", { delivery_cost, body_delivery_cost: body.delivery_cost, order_items: mainCart.order_items });
82
92
  }
83
93
 
84
- let service_amount = body.service_amount?body.service_amount:0;
85
-
94
+ if (final.is_delivery_discount) {
95
+ delivery_cost = Math.max(0, delivery_cost - final.delivery_discount);
96
+ body.delivery_cost = delivery_cost;
97
+ }
98
+
99
+ // Adjust service amount based on service discount
100
+ if (final.is_service_discount) {
101
+ service_amount = Math.max(0, service_amount - final.service_discount);
102
+ body.service_amount = service_amount;
103
+ }
86
104
  //we took 2 value because in case of absolute we use tipValue
87
105
  let tipValue = body.tip_value?body.tip_value:0;
88
106
  let tipValueReq = body.tip_value?body.tip_value:0;
89
107
 
90
108
  if (body.tip_type && body.tip_type == 'percentage') {
91
- tipValue = (mainCart.final_amount * parseInt(tipValueReq)) / 100
92
- tipValue = parseFloat(tipValue).toFixed(2)
109
+ tipValue = (mainCart.final_amount * parseInt(tipValueReq)) / 100
110
+ tipValue = parseFloat(tipValue).toFixed(2)
93
111
  }
94
112
 
95
113
  mainCart.tip_amount = parseFloat(tipValue).toFixed(2);
@@ -105,10 +123,10 @@ function applyDistribution(body) {
105
123
 
106
124
  taxData.total_after_tax = parseFloat(taxData.total_after_tax) + parseFloat(tipValue);
107
125
  taxData.total_after_tax = parseFloat(taxData.total_after_tax).toFixed(2);
108
-
126
+
109
127
  mainCart.final_amount = parseFloat(mainCart.final_amount) + parseFloat(tipValue);
110
128
  mainCart.cash_expected = parseFloat(mainCart.cash_expected) + parseFloat(tipValue);
111
-
129
+
112
130
  taxData.final_amount = parseFloat(taxData.final_amount).toFixed(2);
113
131
  taxData.cash_expected = parseFloat(taxData.cash_expected).toFixed(2);
114
132
 
@@ -1,9 +1,12 @@
1
- function getPointsDiscount(cartObject, points, userDetails) {
1
+ function getPointsDiscount(cartObject, points, userDetails, deliveryCost = 0, serviceAmount = 0) {
2
2
  return new Promise(function (resolve, reject) {
3
3
  try {
4
4
  let itemsTotal = 0
5
5
  let carts = cartObject.item_details
6
+ let deliveryDiscount = 0;
7
+ let serviceDiscount = 0;
6
8
 
9
+ // reset old discounts
7
10
  carts.forEach(function (v) {
8
11
  delete v.points_discount_modifier;
9
12
  delete v.points_discount;
@@ -32,8 +35,11 @@ function getPointsDiscount(cartObject, points, userDetails) {
32
35
  });
33
36
  }
34
37
  });
38
+
35
39
  if (!points) {
36
- resolve(0);
40
+ cartObject.delivery_discount = 0;
41
+ cartObject.service_discount = 0;
42
+ resolve(cartObject);
37
43
  } else {
38
44
  let pointsAmount = 0;
39
45
  let count = 0;
@@ -71,113 +77,238 @@ function getPointsDiscount(cartObject, points, userDetails) {
71
77
  element.point_discount_status = true;
72
78
  }
73
79
  count++;
80
+ });
74
81
 
75
- if (count == carts.length) {
76
- let singlePriceDiscount = pointsAmount / itemsTotal;
77
- singlePriceDiscount = (itemsTotal && itemsTotal > 0)?parseFloat(singlePriceDiscount).toFixed(6):0;
82
+ // Apply points to service charge if enabled
83
+ if (points.enable_service_charge_usage === 1 && serviceAmount > 0 && storeAmount > 0) {
84
+ // Check if service discount is already applied through promotions
85
+ let hasServicePromo = cartObject.is_service_discount === true;
86
+
87
+ if (!hasServicePromo) {
88
+ cartObject.is_service_discount = true;
89
+ if (parseFloat(storeAmount) >= parseFloat(serviceAmount)) {
90
+ serviceDiscount = parseFloat(serviceAmount);
91
+ pointsAmount = parseFloat(pointsAmount) + parseFloat(serviceAmount);
92
+ storeAmount = parseFloat(storeAmount) - parseFloat(serviceAmount);
93
+ } else {
94
+ serviceDiscount = parseFloat(storeAmount);
95
+ pointsAmount = parseFloat(pointsAmount) + parseFloat(storeAmount);
96
+ storeAmount = 0;
97
+ }
98
+ serviceDiscount = parseFloat(serviceDiscount).toFixed(2);
99
+ cartObject.service_discount = serviceDiscount;
100
+ } else {
101
+ cartObject.service_discount = cartObject.service_discount || 0;
102
+ }
103
+ } else {
104
+ cartObject.service_discount = cartObject.service_discount || 0;
105
+ if (!cartObject.is_service_discount) {
106
+ cartObject.is_service_discount = false;
107
+ }
108
+ }
78
109
 
79
- let storeValue = 0
80
- let itemDiscount = 0;
81
- let itemTotalDicount = 0;
110
+ // Apply points to delivery if enabled and no delivery promotion is already applied
111
+ if (points.enable_delivery_points_usage === 1 && deliveryCost > 0 && storeAmount > 0) {
112
+ // Check if delivery discount is already applied through promotions
113
+ let hasDeliveryPromo = cartObject.is_delivery_discount === true;
82
114
 
83
- carts.forEach((item, index) => {
84
- item.points_discount = item.points_discount ? item.points_discount : 0;
85
- item.points_discount_modifier = item.points_discount_modifier ? item.points_discount_modifier : 0;
115
+ if (!hasDeliveryPromo) {
116
+ cartObject.is_delivery_discount = true;
117
+ if (parseFloat(storeAmount) >= parseFloat(deliveryCost)) {
118
+ deliveryDiscount = parseFloat(deliveryCost);
119
+ pointsAmount = parseFloat(pointsAmount) + parseFloat(deliveryCost);
120
+ storeAmount = parseFloat(storeAmount) - parseFloat(deliveryCost);
121
+ } else {
122
+ deliveryDiscount = parseFloat(storeAmount);
123
+ pointsAmount = parseFloat(pointsAmount) + parseFloat(storeAmount);
124
+ storeAmount = 0;
125
+ }
126
+ deliveryDiscount = parseFloat(deliveryDiscount).toFixed(2);
127
+ cartObject.delivery_discount = deliveryDiscount;
128
+ } else {
129
+ // If delivery promotion is already applied, preserve existing discount
130
+ cartObject.delivery_discount = cartObject.delivery_discount || 0;
131
+ }
132
+ } else {
133
+ cartObject.delivery_discount = cartObject.delivery_discount || 0;
134
+ if (!cartObject.is_delivery_discount) {
135
+ cartObject.is_delivery_discount = false;
136
+ }
137
+ }
86
138
 
87
- if (item.isPackage == 1) {
88
- if (item.point_discount_status) {
89
- let promoDiscount = (item.promotion_discount) ? item.promotion_discount : 0;
90
- itemDiscount = ((item.item_price * item.quantity) - promoDiscount) * singlePriceDiscount;
91
- itemDiscount = parseFloat(itemDiscount).toFixed(2);
92
- itemTotalDicount = parseFloat(itemDiscount) + parseFloat(itemTotalDicount);
139
+ if (count == carts.length) {
140
+ let singlePriceDiscount = pointsAmount / itemsTotal;
141
+ singlePriceDiscount = (itemsTotal && itemsTotal > 0)?parseFloat(singlePriceDiscount).toFixed(6):0;
93
142
 
94
- if (itemDiscount > 0)
95
- indexes.push(index);
143
+ let indexes = [];
144
+ let itemTotalDicount = 0;
96
145
 
97
- item.points_discount = itemDiscount;
98
- item.points_discount_modifier = 0;
146
+ carts.forEach((item, index) => {
147
+ item.points_discount = item.points_discount ? item.points_discount : 0;
148
+ item.points_discount_modifier = item.points_discount_modifier ? item.points_discount_modifier : 0;
99
149
 
100
- let packDis = 0;
150
+ // Replace the package items section (around line 120-170) with this corrected version:
101
151
 
102
- item.package_items.forEach((packageItem, packageItemIndex) => {
103
- let packageItemPromoDiscount = (packageItem.promotion_discount) ? packageItem.promotion_discount : 0;
104
- packageItem.points_discount_modifier = 0;
152
+ if (item.isPackage == 1) {
153
+ if (item.point_discount_status) {
154
+ let promoDiscount = (item.promotion_discount) ? item.promotion_discount : 0;
155
+ let itemDiscount = ((item.item_price * item.quantity) - promoDiscount) * singlePriceDiscount;
156
+ itemDiscount = parseFloat(itemDiscount).toFixed(2);
157
+
158
+ // Cap item discount to not exceed actual item price
159
+ let maxItemDiscount = (item.item_price * item.quantity) - promoDiscount;
160
+ if (parseFloat(itemDiscount) > maxItemDiscount) {
161
+ itemDiscount = parseFloat(maxItemDiscount).toFixed(2);
162
+ }
163
+
164
+ if (itemDiscount > 0)
165
+ indexes.push(index);
166
+
167
+ let totalPackageItemsDiscount = 0;
168
+ let totalPackageModifiersDiscount = 0;
169
+
170
+ item.package_items.forEach((packageItem, packageItemIndex) => {
171
+ let packageItemPromoDiscount = (packageItem.promotion_discount) ? packageItem.promotion_discount : 0;
172
+ packageItem.points_discount_modifier = 0;
173
+
174
+ // Calculate base package item price
175
+ let packageItemBasePrice = (packageItem.price * parseInt(item.quantity)) - parseFloat(packageItem.default_combo_discount || 0) - parseFloat(packageItemPromoDiscount);
176
+
177
+ // Ensure base price is not negative
178
+ if (packageItemBasePrice < 0) {
179
+ packageItemBasePrice = 0;
180
+ }
181
+
182
+ // Calculate discount for package item
183
+ let packageItemDiscount = (packageItemBasePrice * parseFloat(singlePriceDiscount));
184
+ packageItemDiscount = parseFloat(packageItemDiscount).toFixed(2);
185
+
186
+ // Cap package item discount to not exceed its actual price
187
+ if (parseFloat(packageItemDiscount) > packageItemBasePrice) {
188
+ packageItemDiscount = parseFloat(packageItemBasePrice).toFixed(2);
189
+ }
190
+
191
+ // Ensure discount is not negative
192
+ if (parseFloat(packageItemDiscount) < 0) {
193
+ packageItemDiscount = "0.00";
194
+ }
195
+
196
+ packageItem.points_discount = packageItemDiscount;
197
+ totalPackageItemsDiscount = parseFloat(totalPackageItemsDiscount) + parseFloat(packageItemDiscount);
198
+
199
+ // Handle modifiers
200
+ if (packageItem.modifiers && packageItem.modifiers.length > 0) {
201
+ packageItem.modifiers.forEach((modi, modiIndex) => {
202
+ let modiPromoDiscount = (modi.promotion_discount) ? modi.promotion_discount : 0;
203
+
204
+ // Calculate modifier base price
205
+ let modiBasePrice = (parseFloat(modi.modifier_item_price) * parseInt(modi.quantity)) * item.quantity - modiPromoDiscount;
206
+
207
+ // Ensure modifier base price is not negative
208
+ if (modiBasePrice < 0) {
209
+ modiBasePrice = 0;
210
+ }
211
+
212
+ let modiItemAmount = (modiBasePrice * parseFloat(singlePriceDiscount));
213
+ modiItemAmount = parseFloat(modiItemAmount).toFixed(2);
214
+
215
+ // Cap modifier discount
216
+ if (parseFloat(modiItemAmount) > modiBasePrice) {
217
+ modiItemAmount = parseFloat(modiBasePrice).toFixed(2);
218
+ }
219
+
220
+ // Ensure discount is not negative
221
+ if (parseFloat(modiItemAmount) < 0) {
222
+ modiItemAmount = "0.00";
223
+ }
224
+
225
+ modi.points_discount = modiItemAmount;
226
+ packageItem.points_discount_modifier = (parseFloat(packageItem.points_discount_modifier) + parseFloat(modi.points_discount)).toFixed(2);
227
+ totalPackageModifiersDiscount = parseFloat(totalPackageModifiersDiscount) + parseFloat(modiItemAmount);
228
+ });
229
+ }
230
+ });
231
+
232
+ // Set main package item discounts to reflect total of package items
233
+ item.points_discount = parseFloat(totalPackageItemsDiscount).toFixed(2);
234
+ item.points_discount_modifier = parseFloat(totalPackageModifiersDiscount).toFixed(2);
235
+
236
+ // Add to cart-level total
237
+ itemTotalDicount = parseFloat(itemTotalDicount) + parseFloat(totalPackageItemsDiscount) + parseFloat(totalPackageModifiersDiscount);
238
+ itemTotalDicount = parseFloat(itemTotalDicount).toFixed(2);
239
+ }
240
+ } else {
241
+ if (item.point_discount_status) {
242
+ let promoDiscount = (item.promotion_discount) ? item.promotion_discount : 0;
105
243
 
106
- packageItem.points_discount = ((((packageItem.price * parseInt(item.quantity)) - parseFloat((packageItem.default_combo_discount)) - parseFloat(packageItemPromoDiscount))) * parseFloat(singlePriceDiscount)).toFixed(2);
107
- packDis = (parseFloat(packDis) + parseFloat(packageItem.points_discount)).toFixed(2);
244
+ // --- Base item discount ---
245
+ let basePrice = parseFloat(item.item_price) * item.quantity;
246
+ let baseDiscount = ((basePrice - promoDiscount) * singlePriceDiscount);
247
+ baseDiscount = parseFloat(baseDiscount).toFixed(2);
108
248
 
109
- packageItem.modifiers.forEach((modi, modiIndex) => {
110
- let modiItemAmount = 0;
111
- let modiPromoDiscount = (modi.promotion_discount) ? modi.promotion_discount : 0;
112
- modiItemAmount = (((parseFloat(modi.modifier_item_price) * parseInt(modi.quantity)) * item.quantity) - modiPromoDiscount) * parseFloat(singlePriceDiscount);
113
- modiItemAmount = parseFloat(modiItemAmount).toFixed(2);
114
- itemTotalDicount = parseFloat(itemTotalDicount) + parseFloat(modiItemAmount);
115
- itemTotalDicount = parseFloat(itemTotalDicount).toFixed(2);
116
- modi.points_discount = modiItemAmount;
117
- packageItem.points_discount_modifier = (parseFloat(packageItem.points_discount_modifier) + parseFloat(modi.points_discount)).toFixed(2);
118
- });
119
- packageItem.points_discount_modifier = (parseFloat(packageItem.points_discount) + parseFloat(packageItem.points_discount_modifier)).toFixed(2);
120
- });
249
+ // cap base discount
250
+ if (parseFloat(baseDiscount) > basePrice) {
251
+ baseDiscount = basePrice.toFixed(2);
252
+ }
121
253
 
122
- if (itemDiscount != packDis && item.package_items) {
123
- if (packDis > itemDiscount) {
124
- let diff = (parseFloat(packDis) - parseFloat(itemDiscount)).toFixed(2);
125
- item.package_items[0].points_discount = (parseFloat(item.package_items[0].points_discount) - parseFloat(diff)).toFixed(2);
126
- } else {
127
- let diff = (parseFloat(itemDiscount) - parseFloat(packDis)).toFixed(2);
128
- item.package_items[0].points_discount = (parseFloat(item.package_items[0].points_discount) - parseFloat(diff)).toFixed(2);
129
- }
130
- }
254
+ if (parseFloat(baseDiscount) > 0) {
255
+ indexes.push(index);
131
256
  }
132
- } else {
133
- if (item.point_discount_status) {
134
- let promoDiscount = (item.promotion_discount) ? item.promotion_discount : 0;
135
- itemDiscount = ((item.item_price * item.quantity) - promoDiscount) * singlePriceDiscount;
136
- itemDiscount = parseFloat(itemDiscount).toFixed(2);
137
- itemTotalDicount = parseFloat(itemDiscount) + parseFloat(itemTotalDicount);
138
-
139
- if (itemDiscount > 0)
140
- indexes.push(index);
141
-
142
- item.points_discount = itemDiscount;
143
-
144
- item.item_modifiers.forEach((modi, modiIndex) => {
145
- let modiItemAmount = 0;
146
- let modiPromoDiscount = (modi.promotion_discount) ? modi.promotion_discount : 0;
147
- modiItemAmount = (((parseFloat(modi.modifier_item_price) * parseInt(modi.quantity)) * item.quantity) - modiPromoDiscount) * parseFloat(singlePriceDiscount);
148
- modiItemAmount = parseFloat(modiItemAmount).toFixed(2);
149
- itemTotalDicount = parseFloat(itemTotalDicount) + parseFloat(modiItemAmount);
150
- itemTotalDicount = parseFloat(itemTotalDicount).toFixed(2);
151
- modi.points_discount = modiItemAmount;
257
+ item.points_discount = baseDiscount;
258
+
259
+ // --- Modifiers ---
260
+ let modsTotalDiscount = 0;
261
+ if (item.item_modifiers && item.item_modifiers.length > 0) {
262
+ item.item_modifiers.forEach((modi) => {
263
+ let modiBase = parseFloat(modi.modifier_item_price) * modi.quantity * item.quantity;
264
+ let modiDiscount = (modiBase * parseFloat(singlePriceDiscount));
265
+ modiDiscount = parseFloat(modiDiscount).toFixed(2);
266
+
267
+ // cap modifier
268
+ if (parseFloat(modiDiscount) > modiBase) {
269
+ modiDiscount = modiBase.toFixed(2);
270
+ }
271
+
272
+ modi.points_discount = modiDiscount;
273
+ modsTotalDiscount = (parseFloat(modsTotalDiscount) + parseFloat(modiDiscount)).toFixed(2);
152
274
  });
275
+ }
276
+ item.points_discount_modifier = modsTotalDiscount;
153
277
 
154
- item.points_discount_modifier = itemTotalDicount;
278
+ // --- cap total item discount ---
279
+ let itemMax = parseFloat(item.item_price_with_modifier) * item.quantity;
280
+ let totalItemDiscount = parseFloat(item.points_discount) + parseFloat(item.points_discount_modifier);
281
+ if (totalItemDiscount > itemMax) {
282
+ let overflow = totalItemDiscount - itemMax;
283
+ if (parseFloat(item.points_discount_modifier) >= overflow) {
284
+ item.points_discount_modifier = (parseFloat(item.points_discount_modifier) - overflow).toFixed(2);
285
+ } else {
286
+ let leftover = overflow - parseFloat(item.points_discount_modifier);
287
+ item.points_discount_modifier = "0.00";
288
+ item.points_discount = (parseFloat(item.points_discount) - leftover).toFixed(2);
289
+ }
155
290
  }
156
- }
157
- });
158
291
 
159
- if ((Number(itemTotalDicount) < Number(pointsAmount) || Number(itemTotalDicount) > Number(pointsAmount)) && pointsAmount > 0 && itemTotalDicount > 0) {
160
- let difference = Number(pointsAmount) - Number(itemTotalDicount);
161
- difference = parseFloat(difference).toFixed(2);
162
- if (index > -1) {
163
- carts[indexes[0]].points_discount = (difference > 0) ? parseFloat(carts[indexes[0]].points_discount) + parseFloat(difference) : parseFloat(carts[indexes[0]].points_discount) - Math.abs(difference);
164
- carts[indexes[0]].points_discount = parseFloat(carts[indexes[0]].points_discount).toFixed(2);
165
- itemTotalDicount = (difference < 0) ? itemTotalDicount + difference : itemTotalDicount - Math.abs(difference);
166
- itemTotalDicount = parseFloat(itemTotalDicount).toFixed(2);
292
+ // add to cart-level total
293
+ itemTotalDicount = (parseFloat(itemTotalDicount) + parseFloat(item.points_discount) + parseFloat(item.points_discount_modifier)).toFixed(2);
167
294
  }
168
295
  }
296
+ });
169
297
 
170
- cartObject.item_details = carts
171
- cartObject.store_value = pointsAmount
172
- cartObject.point_discount_amount = pointsAmount
298
+ cartObject.item_details = carts
299
+ cartObject.store_value = pointsAmount
300
+ cartObject.point_discount_amount = pointsAmount
301
+ cartObject.delivery_discount = deliveryDiscount;
302
+ cartObject.service_discount = serviceDiscount;
173
303
 
174
- resolve(cartObject);
175
- }
176
- });
304
+ resolve(cartObject);
305
+ }
177
306
  } else {
178
307
  cartObject.item_details = carts
179
- cartObject.store_value = pointsAmount
180
- cartObject.point_discount_amount = pointsAmount
308
+ cartObject.store_value = 0
309
+ cartObject.point_discount_amount = 0
310
+ cartObject.delivery_discount = 0;
311
+ cartObject.service_discount = 0;
181
312
 
182
313
  resolve(cartObject);
183
314
  }
@@ -959,49 +959,65 @@ function getFixedPriceProductOffer(cartObject, offer) {
959
959
  var total = 0;
960
960
  var count = 0;
961
961
  var fixedPrice = offer.oo_offer_value;
962
-
963
- offer.offer_products.offer_discount_products = offer.offer_products.offer_discount_products.map(val =>
962
+ let appliedQty = 0; // track how many quantities discounted
963
+ let discountedItemIds = new Set(); // track which items already discounted
964
+ offer.offer_products.offer_discount_products = offer.offer_products.offer_discount_products.map(val =>
964
965
  val.toString().length > 10 ? val : Number(val)
965
966
  );
966
- offer.offer_products.package_items = offer.offer_products.package_items.map(x =>
967
+ offer.offer_products.package_items = offer.offer_products.package_items.map(x =>
967
968
  x.toString().length > 10 ? x : parseInt(x, 10)
968
969
  );
969
970
 
970
- var cartItem = carts;
971
+
971
972
 
973
+ // ✅ Sort by price (descending → highest first)
974
+ carts.sort((a, b) => (parseInt(b.item_price) > parseInt(a.item_price)) ? -1 : 1);
975
+ var cartItem = JSON.parse(JSON.stringify(carts))
976
+
972
977
  cartItem.forEach((element, index) => {
973
978
  var ItemIndex = carts.findIndex((x) => x.item_id == element.item_id && !x.remove);
974
979
  let itemId = element.item_id?.toString().length > 10 ? element.item_id : parseInt(element.item_id);
975
- if (offer.offer_products.offer_discount_products.includes(itemId) || offer.offer_products.package_items.includes(itemId)) {
980
+
981
+ if (
982
+ (offer.offer_products.offer_discount_products.includes(itemId) ||
983
+ offer.offer_products.package_items.includes(itemId))
984
+ && !discountedItemIds.has(itemId)
985
+ ) {
976
986
  var offerAmount = 0;
977
987
  var singleItemCost = element.item_price;
978
-
979
- if(singleItemCost >= fixedPrice){
980
- offerAmount = (singleItemCost * element.quantity) - (fixedPrice * element.quantity);
981
- }
982
-
983
- total = total + parseFloat(offerAmount);
984
-
985
- carts[ItemIndex].promotion_discount_modifier = parseFloat(offerAmount).toFixed(2);
986
- carts[ItemIndex].promotion_discount = parseFloat(offerAmount).toFixed(2);
987
- carts[ItemIndex].remove = true;
988
-
989
- if (offerAmount > 0) {
990
- carts[ItemIndex].redeem_promotion_id = offer.offer_id;
991
- } else {
992
- carts[ItemIndex].item_modifiers.map((res) => {
993
- res.promotion_discount = 0;
994
- res.redeem_promotion_id = 0;
995
- });
988
+
989
+ const maxQty = offer.max_quantity || 1;
990
+ let remainingQty = maxQty - appliedQty;
991
+ const qtyToDiscount = Math.min(element.quantity, remainingQty);
992
+
993
+ if (qtyToDiscount > 0 && singleItemCost >= fixedPrice) {
994
+ offerAmount = (singleItemCost * qtyToDiscount) - (fixedPrice * qtyToDiscount);
995
+ appliedQty += qtyToDiscount;
996
+
997
+ total += parseFloat(offerAmount);
998
+ carts[ItemIndex].promotion_discount_modifier = parseFloat(offerAmount).toFixed(2);
999
+ carts[ItemIndex].promotion_discount = parseFloat(offerAmount).toFixed(2);
1000
+ carts[ItemIndex].remove = true;
1001
+
1002
+ if (offerAmount > 0) {
1003
+ carts[ItemIndex].redeem_promotion_id = offer.offer_id;
1004
+ } else {
1005
+ carts[ItemIndex].item_modifiers.map((res) => {
1006
+ res.promotion_discount = 0;
1007
+ res.redeem_promotion_id = 0;
1008
+ });
1009
+ }
1010
+
1011
+ if (appliedQty == maxQty) {
1012
+ discountedItemIds.add(itemId);
1013
+ }
996
1014
  }
997
- count++;
998
- } else {
999
- count++;
1000
1015
  }
1001
-
1016
+
1017
+ count++;
1002
1018
  if (count == carts.length && carts) {
1003
- cartObject.item_details = carts
1004
- cartObject.discount = total
1019
+ cartObject.item_details = carts;
1020
+ cartObject.discount = total;
1005
1021
  resolve(cartObject);
1006
1022
  }
1007
1023
  });
package/index.js CHANGED
@@ -848,8 +848,9 @@ async function calculateTax(inputJSON) {
848
848
  // }
849
849
  // };
850
850
 
851
+ // let json = JSON.parse(fs.readFileSync('./sampleInput.json', 'utf8'));
851
852
  // calculateTax(json).then(res=>{
852
- // // console.log(JSON.stringify(res))
853
+ // console.log(JSON.stringify(res))
853
854
 
854
855
  // const jsonResponse = JSON.stringify(res, null, 2); // Format the JSON with indentation
855
856
  // const filePath = path.join(__dirname, 'response.json'); // File path in the same directory
@@ -865,5 +866,5 @@ async function calculateTax(inputJSON) {
865
866
  // }).catch(err=>{
866
867
  // console.log(err)
867
868
  // })
868
-
869
+
869
870
  module.exports = { calculateTax }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foodbot-cart-calculations",
3
- "version": "1.0.47",
3
+ "version": "1.0.49",
4
4
  "description": "Package for cart calculations in which it performs discount distribution and tax distribution on order",
5
5
  "main": "index.js",
6
6
  "scripts": {