From 95c532a15b6bcfe7fdf7566231ed49f053dfb559 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 10 Feb 2025 13:21:51 +0000 Subject: [PATCH] [FIX] stock_picking_batch_validate_confirm: avoid propagating context with defaults When this module was installed along with `sale_elaboration`, elaboration sale order lines could be created automatically when confirming a picking. The `sale.order.line` model also has a `move_ids` field. Thus, those lines were created associated to the `stock.move` records found from within the batch. To make it even more fun, a batch can contain moves associated to unrelated sales. Thus, the elaboration lines were getting stock moves (which is wrong because they are services) and those moves came from unrelated sale orders. This mismatch was resulting in unexpected behaviors here and there. Now, we just produce defaults based on the standard context that all wizards get by default. This is safe and doesn't pollute any sub-calls. @moduon MT-9033 --- .../models/stock_picking_batch.py | 14 ++-------- .../tests/test_batch_confirm.py | 7 ++++- .../wizards/stock_picking_batch_confirm.py | 27 ++++++++++++++++--- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/stock_picking_batch_validate_confirm/models/stock_picking_batch.py b/stock_picking_batch_validate_confirm/models/stock_picking_batch.py index ed2f8bb9bd08..22d5ef836686 100644 --- a/stock_picking_batch_validate_confirm/models/stock_picking_batch.py +++ b/stock_picking_batch_validate_confirm/models/stock_picking_batch.py @@ -15,24 +15,14 @@ def action_done(self): [("state", "not in", ("cancel", "done"))] ) if pending_orig_moves: - return self._action_generate_batch_confirm_wizard(pending_orig_moves) + return self._action_generate_batch_confirm_wizard() return super().action_done() - def _action_generate_batch_confirm_wizard(self, pending_orig_moves): - view = self.env.ref( - "stock_picking_batch_validate_confirm.stock_picking_batch_confirm_view_form" - ) + def _action_generate_batch_confirm_wizard(self): return { "name": _("Batch Confirm"), "type": "ir.actions.act_window", "view_mode": "form", "res_model": "stock.picking.batch.confirm", - "views": [(view.id, "form")], - "view_id": view.id, "target": "new", - "context": dict( - self.env.context, - default_batch_id=self.id, - default_move_ids=[(6, 0, pending_orig_moves.ids)], - ), } diff --git a/stock_picking_batch_validate_confirm/tests/test_batch_confirm.py b/stock_picking_batch_validate_confirm/tests/test_batch_confirm.py index 0dcbb24c9ab4..51019091e0d7 100644 --- a/stock_picking_batch_validate_confirm/tests/test_batch_confirm.py +++ b/stock_picking_batch_validate_confirm/tests/test_batch_confirm.py @@ -77,6 +77,9 @@ def test_batch_confirm(self): ], } ) + batch = batch.with_context( + active_model=batch._name, active_id=batch.id, active_ids=batch.ids + ) self.env["stock.quant"]._update_available_quantity( self.productA, self.location, 10.0 ) @@ -88,7 +91,9 @@ def test_batch_confirm(self): res_dict = batch.action_done() self.assertEqual(res_dict.get("res_model"), "stock.picking.batch.confirm") wizard = Form( - self.env[res_dict["res_model"]].with_context(**res_dict["context"]) + self.env[res_dict["res_model"]].with_context( + batch.env.context, **res_dict.get("context", {}) + ) ).save() wizard.button_validate() self.assertEqual(batch.state, "done") diff --git a/stock_picking_batch_validate_confirm/wizards/stock_picking_batch_confirm.py b/stock_picking_batch_validate_confirm/wizards/stock_picking_batch_confirm.py index c8663c502b10..25c14c4c1b6e 100644 --- a/stock_picking_batch_validate_confirm/wizards/stock_picking_batch_confirm.py +++ b/stock_picking_batch_validate_confirm/wizards/stock_picking_batch_confirm.py @@ -1,15 +1,36 @@ # Copyright 2024 Moduon Team S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) -from odoo import fields, models +from odoo import api, fields, models class StockPickingBatchConfirm(models.TransientModel): _name = "stock.picking.batch.confirm" _description = "Wizard Batch Confirm" - batch_id = fields.Many2one("stock.picking.batch", string="Batch") - move_ids = fields.Many2many("stock.move", string="Moves") + batch_id = fields.Many2one( + "stock.picking.batch", + string="Batch", + required=True, + default=lambda self: self._default_batch_id(), + ) + move_ids = fields.Many2many( + "stock.move", string="Moves", compute="_compute_move_ids" + ) + + @api.model + def _default_batch_id(self): + """Get batch from context.""" + if self.env.context.get("active_model") == "stock.picking.batch": + return self.env.context.get("active_id") + + @api.depends("batch_id") + def _compute_move_ids(self): + """Get moves from batch.""" + for wizard in self: + wizard.move_ids = wizard.batch_id.move_ids.move_orig_ids.filtered_domain( + [("state", "not in", ("cancel", "done"))] + ) def button_validate(self): return self.batch_id.with_context(skip_batch_confirm=True).action_done()