Spaces:
Sleeping
Sleeping
File size: 2,657 Bytes
d904dd8 589c7cd d904dd8 589c7cd d904dd8 589c7cd d904dd8 589c7cd d904dd8 589c7cd d904dd8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | """
This module is used to calculate the split of the bill among people.
Author: Sarath Rajan S
Date: 26-01-2026
"""
def splitCalculator(receipt_data: dict, matched_items: list, final_amount_paid: float = None):
"""
Calculates the split of the bill.
1. Calculate Raw Individual Total
2. Ratio = Individual Total / Raw Receipt Total
3. Final Split = Ratio * Final Amount Paid
"""
# The denominator for ratios should be the sum of all individual item costs being split.
# This ensures that even if tax/service charge are not itemized,
# the total split will still add up to final_amount_paid proportionally.
subtotal = sum(float(item.get("price", 0)) * int(item.get("quantity", 1)) for item in matched_items)
# If final_amount_paid is not provided or zero, assume no discount/tax (subtotal is the total)
if final_amount_paid is None or final_amount_paid <= 0:
final_amount_paid = subtotal
person_data = {} # {name: {"items": [], "raw_sum": 0}}
# Avoid division by zero
if subtotal == 0:
return []
for item in matched_items:
iname = item.get("name", "Unknown")
iprice = float(item.get("price", 0))
iqty = int(item.get("quantity", 1))
item_total = iprice * iqty
people = item.get("people", [])
if not people:
people = ["Unassigned"]
share = item_total / len(people)
for person in people:
if person not in person_data:
person_data[person] = {"items": [], "raw_sum": 0}
# Since items are now exploded in the matching phase, iqty is usually 1 here
item_display = f"{iname} @ ${iprice}"
if iqty > 1:
item_display = f"{iname} (x{iqty}) @ ${iprice}"
person_data[person]["items"].append(item_display)
person_data[person]["raw_sum"] += share
table_data = []
for person, data in person_data.items():
# Step: Ratio of person raw total vs subtotal
ratio = data["raw_sum"] / subtotal if subtotal > 0 else 0
# Step: Apply final amount paid based on that ratio
final_cost = ratio * final_amount_paid
table_data.append({
"Person": person,
"Items Consumed": "\n".join(data["items"]), # Multi-line string for "nested" look
"Raw Share ($)": round(data["raw_sum"], 2),
"Ratio (%)": f"{round(ratio * 100, 1)}%",
"Final Split ($)": round(final_cost, 2)
})
return table_data
|