diff --git a/models/stock_location.py b/models/stock_location.py index 3543a44..a72c793 100644 --- a/models/stock_location.py +++ b/models/stock_location.py @@ -16,10 +16,9 @@ class StockLocation(models.Model): # 1. HIGHEST PRIORITY: Direct Manufacturing Order Database Lookup # This bypasses incomplete UI data by querying the MO directly via context IDs. mo_id = (ctx.get('active_mo_id') or - ctx.get('default_mo_id') or ctx.get('default_production_id') or - ctx.get('mo_id') or - ctx.get('production_id')) + ctx.get('production_id') or + ctx.get('active_id') if ctx.get('active_model') == 'mrp.production' else None) if mo_id: # sudo() ensures we can read the MO and its allowed locations regardless of field access @@ -83,23 +82,26 @@ class StockQuant(models.Model): @api.model def web_search_read(self, domain, specification, offset=0, limit=None, order=None, count_limit=None): """ - UI Override with DOMAIN STRIPPING to prevent Odoo's native JS from blocking us. + UI Override with ROBUST DOMAIN STRIPPING to fix RPC_ERROR/ValueError. """ ctx = self.env.context if not ctx.get('skip_location_restriction') and ctx.get('uid'): allowed_ids = self.env['stock.location']._get_allowed_locations() if allowed_ids: - # STRIP any existing native location_id filters from the domain. - # Odoo's JS often adds its own ["location_id", "child_of", single_id]. - # By stripping them, we ensure our multi-location list takes precedence. - stripped_domain = [] + # STRIP both native location_id filters AND their orphaned operators. + # The safest way is to extract only the non-location tuples (leaves). + # expression.AND(list_of_tuples) reconstruction a perfectly valid + # Polish notation with implicit 'AND' between our leaves. + clean_leaves = [] for leaf in domain: - if isinstance(leaf, (list, tuple)) and len(leaf) == 3 and leaf[0] == 'location_id': - continue - stripped_domain.append(leaf) + if isinstance(leaf, (list, tuple)): + if len(leaf) == 3 and leaf[0] == 'location_id': + continue + clean_leaves.append(leaf) - # Re-apply our multi-location filter - domain = expression.AND([stripped_domain, [('location_id', 'child_of', allowed_ids)]]) + # Re-apply our multi-location filter using expression.AND. + # This treats clean_leaves + [location_id filter] as a fresh, valid domain. + domain = expression.AND([clean_leaves, [('location_id', 'child_of', allowed_ids)]]) _logger.error(f"DEBUG_RESTRICT: SEARCH QUANT - Allowed: {allowed_ids} - Final Domain: {domain}") return super().web_search_read(domain, specification, offset=offset, limit=limit, order=order, count_limit=count_limit)