From ca18e93958c38653214f5a361dd5544761fae0d9 Mon Sep 17 00:00:00 2001 From: "Pedram (pebr)" Date: Thu, 29 Feb 2024 14:09:18 +0000 Subject: [PATCH] [FIX] point_of_sale: correct computation of product total with discount Before this commit, if a product had a discount applied in two different orders, it could lead to incorrect calculations in the report For instance, if a product priced at 14.45 had a 30% discount applied, the discounted value would be 10.115, which rounds to 10.12. However, if there were two orders with the same discount, the report calculation would count the quantity of a product with the same discount and calculate the product total amount in one place. This would result in a discounted value of 10.115 * 2 = 20.23, while in the two different orders we had two 10.12 which sums to 20.24. With this commit, the calculation method has been changed. Now, the product amount total for each line is calculated first, and then the sum of these amounts is used to calculate the total for all of the orders. This change ensures accurate computation of the product total sum when discounts are applied across multiple orders. opw-3721376 closes odoo/odoo#156160 X-original-commit: bb71f77e117a8a07c1e161f583d136cd5c16a078 Signed-off-by: Joseph Caburnay (jcb) Signed-off-by: Pedram Bi Ria (pebr) --- .../models/report_sale_details.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/addons/point_of_sale/models/report_sale_details.py b/addons/point_of_sale/models/report_sale_details.py index c6b93242a38..6a065d07595 100644 --- a/addons/point_of_sale/models/report_sale_details.py +++ b/addons/point_of_sale/models/report_sale_details.py @@ -198,8 +198,9 @@ class ReportSaleDetails(models.AbstractModel): 'quantity': qty, 'price_unit': price_unit, 'discount': discount, - 'uom': product.uom_id.name - } for (product, price_unit, discount), qty in product_list.items()], key=lambda l: l['product_name']), + 'uom': product.uom_id.name, + 'total_paid': product_total + } for (product, price_unit, discount), (qty, product_total) in product_list.items()], key=lambda l: l['product_name']), } products.append(category_dictionnary) products = sorted(products, key=lambda l: str(l['name'])) @@ -214,8 +215,9 @@ class ReportSaleDetails(models.AbstractModel): 'quantity': qty, 'price_unit': price_unit, 'discount': discount, - 'uom': product.uom_id.name - } for (product, price_unit, discount), qty in product_list.items()], key=lambda l: l['product_name']), + 'uom': product.uom_id.name, + 'total_paid': product_total + } for (product, price_unit, discount), (qty, product_total) in product_list.items()], key=lambda l: l['product_name']), } refund_products.append(category_dictionnary) refund_products = sorted(refund_products, key=lambda l: str(l['name'])) @@ -287,8 +289,9 @@ class ReportSaleDetails(models.AbstractModel): keys1 = line.product_id.product_tmpl_id.pos_categ_ids.mapped("name") or [_('Not Categorized')] for key1 in keys1: products.setdefault(key1, {}) - products[key1].setdefault(key2, 0.0) - products[key1][key2] += line.qty + products[key1].setdefault(key2, [0.0, 0.0]) + products[key1][key2][0] += line.qty + products[key1][key2][1] += line.currency_id.round(line.price_unit * line.qty * (100 - line.discount) / 100.0) if line.tax_ids_after_fiscal_position: line_taxes = line.tax_ids_after_fiscal_position.sudo().compute_all(line.price_unit * (1-(line.discount or 0.0)/100.0), currency, line.qty, product=line.product_id, partner=line.order_id.partner_id or False) @@ -309,20 +312,18 @@ class ReportSaleDetails(models.AbstractModel): def _get_total_and_qty_per_category(self, categories): all_qty = 0 all_total = 0 - total = lambda product: (product['quantity'] * product['price_unit']) * (100 - product['discount']) / 100 for category_dict in categories: qty_cat = 0 total_cat = 0 for product in category_dict['products']: qty_cat += product['quantity'] - product['total_paid'] = total(product) total_cat += product['total_paid'] category_dict['total'] = total_cat category_dict['qty'] = qty_cat # IMPROVEMENT: It would be better if the `products` are grouped by pos.order.line.id. unique_products = list({tuple(sorted(product.items())): product for category in categories for product in category['products']}.values()) all_qty = sum([product['quantity'] for product in unique_products]) - all_total = sum([total(product) for product in unique_products]) + all_total = sum([product['total_paid'] for product in unique_products]) return categories, {'total': all_total, 'qty': all_qty}