Spaces:
Sleeping
Sleeping
| import math | |
| import copy | |
| from algorithm.product import Product | |
| def calculate_dish_price_with_taxes(_products, taxes, grand_total): | |
| payment_total = round(grand_total - taxes, 2) | |
| grand_total = round(payment_total, 2) + round(taxes, 2) | |
| _product_with_taxes = copy.deepcopy(_products) | |
| for _product in _product_with_taxes: | |
| _product.price = round(((_product.price / payment_total) * grand_total), 5) | |
| return _product_with_taxes, grand_total | |
| def round_up_two_decimals(_products_total): | |
| _product_with_taxes_rounded = copy.deepcopy(_products_total) | |
| for _product in _product_with_taxes_rounded: | |
| _product.price = math.ceil(_product.price * 100) / 100 | |
| return _product_with_taxes_rounded | |
| def first_algorithm(_products_total_rounded, receipt_subtotal): | |
| current_total = 0 | |
| for _product in _products_total_rounded: | |
| current_total += _product.price | |
| current_total = round(current_total, 2) | |
| difference = current_total - receipt_subtotal | |
| corrections = copy.deepcopy(_products_total_rounded) | |
| for _product in corrections: | |
| _product.price = round((_product.price / current_total) * difference, 2) | |
| for i in range(len(_products_total_rounded)): | |
| _products_total_rounded[i].price = round(_products_total_rounded[i].price - corrections[i].price, 2) | |
| _final_total = 0 | |
| for _product in _products_total_rounded: | |
| _final_total += _product.price | |
| return _products_total_rounded, _final_total | |
| def fractional_part_rest(value): | |
| fraction_str = f"{value:.10f}".split('.')[1] | |
| rest_of_digits = fraction_str[2:] | |
| return float(rest_of_digits) | |
| def second_algorithm(_products_total, receipt_total): | |
| _products_total_rounded = round_up_two_decimals(_products_total) | |
| current_total = 0 | |
| for _product in _products_total_rounded: | |
| current_total += _product.price | |
| if current_total == receipt_total: | |
| return _products_total_rounded, receipt_total | |
| difference = current_total - receipt_total | |
| difference = round(difference, 2) | |
| fractional_parts = copy.deepcopy(_products_total) | |
| for _product in fractional_parts: | |
| _product.price = fractional_part_rest(_product.price) - math.ceil(_product.price) | |
| fractional_parts = sorted(fractional_parts, key=lambda p: p.price, reverse=False) | |
| for i in range(len(fractional_parts)): | |
| if difference <= 0: | |
| break | |
| _products_total_rounded[i].price -= 0.01 | |
| difference -= 0.01 | |
| _final_total = 0 | |
| for _product in _products_total_rounded: | |
| _final_total += _product.price | |
| for _product in _products_total_rounded: | |
| _product.price = round(_product.price, 2) | |
| return _products_total_rounded, _final_total | |
| def clean_and_convert_to_float(price): | |
| if price == "": return 0.0 | |
| clean_price = ''.join(c for c in str(price) if c.isdigit() or c in ",.") | |
| return float(clean_price.replace(",", ".")) | |
| def calculate_tips_and_taxes(items_table, total_amount, tax, tips): | |
| products = [] | |
| if items_table[0][0] == "No items": | |
| return products, 0 | |
| if total_amount == "Not specified" or total_amount == "unknown" or total_amount is None: | |
| total_amount = "0.0" | |
| if tax == "Not specified" or tax == "unknown" or tax is None: | |
| tax = "0.0" | |
| if tips == "Not specified" or tips == "unknown" or tips is None: | |
| tips = "0.0" | |
| for item in items_table: | |
| price = item[5] | |
| if price == "Not specified" or price == "unknown": | |
| price = "0.0" | |
| item_value = clean_and_convert_to_float(price) if item[5] is not None else 0.0 | |
| products.append(Product(item[0], item_value)) | |
| sum_of_product_prices = 0 | |
| for _product in products: | |
| sum_of_product_prices += _product.price | |
| sum_of_product_prices = round(float(sum_of_product_prices), 2) | |
| total_amount = round(clean_and_convert_to_float(total_amount), 2) | |
| tips = round(clean_and_convert_to_float(tips), 2) | |
| tax = round(tips + round(clean_and_convert_to_float(tax), 2), 2) | |
| if round(float(total_amount), 2) != round(float(sum_of_product_prices) + float(tax), 2): | |
| return products, sum_of_product_prices | |
| products_total, subtotal = calculate_dish_price_with_taxes(products, taxes=float(tax), | |
| grand_total=float(total_amount)) | |
| final_prices, final_total = second_algorithm(products_total, subtotal) | |
| final_total = round(final_total, 2) | |
| return final_prices, final_total | |