Skip to content

Commit

Permalink
[FIX] sale: avoid prices recomputation
Browse files Browse the repository at this point in the history
Steps to reproduce

* Create a new SO
* Add a new line with a storable product and 15.12 as quantity
* change the price to X
* Save and confirm
* Set a scheduled date (Other info tab)
* Save

-> The price of the SOL is recomputed.

Cause

Because of floating point issues, the value returned by the onchange for
the product_uom_qty field is 15.1200000....1, therefore being considered
in the client-side as having been changed by the onchange.
The value is then sent to the server on save, triggering a recomputation
of the SOL prices.

Until there is a clear solution in the framework, this commit drops
'unmodified values' for the product_uom_qty field, only if there is
one updated line in the write call.

opw-3670318

closes odoo#155392

X-original-commit: ef1b590
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
  • Loading branch information
Feyensv committed Feb 26, 2024
1 parent 50d8450 commit 789186a
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
13 changes: 12 additions & 1 deletion addons/sale/models/sale_order_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,18 @@ def write(self, values):
if 'product_uom_qty' in values:
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
self.filtered(
lambda r: r.state == 'sale' and float_compare(r.product_uom_qty, values['product_uom_qty'], precision_digits=precision) != 0)._update_line_quantity(values)
lambda r: r.state == 'sale' and float_compare(
r.product_uom_qty,
values['product_uom_qty'],
precision_digits=precision
) != 0
)._update_line_quantity(values)
if len(self) == 1 and float_compare(
self.product_uom_qty,
values['product_uom_qty'],
precision_digits=precision
) == 0:
values.pop('product_uom_qty')

# Prevent writing on a locked SO.
protected_fields = self._get_protected_fields()
Expand Down
48 changes: 44 additions & 4 deletions addons/sale_stock/tests/test_sale_stock.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from datetime import datetime, timedelta

from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
from odoo.addons.sale.tests.common import TestSaleCommon
from freezegun import freeze_time

from odoo import Command
from odoo.exceptions import UserError
from odoo.tests import Form, tagged
from odoo import Command

from odoo.addons.sale.tests.common import SaleCommon, TestSaleCommon
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import (
ValuationReconciliationTestCommon,
)


@tagged('post_install', '-at_install')
Expand Down Expand Up @@ -1750,3 +1755,38 @@ def test_delivery_on_negative_delivered_qty(self):
picking.button_validate()
self.assertEqual(sale_order.order_line.qty_delivered, -1.0)
self.assertEqual(sale_order.order_line.qty_to_invoice, -1.0)


class TestSaleOrder(SaleCommon):

@freeze_time('2017-01-07')
def test_order_onchange(self):
order = self.empty_order
storable_product = self.env['product.product'].create({
'name': 'Test Storable',
'type': 'product',
'list_price': 25.0,
})
order.order_line = [
Command.create({
'product_id': storable_product.id,
'product_uom_qty': 15.12,
'price_unit': 50.0,
}),
]
# retrieve the onchange spec for calling 'onchange'
order_form = Form(order)
# spec = order_form._view['onchange']
# onchange_vals = order_form._onchange_values()
# res = order.onchange(
# dict(
# onchange_vals,
# commitment_date='2017-01-12',
# ),
# 'commitment_date',
# spec
# )
# self.assertEqual(res['value']['order_line'][1][2]['product_uom_qty'], 15.12)
order_form.commitment_date = '2017-01-12'
order_form.save()
self.assertEqual(order.order_line.price_unit, 50.0)

0 comments on commit 789186a

Please sign in to comment.