From 3e49f2bb577ef0e24b24ff83c9d84fa1454276ff Mon Sep 17 00:00:00 2001 From: "Andrea Grazioso (agr-odoo)" Date: Thu, 6 Apr 2023 08:34:59 +0000 Subject: [PATCH] [FIX] sale: sale order line quantity not rounded Create a Field Service Task Assing a customer, in Timesheet tab add a line with Hours Spent 00:20 Mark as Done Sale Order will be created with a sale order line Total of the line and Total of the order will not match This occurs because the sale order line has been created with an unrounded quantity of 0.333333 opw-3184468 closes odoo/odoo#118628 X-original-commit: ca72697042687e205fb288a97ec4717a97c89664 Related: odoo/enterprise#39799 Signed-off-by: Grazioso Andrea (agr) --- addons/sale/models/sale_order_line.py | 10 +++++----- addons/sale/tests/test_sale_prices.py | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/addons/sale/models/sale_order_line.py b/addons/sale/models/sale_order_line.py index d8c3e0dacc8..69ca835c773 100644 --- a/addons/sale/models/sale_order_line.py +++ b/addons/sale/models/sale_order_line.py @@ -941,16 +941,16 @@ class SaleOrderLine(models.Model): #=== CRUD METHODS ===# def _add_precomputed_values(self, vals_list): - """ In the specific case where the discount is provided in the create values + """ In case an editable precomputed field is provided in the create values without being rounded, we have to 'manually' round it otherwise it won't be, - because editable precomputed field values are kept 'as is'. + because those field values are kept 'as is'. This is a temporary fix until the problem is fixed in the ORM. """ - precision = self.env['decimal.precision'].precision_get('Discount') for vals in vals_list: - if vals.get('discount'): - vals['discount'] = float_round(vals['discount'], precision_digits=precision) + for fname in ('discount', 'product_uom_qty'): + if fname in vals: + vals[fname] = self._fields[fname].convert_to_cache(vals[fname], self) return super()._add_precomputed_values(vals_list) @api.model_create_multi diff --git a/addons/sale/tests/test_sale_prices.py b/addons/sale/tests/test_sale_prices.py index a5d11f8bb42..5e7b10e8b2b 100644 --- a/addons/sale/tests/test_sale_prices.py +++ b/addons/sale/tests/test_sale_prices.py @@ -7,7 +7,7 @@ from datetime import timedelta from odoo import fields from odoo.fields import Command from odoo.tests import Form, tagged -from odoo.tools import float_compare, mute_logger +from odoo.tools import float_compare, mute_logger, float_round from odoo.addons.sale.tests.common import SaleCommon @@ -978,3 +978,21 @@ class TestSalePrices(SaleCommon): # 136.36 price tax excluded with discount applied self.assertEqual(order.amount_undiscounted, 272.72) self.assertEqual(line.price_subtotal, 136.36) + + def test_product_quantity_rounding(self): + """When adding a sale order line, product quantity should be rounded + according to decimal precision""" + order = self.empty_order + + product_uom_qty = 0.333333 + order.order_line = [Command.create({ + 'product_id': self.product.id, + 'product_uom_qty': product_uom_qty, + 'price_unit': 75.0, + })] + order.action_confirm() + line = order.order_line + quantity_precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') + expected_price_subtotal = line.price_unit * float_round(product_uom_qty, precision_digits=quantity_precision) + self.assertAlmostEqual(line.price_subtotal, expected_price_subtotal) + self.assertEqual(order.amount_total, order.tax_totals.get('amount_total'))