From c1f97a367fc22eeaaaa2272a66483f272c6c332f Mon Sep 17 00:00:00 2001 From: Adrien Widart Date: Fri, 11 Jun 2021 07:28:51 +0000 Subject: [PATCH] [FIX] purchase: compute unit price with different uom On a product form, if the purchase UoM is different from the default UoM, this will lead to an error when creating a RfQ. To reproduce the error: (Need stock) 1. In Settings, enable "Unit of Measures" 2. Create a product P: - Cost: 100 - UoM: Units - Purchase UoM: Dozens 3. Create a RfQ: - Add P Error: The quantity is 1 and UoM is Dozens, however the unit price is $14400. The ratio has been applied twice. When setting the product, an onchange method computes the unit price. However, the computation is wrong: it first converts the product's standard price using the purchase UoM of the product. Then, it converts the result, this time using the UoM of the PO line. OPW-2519294 closes odoo/odoo#72139 X-original-commit: b37a13d7763e4a69695fdb1567dce5d0f69ff78a Signed-off-by: Arnold Moyaux Signed-off-by: Adrien Widart --- addons/purchase/models/purchase.py | 6 ++--- addons/purchase/tests/test_purchase.py | 33 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index a60509be3a5..01f68727194 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -1125,8 +1125,9 @@ class PurchaseOrderLine(models.Model): # If not seller, use the standard price. It needs a proper currency conversion. if not seller: + po_line_uom = self.product_uom or self.product_id.uom_po_id price_unit = self.env['account.tax']._fix_tax_included_price_company( - self.product_id.uom_id._compute_price(self.product_id.standard_price, self.product_id.uom_po_id), + self.product_id.uom_id._compute_price(self.product_id.standard_price, po_line_uom), self.product_id.supplier_taxes_id, self.taxes_id, self.company_id, @@ -1139,9 +1140,6 @@ class PurchaseOrderLine(models.Model): self.date_order or fields.Date.today(), ) - if self.product_uom: - price_unit = self.product_id.uom_id._compute_price(price_unit, self.product_uom) - self.price_unit = price_unit return diff --git a/addons/purchase/tests/test_purchase.py b/addons/purchase/tests/test_purchase.py index 0955326e9db..d27429abbd3 100644 --- a/addons/purchase/tests/test_purchase.py +++ b/addons/purchase/tests/test_purchase.py @@ -215,3 +215,36 @@ class TestPurchase(AccountTestInvoicingCommon): line.product_packaging_qty = 1.0 po_form.save() self.assertEqual(po.order_line.product_qty, 12) + + def test_with_different_uom(self): + """ This test ensures that the unit price is correctly computed""" + uom_units = self.env['ir.model.data'].xmlid_to_object('uom.product_uom_unit') + uom_dozens = self.env['ir.model.data'].xmlid_to_object('uom.product_uom_dozen') + uom_pairs = self.env['uom.uom'].create({ + 'name': 'Pairs', + 'category_id': uom_units.category_id.id, + 'uom_type': 'bigger', + 'factor_inv': 2, + 'rounding': 1, + }) + product_data = { + 'name': 'SuperProduct', + 'type': 'consu', + 'uom_id': uom_units.id, + 'uom_po_id': uom_pairs.id, + 'standard_price': 100 + } + product_01 = self.env['product.product'].create(product_data) + product_02 = self.env['product.product'].create(product_data) + + po_form = Form(self.env['purchase.order']) + po_form.partner_id = self.partner_a + with po_form.order_line.new() as po_line: + po_line.product_id = product_01 + with po_form.order_line.new() as po_line: + po_line.product_id = product_02 + po_line.product_uom = uom_dozens + po = po_form.save() + + self.assertEqual(po.order_line[0].price_unit, 200) + self.assertEqual(po.order_line[1].price_unit, 1200)