From 063f7af8adcdb0c87b6e4de08bc81c6e6f4696eb Mon Sep 17 00:00:00 2001 From: "Nasreddin Boulif (bon)" <bon@odoo.com> Date: Thu, 25 Aug 2022 21:08:40 +0000 Subject: [PATCH] [FIX] purchase: Update price unit on new line even if confirmed RFQ Steps to reproduce: - Install purchase - Go to Settings and activate `Variant Grid Entry` - Create a new Requests for Quotation - Add a customer and add a product that has a variant min 2 variant - Wizard should ask for the variant - Select 1 variant by increasing quantity in the grid and confirm - Confirm order - Add again a product variant with the wizard Issue: Price unit is not set on the new line. Cause: In `_onchange_quantity` (triggered by the purchase_product_matrix module), we do not update price unit if order line is in state `purchase` or `done`. Solution: Replace condition to not perform `_onchange_quantity` if order line has an invoice line. opw-2956755 closes odoo/odoo#98960 Signed-off-by: Adrien Widart <awt@odoo.com> --- addons/purchase/models/purchase.py | 2 +- addons/purchase/tests/test_purchase.py | 77 ++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index 0fc49ac61322..569b532c5f6b 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -701,7 +701,7 @@ class PurchaseOrderLine(models.Model): @api.onchange('product_qty', 'product_uom') def _onchange_quantity(self): - if not self.product_id or self.state in ('purchase', 'done'): + if not self.product_id or self.invoice_lines: return params = {'order_id': self.order_id} seller = self.product_id._select_seller( diff --git a/addons/purchase/tests/test_purchase.py b/addons/purchase/tests/test_purchase.py index 3edfe742146a..068d99914fc0 100644 --- a/addons/purchase/tests/test_purchase.py +++ b/addons/purchase/tests/test_purchase.py @@ -3,6 +3,7 @@ from datetime import timedelta +from odoo.addons.account.tests.account_test_savepoint import AccountTestInvoicingCommon from odoo.tests.common import SavepointCase from odoo.tests import Form @@ -137,3 +138,79 @@ class TestPurchase(SavepointCase): pol.name = "New custom description" pol.product_qty += 1 self.assertEqual(pol.name, "New custom description") + +class TestPurchaseAccount(AccountTestInvoicingCommon): + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref=chart_template_ref) + + cls.product_consu = cls.env['product.product'].create({ + 'name': 'Product A', + 'type': 'consu', + }) + cls.product_consu2 = cls.env['product.product'].create({ + 'name': 'Product B', + 'type': 'consu', + }) + cls.vendor = cls.env['res.partner'].create({'name': 'vendor1'}) + cls.uom_unit = cls.env.ref('uom.product_uom_unit') + + def test_on_change_quantity_price_unit(self): + """ When a user changes the quantity of a product in a purchase order it + should only update the unit price if PO line has no invoice line. """ + + supplierinfo_vals = { + 'name': self.vendor.id, + 'price': 10.0, + 'min_qty': 1, + "product_id": self.product_consu.id, + "product_tmpl_id": self.product_consu.product_tmpl_id.id, + } + + supplierinfo = self.env["product.supplierinfo"].create(supplierinfo_vals) + po_form = Form(self.env['purchase.order']) + po_form.partner_id = self.vendor + with po_form.order_line.new() as po_line_form: + po_line_form.product_id = self.product_consu + po_line_form.product_qty = 1 + po = po_form.save() + po_line = po.order_line[0] + + self.assertEqual(10.0, po_line.price_unit, "Unit price should be set to 10.0 for 1 quantity") + + # Ensure price unit is updated when changing quantity on a un-confirmed PO + supplierinfo.write({'min_qty': 2, 'price': 20.0}) + po_line.write({'product_qty': 2}) + po_line._onchange_quantity() + self.assertEqual(20.0, po_line.price_unit, "Unit price should be set to 20.0 for 2 quantity") + + po.button_confirm() + + # Ensure price unit is updated when changing quantity on a confirmed PO + supplierinfo.write({'min_qty': 3, 'price': 30.0}) + po_line.write({'product_qty': 3}) + po_line._onchange_quantity() + self.assertEqual(30.0, po_line.price_unit, "Unit price should be set to 30.0 for 3 quantity") + + action = po.action_view_invoice() + invoice_form = Form(self.env['account.move'].with_context(action['context'])) + invoice_form.save() + + # Ensure price unit is NOT updated when changing quantity on PO confirmed and line linked to an invoice line + supplierinfo.write({'min_qty': 4, 'price': 40.0}) + po_line.write({'product_qty': 4}) + po_line._onchange_quantity() + self.assertEqual(30.0, po_line.price_unit, "Unit price should be set to 30.0 for 3 quantity") + + with po_form.order_line.new() as po_line_form: + po_line_form.product_id = self.product_consu + po_line_form.product_qty = 1 + po = po_form.save() + po_line = po.order_line[1] + + self.assertEqual(0.0, po_line.price_unit, "Unit price should be reset to 0 since the supplier supplies minimum of 4 quantities") + + # Ensure price unit is updated when changing quantity on PO confirmed and line NOT linked to an invoice line + po_line.write({'product_qty': 4}) + po_line._onchange_quantity() + self.assertEqual(40.0, po_line.price_unit, "Unit price should be set to 40.0 for 4 quantity") -- GitLab