foodbot-cart-calculations 1.0.67 → 1.0.68

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.
@@ -829,172 +829,202 @@ async function calculateItemWiseSplit(cart, itemWiseItems) {
829
829
  async function calculateHalfSplit(cart, options = {}) {
830
830
  return new Promise(async (resolve, reject) => {
831
831
  try {
832
- // Safe getters / defaults
833
832
  const itemWiseItems = options.itemWiseItems || [];
834
- const allItems = options.allItems || (cart && cart.items) || [];
833
+ const allItems = options.allItems || cart.items || [];
835
834
  const splits = cart.split_payments || [];
836
835
 
837
836
  // Totals
838
- const totalAmount = parseFloat((cart.after_discount) ?? 0) || 0;
839
- const totalTax = parseFloat((cart.tax_amount) ?? 0) || 0;
837
+ const totalAmount = parseFloat(cart.after_discount ?? 0) || 0;
838
+ const totalTax = parseFloat(cart.tax_amount ?? 0) || 0;
840
839
 
841
- // Already paid sums
840
+ // Paid amounts
842
841
  const paidSplits = splits.filter((p) => p.paid_status);
843
- const paidAmount = paidSplits.reduce((sum, p) => sum + (parseFloat(p.amount || '0') || 0), 0);
844
- const paidTax = paidSplits.reduce((sum, p) => sum + (parseFloat(p.tax || '0') || 0), 0);
842
+ const paidAmount = paidSplits.reduce((sum, p) => sum + (parseFloat(p.amount || 0)), 0);
843
+ const paidTax = paidSplits.reduce((sum, p) => sum + (parseFloat(p.tax || 0)), 0);
845
844
 
846
845
  // Unpaid totals
847
846
  const unpaidTotalAmount = totalAmount - paidAmount;
848
847
  const unpaidTotalTax = totalTax - paidTax;
849
848
 
850
- // Unpaid split count
851
849
  const unpaidSplits = splits.filter((p) => !p.paid_status);
852
- const unpaidCount = unpaidSplits.length || 1; // avoid division by zero
850
+ const unpaidCount = unpaidSplits.length || 1;
853
851
 
854
- // If caller provided per-person values use them, otherwise compute equal split per unpaid person
855
- let halfSplitTaxPerPerson = (typeof options.halfSplitTaxPerPerson == 'number')
856
- ? options.halfSplitTaxPerPerson
857
- : unpaidTotalTax / unpaidCount;
852
+ // per-person distribution
853
+ let halfSplitTaxPerPerson =
854
+ typeof options.halfSplitTaxPerPerson == "number"
855
+ ? options.halfSplitTaxPerPerson
856
+ : unpaidTotalTax / unpaidCount;
858
857
 
859
- let halfSplitTotalPerPerson = (typeof options.halfSplitTotalPerPerson == 'number')
860
- ? options.halfSplitTotalPerPerson
861
- : unpaidTotalAmount / unpaidCount;
858
+ let halfSplitTotalPerPerson =
859
+ typeof options.halfSplitTotalPerPerson == "number"
860
+ ? options.halfSplitTotalPerPerson
861
+ : unpaidTotalAmount / unpaidCount;
862
862
 
863
- // Keep accumulators for rounding remainder
864
863
  let accumulatedAmount = 0;
865
864
  let accumulatedTax = 0;
866
865
  let unpaidIndex = 0;
867
866
 
868
- // For each split payment: assign items, compute item-level taxes & subtotal, then apply split rounding rules
869
867
  for (let p of splits) {
870
868
  if (!p.paid_status) {
871
- const isLastUnpaid = unpaidIndex == unpaidCount - 1;
869
+ const isLastUnpaid = unpaidIndex === unpaidCount - 1;
872
870
 
873
- // clone items so we don't mutate shared object
871
+ // Clone all items for this split user
874
872
  p.items = JSON.parse(JSON.stringify(allItems));
875
873
 
876
- // Recompute item-level tax/amount similar to your itemwise logic
874
+ // --------------------------------------------------------
875
+ // 🔥 ADDED LOGIC — Adjust quantities for the LAST UNPAID customer
876
+ // --------------------------------------------------------
877
+ if (isLastUnpaid) {
878
+ p.items.forEach((item) => {
879
+ const origin = itemWiseItems.find((it) => it._temp_id === item._temp_id);
880
+ if (!origin) return;
881
+
882
+ // 1. Compute how many qty PAID customers already took
883
+ let paidQty = 0;
884
+ splits.forEach((sp) => {
885
+ if (sp.paid_status && sp.items) {
886
+ const paidItem = sp.items.find((pi) => pi._temp_id === item._temp_id);
887
+ if (paidItem) paidQty += parseFloat(paidItem.quantity || 0);
888
+ }
889
+ });
890
+
891
+ // 2. Remaining qty for unpaid
892
+ const remainingQty = origin.quantity - paidQty;
893
+
894
+ // 3. Quantity each unpaid gets
895
+ const qtyPerUnpaid = parseFloat((remainingQty / unpaidCount).toFixed(6));
896
+
897
+ // 4. All other unpaid customers qty allocated
898
+ const allocatedToOthers = qtyPerUnpaid * (unpaidCount - 1);
899
+
900
+ // 5. FINAL remainder → assign to *last unpaid customer*
901
+ const finalQty = parseFloat((remainingQty - allocatedToOthers).toFixed(6));
902
+
903
+ item.quantity = finalQty;
904
+ });
905
+ }
906
+
907
+ // --------------------------------------------------------
908
+ // RECOMPUTE subtotal + taxes with UPDATED quantities
909
+ // --------------------------------------------------------
877
910
  let subtotal = 0;
878
911
  let tax = 0;
879
912
 
880
913
  for (let pi of p.items) {
881
- const item = itemWiseItems.find((i) => i._temp_id == pi._temp_id);
914
+ const item = itemWiseItems.find((i) => i._temp_id === pi._temp_id);
882
915
  if (!item) continue;
883
916
 
884
917
  const qty = Number(pi.quantity || 0);
885
918
  const price = Number(item.per_item_cost || 0);
886
919
  const itemTaxTotal = Number(item.total_tax_amount || 0);
887
920
 
888
- // quantity-wise tax array
889
921
  const quantityWiseTaxArray = (item.tax_array || []).map((taxObj) => {
890
- const unitBase = Number(taxObj.base_price || 0) / (Number(item.quantity) || 1);
891
- const unitTaxAmount = Number(taxObj.tax_amount || 0) / (Number(item.quantity) || 1);
922
+ const unitBase = Number(taxObj.base_price) / (item.quantity || 1);
923
+ const unitTax = Number(taxObj.tax_amount) / (item.quantity || 1);
924
+
892
925
  return {
893
926
  ...taxObj,
894
- base_price: (unitBase * qty).toFixed(6),
895
- tax_amount: (unitTaxAmount * qty).toFixed(6),
927
+ base_price: (unitBase * qty).toFixed(toFix),
928
+ tax_amount: (unitTax * qty).toFixed(toFix),
896
929
  };
897
930
  });
898
931
 
899
- // modifiers
932
+ // modifiers tax
900
933
  let modifierTaxArray = [];
901
934
  const mods = item.item_modifiers || item.modifiers || [];
902
- for (let m of mods) {
935
+
936
+ mods.forEach((m) => {
903
937
  const mq = Number(m.quantity || 0) || 1;
904
- const modTax = (m.tax_array || []).map((tx) => {
905
- const unitBase = Number(tx.base_price || 0) / ((Number(item.quantity) || 1) * mq);
906
- const unitTax = Number(tx.tax_amount || 0) / ((Number(item.quantity) || 1) * mq);
938
+
939
+ const modTax = m.tax_array.map((tx) => {
940
+ const unitBase = Number(tx.base_price) / (item.quantity * mq);
941
+ const unitTax = Number(tx.tax_amount) / (item.quantity * mq);
942
+
907
943
  return {
908
944
  ...tx,
909
- base_price: (unitBase * (mq * qty)).toFixed(6),
910
- tax_amount: (unitTax * (mq * qty)).toFixed(6),
945
+ base_price: (unitBase * (mq * qty)).toFixed(toFix),
946
+ tax_amount: (unitTax * (mq * qty)).toFixed(toFix),
911
947
  };
912
948
  });
949
+
913
950
  modifierTaxArray.push(...modTax);
914
- }
951
+ });
915
952
 
916
- // merge item-level taxes by tax_id
953
+ // Merge item taxes
917
954
  const mergedItemTaxMap = {};
918
- for (let t of [...quantityWiseTaxArray, ...modifierTaxArray]) {
955
+ [...quantityWiseTaxArray, ...modifierTaxArray].forEach((t) => {
919
956
  if (!mergedItemTaxMap[t.tax_id]) {
920
957
  mergedItemTaxMap[t.tax_id] = { ...t, base_price: 0, tax_amount: 0 };
921
958
  }
922
- mergedItemTaxMap[t.tax_id].base_price += Number(t.base_price || 0);
923
- mergedItemTaxMap[t.tax_id].tax_amount += Number(t.tax_amount || 0);
924
- }
959
+ mergedItemTaxMap[t.tax_id].base_price += Number(t.base_price);
960
+ mergedItemTaxMap[t.tax_id].tax_amount += Number(t.tax_amount);
961
+ });
925
962
 
926
963
  pi.tax_array = Object.values(mergedItemTaxMap).map((i) => ({
927
964
  ...i,
928
- base_price: Number(i.base_price).toFixed(6),
929
- tax_amount: Number(i.tax_amount).toFixed(6),
965
+ base_price: Number(i.base_price).toFixed(toFix),
966
+ tax_amount: Number(i.tax_amount).toFixed(toFix),
930
967
  }));
931
968
 
932
- // subtotal and tax contribution for this item in this split
933
969
  subtotal += price * qty;
934
- tax += (itemTaxTotal / (Number(item.quantity) || 1)) * qty;
935
- } // end items loop
970
+ tax += (itemTaxTotal / item.quantity) * qty;
971
+ }
936
972
 
937
- // Merge tax_array across items for this split
973
+ // Merge taxes for whole split
938
974
  const mergedTaxMap = {};
939
- for (let pi of p.items) {
975
+ p.items.forEach((pi) => {
940
976
  (pi.tax_array || []).forEach((t) => {
941
977
  if (!mergedTaxMap[t.tax_id]) {
942
978
  mergedTaxMap[t.tax_id] = { ...t, base_price: 0, tax_amount: 0 };
943
979
  }
944
- mergedTaxMap[t.tax_id].base_price += Number(t.base_price || 0);
945
- mergedTaxMap[t.tax_id].tax_amount += Number(t.tax_amount || 0);
980
+ mergedTaxMap[t.tax_id].base_price += Number(t.base_price);
981
+ mergedTaxMap[t.tax_id].tax_amount += Number(t.tax_amount);
946
982
  });
947
- }
983
+ });
948
984
 
949
985
  p.merge_tax_array = Object.values(mergedTaxMap).map((t) => ({
950
986
  ...t,
951
- base_price: Number(t.base_price).toFixed(6),
952
- tax_amount: Number(t.tax_amount).toFixed(6),
987
+ base_price: Number(t.base_price).toFixed(toFix),
988
+ tax_amount: Number(t.tax_amount).toFixed(toFix),
953
989
  }));
954
990
 
955
- // Apply equal split amounts with rounding adjustment:
991
+ // --------------------------------------------------------
992
+ // APPLY SPLIT AMOUNT + REMAINDER HANDLING
993
+ // --------------------------------------------------------
956
994
  if (isLastUnpaid) {
957
- // last unpaid gets the remainder (unpaid totals minus accumulated assigned amounts)
958
- // Use arithmetic with Number() and then format to 2 decimals for amount/tax
959
- const remainingTax = (unpaidTotalTax - accumulatedTax);
960
- const remainingAmount = (unpaidTotalAmount - accumulatedAmount);
961
-
962
- p.tax = Number(remainingTax).toFixed(toFix);
963
- p.amount = Number(remainingAmount).toFixed(toFix);
995
+ p.tax = Number(unpaidTotalTax - accumulatedTax).toFixed(toFix);
996
+ p.amount = Number(unpaidTotalAmount - accumulatedAmount).toFixed(toFix);
964
997
  p.due = p.amount;
965
998
  } else {
966
- // Non-last unpaid: assign precomputed per-person values (rounded to 2 decimals)
967
- const taxAmount = Number(Number(halfSplitTaxPerPerson).toFixed(toFix));
968
- const dueAmount = Number(Number(halfSplitTotalPerPerson).toFixed(toFix));
999
+ const taxAmount = Number(halfSplitTaxPerPerson).toFixed(toFix);
1000
+ const amountPer = Number(halfSplitTotalPerPerson).toFixed(toFix);
969
1001
 
970
- p.tax = taxAmount.toFixed(toFix);
971
- p.amount = dueAmount.toFixed(toFix);
972
- p.due = dueAmount.toFixed(toFix);
1002
+ p.tax = taxAmount;
1003
+ p.amount = amountPer;
1004
+ p.due = amountPer;
973
1005
 
974
- accumulatedTax += taxAmount;
975
- accumulatedAmount += dueAmount;
1006
+ accumulatedTax += Number(taxAmount);
1007
+ accumulatedAmount += Number(amountPer);
976
1008
  }
977
1009
 
978
1010
  unpaidIndex++;
979
- } // end if unpaid
980
- } // end for splits loop
981
-
982
- // Attach updated splits back to cart (if different structure)
983
- if (cart.split_payments) {
984
- cart.split_payments = splits;
1011
+ }
985
1012
  }
1013
+
1014
+ cart.split_payments = splits;
986
1015
  resolve(cart);
1016
+
987
1017
  } catch (err) {
988
- // bubble up so callers can handle
989
- console.error("❌ Split Payment Calculation Failed:", err);
1018
+ console.error("❌ HalfSplit Calculation Error:", err);
990
1019
  resolve({
991
- 'status': 'error',
992
- 'status_code': 500,
993
- 'message': 'Internal server error',
994
- 'error': error.stack,
1020
+ status: "error",
1021
+ status_code: 500,
1022
+ message: "Internal server error",
1023
+ error: err.stack,
995
1024
  });
996
1025
  }
997
1026
  });
998
1027
  }
999
1028
 
1029
+
1000
1030
  module.exports = { calculateTax2, calculateItemWiseSplit, calculateHalfSplit }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foodbot-cart-calculations",
3
- "version": "1.0.67",
3
+ "version": "1.0.68",
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": {