Spaces:
Sleeping
Sleeping
| """ | |
| 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 | |