[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) <jcb@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
This commit is contained in:
Pedram (pebr)
2024-03-04 13:26:31 +00:00
parent 5f0a5f41b4
commit ca18e93958
@@ -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}