From 82bf645341b1453fb2f5f52d7eb5e5eb1f6c176b Mon Sep 17 00:00:00 2001 From: Sarah Bellefroid Date: Wed, 20 Mar 2024 09:20:03 +0000 Subject: [PATCH] [FIX] purchase: compute order line name with supplierinfo Currently, when creating a purchase order, if the product has multiple vendor lines (with the vendor selected on the PO), the product description uses information from all the vendor lines; instead of using information from the vendor line that is used for the price. Steps to reproduce: ------------------- * Go to the **Purchase** App * Go to **Products** * Select any product * Select the **Purchase** tab * Add `Vendor Product Name` and `Vendor Product Code` in additional line fields * Add two vendor lines * Line 1: `Vendor`: Vendor1 `Vendor Product Name`: P1 `Vendor Product Code`: A `Price`: 1 * Line 2:
`Vendor`: Vendor 1 `Vendor Product Name`: P1 bis `Vendor Product Code`: B `Price`: 5 * Select **Orders** > **Request for quotation** * Create a new quotation * Select Vendor 1, add the product for which we just added the two vendor lines > **Observation**: The description of the product shows information from both vendor lines added. Why the fix: ------------ This behavior was introduced when `name_get` was removed to use `dispay_name` instead. * https://github.com/odoo/odoo/pull/122085/commits/a8b15c7ab5e2d850d0551a6eb4213bb20a30b210 When adding a product to the purchase order, the onchange on `product_id` is called. The onchange calls the function `_product_id_change`, which itself calls `_get_product_purchase_description`. https://github.com/odoo/odoo/blob/7e9b9494a8d6c4bb8b3800cc0e25fcd3596db75d/addons/purchase/models/purchase.py#L1224 https://github.com/odoo/odoo/blob/7e9b9494a8d6c4bb8b3800cc0e25fcd3596db75d/addons/purchase/models/purchase.py#L1401-L1407 The line `name = product_lang.display_name` calls the function `_compute_display_name`. * We do have a parnter_id in the context as we have selected a vendor on the purchase order. https://github.com/odoo/odoo/blob/7e9b9494a8d6c4bb8b3800cc0e25fcd3596db75d/addons/product/models/product_product.py#L434 * We don't have a supplierinfo in the context yet but we have multiple supplierinfo with the same partner_id. https://github.com/odoo/odoo/blob/7e9b9494a8d6c4bb8b3800cc0e25fcd3596db75d/addons/product/models/product_product.py#L466-L467 Here we thus have 2 sellers. * Ultimately, the display name joins the different display names computer for each seller. https://github.com/odoo/odoo/blob/7e9b9494a8d6c4bb8b3800cc0e25fcd3596db75d/addons/product/models/product_product.py#L473-L483 Coming back to the line `self.name = self._get_product_purchase_description(product_lang)`, we now have the name of the purchase order line set as the concatenation of display names from the supplierinfo, i.e `'[A] P1, [B] P1 bis'`. Once the onchange is called, the function `_compute_price_unit_and_date_planned_and_name` is being called. https://github.com/odoo/odoo/blob/7e9b9494a8d6c4bb8b3800cc0e25fcd3596db75d/addons/purchase/models/purchase.py#L1295 In the current state, we do not meet the if condition. Indeed, the line has a name (`'[A] P1, [B] P1 bis'`) but it isn't in the default_names (`['[A] P1', '[B] P1 bis']`). It somehow corresponds to a setting where the name of the purchase order line was setup by the user. With this current fix, the call to `_product_id_change` will set the name of the line with the product information from the company; and not the partner. We also need to add this name to the `default_names` in `_compute_price_unit_and_date_planned_and_name` so that the description get recomputed with regards to the seller, if any. opw-3802182 closes odoo/odoo#160778 X-original-commit: 6974f5303badbc5f5db104270f9492c12a52f220 Signed-off-by: Arnold Moyaux (arm) Signed-off-by: Sarah Bellefroid (sbel) --- addons/purchase/models/purchase_order_line.py | 4 +- addons/purchase/tests/test_purchase.py | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/addons/purchase/models/purchase_order_line.py b/addons/purchase/models/purchase_order_line.py index 00a7ee26380..77d2dd85dfb 100644 --- a/addons/purchase/models/purchase_order_line.py +++ b/addons/purchase/models/purchase_order_line.py @@ -287,7 +287,7 @@ class PurchaseOrderLine(models.Model): self.product_uom = self.product_id.uom_po_id or self.product_id.uom_id product_lang = self.product_id.with_context( lang=get_lang(self.env, self.partner_id.lang).code, - partner_id=self.partner_id.id, + partner_id=None, company_id=self.company_id.id, ) self.name = self._get_product_purchase_description(product_lang) @@ -364,6 +364,8 @@ class PurchaseOrderLine(models.Model): # record product names to avoid resetting custom descriptions default_names = [] vendors = line.product_id._prepare_sellers({}) + product_ctx = {'seller_id': None, 'partner_id': None, 'lang': get_lang(line.env, line.partner_id.lang).code} + default_names.append(line._get_product_purchase_description(line.product_id.with_context(product_ctx))) for vendor in vendors: product_ctx = {'seller_id': vendor.id, 'lang': get_lang(line.env, line.partner_id.lang).code} default_names.append(line._get_product_purchase_description(line.product_id.with_context(product_ctx))) diff --git a/addons/purchase/tests/test_purchase.py b/addons/purchase/tests/test_purchase.py index 563f7967866..572338918d5 100644 --- a/addons/purchase/tests/test_purchase.py +++ b/addons/purchase/tests/test_purchase.py @@ -572,3 +572,48 @@ class TestPurchase(AccountTestInvoicingCommon): self.assertEqual(po1.order_line[0].price_unit, 100) self.assertEqual(po1.order_line[0].discount, 30) + + def test_orderline_supplierinfo_description(self): + supplierinfo_vals = { + 'partner_id': self.partner_a.id, + 'min_qty': 1, + 'product_id': self.product_a.id, + 'product_tmpl_id': self.product_a.product_tmpl_id.id, + } + + self.env["product.supplierinfo"].create([ + { + **supplierinfo_vals, + 'price': 10, + 'product_name': 'Name 1', + 'product_code': 'Code 1', + }, + { + **supplierinfo_vals, + 'price': 20, + 'product_name': 'Name 2', + 'product_code': 'Code 2', + }, + { + 'partner_id': self.partner_a.id, + 'min_qty': 1, + 'product_id': self.product_b.id, + 'product_tmpl_id': self.product_b.product_tmpl_id.id, + 'price': 5, + 'product_name': 'Name 3', + 'product_code': 'Code 3', + } + ]) + + po_form = Form(self.env['purchase.order']) + po_form.partner_id = self.partner_a + with po_form.order_line.new() as line: + line.product_id = self.product_a + line.product_qty = 1 + po = po_form.save() + self.assertEqual(po.order_line.name, '[Code 1] Name 1') + + with po_form.order_line.edit(0) as line: + line.product_id = self.product_b + po = po_form.save() + self.assertEqual(po.order_line.name, '[Code 3] Name 3')