diff --git a/addons/purchase/models/purchase_order_line.py b/addons/purchase/models/purchase_order_line.py index 820fac3707b..4cc9861b1fa 100644 --- a/addons/purchase/models/purchase_order_line.py +++ b/addons/purchase/models/purchase_order_line.py @@ -377,9 +377,12 @@ class PurchaseOrderLine(models.Model): # remove packaging if not match the product if line.product_packaging_id.product_id != line.product_id: line.product_packaging_id = False - # suggest biggest suitable packaging + # suggest biggest suitable packaging matching the PO's company if line.product_id and line.product_qty and line.product_uom: - line.product_packaging_id = line.product_id.packaging_ids.filtered('purchase')._find_suitable_product_packaging(line.product_qty, line.product_uom) or line.product_packaging_id + suggested_packaging = line.product_id.packaging_ids\ + .filtered(lambda p: p.purchase and (p.product_id.company_id <= p.company_id <= line.company_id))\ + ._find_suitable_product_packaging(line.product_qty, line.product_uom) + line.product_packaging_id = suggested_packaging or line.product_packaging_id @api.onchange('product_packaging_id') def _onchange_product_packaging_id(self): diff --git a/addons/purchase/tests/test_purchase.py b/addons/purchase/tests/test_purchase.py index bf2d777f35d..0f0d335317b 100644 --- a/addons/purchase/tests/test_purchase.py +++ b/addons/purchase/tests/test_purchase.py @@ -174,7 +174,7 @@ class TestPurchase(AccountTestInvoicingCommon): activity.note, ) - def test_onchange_packaging_00(self): + def test_compute_packaging_00(self): """Create a PO and use packaging. Check we suggested suitable packaging according to the product_qty. Also check product_qty or product_packaging are correctly calculated when one of them changed. @@ -219,7 +219,7 @@ class TestPurchase(AccountTestInvoicingCommon): self.assertEqual(po.order_line.product_qty, 12) # Do the same test but without form, to check the `product_packaging_id` and `product_packaging_qty` are set - # without manual call to onchanges + # without manual call to compute po = self.env['purchase.order'].create({ 'partner_id': self.partner_a.id, 'order_line': [ @@ -237,6 +237,43 @@ class TestPurchase(AccountTestInvoicingCommon): po.order_line.product_packaging_qty = 1.0 self.assertEqual(po.order_line.product_qty, 12) + def test_compute_packaging_01(self): + """Create a PO and use packaging in a multicompany environment. + Ensure any suggested packaging matches the PO's. + """ + company1 = self.company_data['company'] + company2 = self.company_data_2['company'] + generic_single_pack = self.env['product.packaging'].create({ + 'name': "single pack", + 'product_id': self.product_a.id, + 'qty': 1.0, + 'company_id': False, + }) + company2_pack_of_10 = self.env['product.packaging'].create({ + 'name': "pack of 10 by Company 2", + 'product_id': self.product_a.id, + 'qty': 10.0, + 'company_id': company2.id, + }) + + po1 = self.env['purchase.order'].with_company(company1).create({ + 'partner_id': self.partner_a.id, + 'order_line': [ + Command.create({'product_id': self.product_a.id, 'product_qty': 10.0}), + ] + }) + self.assertEqual(po1.order_line.product_packaging_id, generic_single_pack) + self.assertEqual(po1.order_line.product_packaging_qty, 10.0) + + # verify that with the right company, we can get the other packaging + po2 = self.env['purchase.order'].with_company(company2).create({ + 'partner_id': self.partner_a.id, + 'order_line': [ + Command.create({'product_id': self.product_a.id, 'product_qty': 10.0}), + ] + }) + self.assertEqual(po2.order_line.product_packaging_id, company2_pack_of_10) + self.assertEqual(po2.order_line.product_packaging_qty, 1.0) def test_with_different_uom(self): """ This test ensures that the unit price is correctly computed""" diff --git a/addons/sale/models/sale_order_line.py b/addons/sale/models/sale_order_line.py index 7aac1939474..9479eec2b59 100644 --- a/addons/sale/models/sale_order_line.py +++ b/addons/sale/models/sale_order_line.py @@ -642,10 +642,12 @@ class SaleOrderLine(models.Model): # remove packaging if not match the product if line.product_packaging_id.product_id != line.product_id: line.product_packaging_id = False - # Find biggest suitable packaging + # suggest biggest suitable packaging matching the SO's company if line.product_id and line.product_uom_qty and line.product_uom: - line.product_packaging_id = line.product_id.packaging_ids.filtered( - 'sales')._find_suitable_product_packaging(line.product_uom_qty, line.product_uom) or line.product_packaging_id + suggested_packaging = line.product_id.packaging_ids\ + .filtered(lambda p: p.sales and (p.product_id.company_id <= p.company_id <= line.company_id))\ + ._find_suitable_product_packaging(line.product_uom_qty, line.product_uom) + line.product_packaging_id = suggested_packaging or line.product_packaging_id @api.depends('product_packaging_id', 'product_uom', 'product_uom_qty') def _compute_product_packaging_qty(self): diff --git a/addons/sale/tests/test_sale_order.py b/addons/sale/tests/test_sale_order.py index d1e36401996..c488044b42a 100644 --- a/addons/sale/tests/test_sale_order.py +++ b/addons/sale/tests/test_sale_order.py @@ -172,7 +172,7 @@ class TestSaleOrder(SaleCommon): with self.assertRaises(UserError): self.sale_order.unlink() - def test_onchange_packaging_00(self): + def test_compute_packaging_00(self): """Create a SO and use packaging. Check we suggested suitable packaging according to the product_qty. Also check product_qty or product_packaging are correctly calculated when one of them changed. @@ -253,6 +253,44 @@ class TestSaleOrder(SaleCommon): self.assertEqual(so2.order_line.product_packaging_qty, 1) self.assertEqual(so2.order_line.product_packaging_id.id, packaging_pack_of_20.id) + def test_compute_packaging_01(self): + """Create a SO and use packaging in a multicompany environment. + Ensure any suggested packaging matches the SO's. + """ + company2 = self.env['res.company'].create([{'name': 'Company 2'}]) + generic_single_pack = self.env['product.packaging'].create({ + 'name': "single pack", + 'product_id': self.product.id, + 'qty': 1.0, + 'company_id': False, + }) + company2_pack_of_10 = self.env['product.packaging'].create({ + 'name': "pack of 10 by Company 2", + 'product_id': self.product.id, + 'qty': 10.0, + 'company_id': company2.id, + }) + + so1 = self.empty_order + so1_form = Form(so1) + with so1_form.order_line.new() as line: + line.product_id = self.product + line.product_uom_qty = 10.0 + so1_form.save() + self.assertEqual(so1.order_line.product_packaging_id, generic_single_pack) + self.assertEqual(so1.order_line.product_packaging_qty, 10.0) + + so2 = self.env['sale.order'].with_company(company2).create({ + 'partner_id': self.partner.id, + }) + so2_form = Form(so2) + with so2_form.order_line.new() as line: + line.product_id = self.product + line.product_uom_qty = 10.0 + so2_form.save() + self.assertEqual(so2.order_line.product_packaging_id, company2_pack_of_10) + self.assertEqual(so2.order_line.product_packaging_qty, 1.0) + def _create_sale_order(self): """Create dummy sale order (without lines)""" return self.env['sale.order'].with_context(