From a0a0b81ec63ec7ccc61ba989ae003f2da2ff040b Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Thu, 5 Mar 2026 13:56:06 +0700 Subject: [PATCH] feat: Restrict lot selection dropdown to lots available in the source location for internal/transit pickings by adding a `stock.lot` search override and passing context variables from `stock.move.line` views. --- models/stock_location.py | 25 +++++++++++++++++++++++++ views/stock_move_line_views.xml | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/models/stock_location.py b/models/stock_location.py index c4a14f5..17e6c04 100644 --- a/models/stock_location.py +++ b/models/stock_location.py @@ -126,6 +126,31 @@ class StockLocation(models.Model): return super()._name_search(name=name, domain=domain, operator=operator, limit=limit, order=order) +class StockLot(models.Model): + _inherit = 'stock.lot' + + @api.model + def _search(self, domain, offset=0, limit=None, order=None, *args, **kwargs): + ctx = self.env.context + + # We only want to filter if the user is in a picking using lot_id directly (like Receive operations) + active_picking_id = ctx.get('active_picking_id') + loc_id = ctx.get('default_location_id') + + if active_picking_id and loc_id: + picking = self.env['stock.picking'].sudo().browse(active_picking_id) + loc = self.env['stock.location'].sudo().browse(loc_id) + + # If the source is an internal or transit location, restrict the dropdown to lots actually present there. + # If the source is a supplier, we do not filter (they could be receiving brand new lots). + if picking.exists() and loc.exists() and loc.usage != 'supplier': + domain = Domain.AND([domain, [ + ('quant_ids.location_id', 'child_of', loc.id), + ('quant_ids.quantity', '>', 0) + ]]) + + return super()._search(domain, offset=offset, limit=limit, order=order, *args, **kwargs) + _logger.info("="*80) _logger.info("STOCK_RESTRICT_SOURCE_LOCATION: stock_location.py module loaded successfully!") _logger.info("="*80) diff --git a/views/stock_move_line_views.xml b/views/stock_move_line_views.xml index 058d53b..c9938ed 100644 --- a/views/stock_move_line_views.xml +++ b/views/stock_move_line_views.xml @@ -38,6 +38,10 @@ {'default_location_id': location_id, 'default_product_id': product_id, 'search_view_ref': 'stock.quant_search_view', 'list_view_ref': 'stock.view_stock_quant_tree', 'form_view_ref': 'stock.view_stock_quant_form', 'readonly_form': True, 'show_src_package': 1, 'active_mo_id': context.get('active_mo_id'), 'default_picking_type_id': context.get('default_picking_type_id'), 'default_allowed_source_location_ids': allowed_source_location_ids} + + + {'default_product_id': product_id, 'active_picking_id': picking_id, 'default_location_id': location_id} + {'no_create': True} @@ -57,6 +61,9 @@ {'default_location_id': location_id, 'default_product_id': product_id, 'search_view_ref': 'stock.quant_search_view', 'list_view_ref': 'stock.view_stock_quant_tree', 'form_view_ref': 'stock.view_stock_quant_form', 'readonly_form': True, 'show_src_package': 1, 'active_mo_id': context.get('active_mo_id'), 'default_picking_type_id': context.get('default_picking_type_id'), 'default_allowed_source_location_ids': allowed_source_location_ids} + + {'default_product_id': parent.product_id, 'active_picking_id': picking_id, 'default_location_id': location_id} + {'no_create': True}