From a7d3c839b8d1c684d7c3211397563f8115871cb1 Mon Sep 17 00:00:00 2001
From: Adrien Widart <awt@odoo.com>
Date: Thu, 19 Aug 2021 12:12:58 +0000
Subject: [PATCH] [FIX] stock, purchase_stock: add product to PO if orderpoint

Suppose a PO that has been generated thanks to reordering rule. When
changing the product of a line, if the user runs the scheduler, the old
product won't be added to the PO

To reproduce the error
1. Create a product P:
    - Product Type: Storable
    - Purchase: Add a vendor
    - Reordering rule:
        - Min = Max = 1
2. Run the scheduler
3. Update the generated PO:
    - Change the product of the line
4. Run the scheduler again
5. Open the PO

Error: The PO only contains one line (the one with the other product).
The PO should now contains a second line for P

OPW-2538707

closes odoo/odoo#75333

Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
---
 addons/purchase_stock/models/stock.py         | 11 +++-
 .../tests/test_reordering_rule.py             | 52 ++++++++++++++-----
 2 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/addons/purchase_stock/models/stock.py b/addons/purchase_stock/models/stock.py
index 7bed49daa207..651c37e68185 100644
--- a/addons/purchase_stock/models/stock.py
+++ b/addons/purchase_stock/models/stock.py
@@ -177,8 +177,15 @@ class Orderpoint(models.Model):
 
     def _quantity_in_progress(self):
         res = super(Orderpoint, self)._quantity_in_progress()
-        for poline in self.env['purchase.order.line'].search([('state','in',('draft','sent','to approve')),('orderpoint_id','in',self.ids)]):
-            res[poline.orderpoint_id.id] += poline.product_uom._compute_quantity(poline.product_qty, poline.orderpoint_id.product_uom, round=False)
+        groups = self.env['purchase.order.line'].read_group(
+            [('state', 'in', ('draft', 'sent', 'to approve')), ('orderpoint_id', 'in', self.ids), ('product_id', 'in', self.mapped('product_id').ids)],
+            ['product_id', 'product_qty', 'product_uom', 'orderpoint_id'],
+            ['orderpoint_id', 'product_id', 'product_uom'], lazy=False,
+        )
+        for group in groups:
+            orderpoint = self.browse(group['orderpoint_id'][0])
+            uom = self.env['uom.uom'].browse(group['product_uom'][0])
+            res[orderpoint.id] += uom._compute_quantity(group['product_qty'], orderpoint.product_uom, round=False) if orderpoint.product_id.id == group['product_id'][0] else 0.0
         return res
 
     def action_view_purchase(self):
diff --git a/addons/purchase_stock/tests/test_reordering_rule.py b/addons/purchase_stock/tests/test_reordering_rule.py
index 582a96b3cc73..447eb0534226 100644
--- a/addons/purchase_stock/tests/test_reordering_rule.py
+++ b/addons/purchase_stock/tests/test_reordering_rule.py
@@ -6,6 +6,20 @@ from odoo.tests import Form
 
 class TestReorderingRule(TransactionCase):
 
+    def setUp(self):
+        super(TestReorderingRule, self).setUp()
+        self.partner = self.env['res.partner'].create({
+            'name': 'Smith'
+        })
+
+        product_form = Form(self.env['product.product'])
+        product_form.name = 'Product A'
+        product_form.type = 'product'
+        with product_form.seller_ids.new() as seller:
+            seller.name = self.partner
+        product_form.route_ids.add(self.env.ref('purchase_stock.route_warehouse0_buy'))
+        self.product_01 = product_form.save()
+
     def test_reordering_rule(self):
         """
             - Receive products in 2 steps
@@ -15,19 +29,8 @@ class TestReorderingRule(TransactionCase):
         warehouse_1 = self.env['stock.warehouse'].search([('company_id', '=', self.env.user.id)], limit=1)
         warehouse_1.write({'reception_steps': 'two_steps'})
 
-        # Create a supplier
-        partner = self.env['res.partner'].create({
-            'name': 'Smith'
-        })
-
-        # create product and set the vendor
-        product_form = Form(self.env['product.product'])
-        product_form.name = 'Product A'
-        product_form.type = 'product'
-        with product_form.seller_ids.new() as seller:
-            seller.name = partner
-        product_form.route_ids.add(self.env.ref('purchase_stock.route_warehouse0_buy'))
-        product_01 = product_form.save()
+        partner = self.partner
+        product_01 = self.product_01
 
         # create reordering rule
         orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
@@ -59,3 +62,26 @@ class TestReorderingRule(TransactionCase):
 
         # On the po generated, the source document should be the name of the reordering rule
         self.assertEqual(order_point.name, purchase_order.origin, 'Source document on purchase order should be the name of the reordering rule.')
+
+    def test_change_pol_product(self):
+        """ In the PO generated by the scheduler, the user changes the product of the line. If the scheduler
+        is executed again, a new line should be added to the PO and correspond to the previous product """
+        product_form = Form(self.env['product.product'])
+        product_form.name = 'Product B'
+        product_form.type = 'product'
+        product_02 = product_form.save()
+
+        orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
+        orderpoint_form.product_id = self.product_01
+        orderpoint_form.product_min_qty = 10
+        orderpoint_form.product_max_qty = 50
+        order_point = orderpoint_form.save()
+
+        self.env['procurement.group'].run_scheduler()
+
+        purchase_order = self.env['purchase.order'].search([('partner_id', '=', self.partner.id)])
+        purchase_order.order_line.product_id = product_02
+
+        self.env['procurement.group'].run_scheduler()
+
+        self.assertEqual(purchase_order.order_line.mapped('product_id'), self.product_01 + product_02)
-- 
GitLab