@@ -40,7 +40,8 @@ def resolve(self, scope):
4040 try :
4141 return resolver_method (scope )
4242 except Exception as e :
43- _logger .error ("Error resolving scope %s: %s" , scope .name , e )
43+ scope_name = scope .name
44+ _logger .error ("Error resolving scope %s: %s" , scope_name , e )
4445 return []
4546
4647 def _resolve_inline (self , scope_dict ):
@@ -101,7 +102,7 @@ def _resolve_cel_expression(self, expression, profile):
101102 if not executor :
102103 _logger .error ("CEL executor not available" )
103104 return []
104- executor = executor .sudo ()
105+ executor = executor .sudo () # nosemgrep: odoo-sudo-without-context
105106
106107 all_ids = []
107108 try :
@@ -145,25 +146,33 @@ def _resolve_area_ids(self, area_ids, include_children=True):
145146
146147 # Build area domain (sudo for model reads - callers may be unprivileged)
147148 if include_children :
148- # Use parent_path for efficient child lookup
149- areas = self .env ["spp.area" ].sudo ().browse (area_ids )
149+ # Collect all parent_path values first, then do a single search using
150+ # OR-chained domain conditions to avoid N+1 queries inside a loop.
151+ areas = self .env ["spp.area" ].sudo ().browse (area_ids ) # nosemgrep: odoo-sudo-without-context
150152 all_area_ids = set (area_ids )
151- for area in areas :
152- if area .parent_path :
153- # Find all child areas using parent_path prefix
154- children = self .env ["spp.area" ].sudo ().search ([("parent_path" , "like" , f"{ area .parent_path } %" )])
155- all_area_ids .update (children .ids )
153+ parent_paths = [area .parent_path for area in areas if area .parent_path ]
154+ if parent_paths :
155+ domain = ["|" ] * (len (parent_paths ) - 1 )
156+ for path in parent_paths :
157+ domain .append (("parent_path" , "like" , f"{ path } %" ))
158+ child_areas = self .env ["spp.area" ].sudo ().search (domain ) # nosemgrep: odoo-sudo-without-context
159+ all_area_ids .update (child_areas .ids )
156160 area_ids = list (all_area_ids )
157161
158162 # Find registrants directly in these areas
159163 domain = [
160164 ("is_registrant" , "=" , True ),
161165 ("area_id" , "in" , area_ids ),
162166 ]
163- direct_ids = set (self .env ["res.partner" ].sudo ().search (domain ).ids )
167+ direct_ids = set (
168+ self .env ["res.partner" ] # nosemgrep: odoo-sudo-without-context, odoo-sudo-on-sensitive-models
169+ .sudo ()
170+ .search (domain )
171+ .ids
172+ )
164173
165174 # Also find individuals without area_id whose group is in these areas
166- Membership = self .env ["spp.group.membership" ].sudo ()
175+ Membership = self .env ["spp.group.membership" ].sudo () # nosemgrep: odoo-sudo-without-context
167176 memberships = Membership .search (
168177 [
169178 ("group.area_id" , "in" , area_ids ),
@@ -203,7 +212,7 @@ def _resolve_area_tag_ids(self, tag_ids, include_children=True):
203212 return []
204213
205214 # Find areas with these tags (sudo for model reads - callers may be unprivileged)
206- areas = self .env ["spp.area" ].sudo ().search ([("tag_ids" , "in" , tag_ids )])
215+ areas = self .env ["spp.area" ].sudo ().search ([("tag_ids" , "in" , tag_ids )]) # nosemgrep: odoo-sudo-without-context
207216 if not areas :
208217 return []
209218
@@ -241,7 +250,7 @@ def _resolve_spatial_polygon_geometry(self, geojson_str):
241250 return spatial_resolver .resolve_polygon (geojson_str )
242251
243252 # Fallback: no spatial support
244- _logger .warning ("Spatial polygon scope requires spp_aggregation_spatial module. " " Returning empty result." )
253+ _logger .warning ("Spatial polygon scope requires spp_aggregation_spatial module. Returning empty result." )
245254 return []
246255
247256 def _resolve_spatial_buffer (self , scope ):
@@ -276,7 +285,7 @@ def _resolve_spatial_buffer_params(self, latitude, longitude, radius_km):
276285 return spatial_resolver .resolve_buffer (latitude , longitude , radius_km )
277286
278287 # Fallback: no spatial support
279- _logger .warning ("Spatial buffer scope requires spp_aggregation_spatial module. " " Returning empty result." )
288+ _logger .warning ("Spatial buffer scope requires spp_aggregation_spatial module. Returning empty result." )
280289 return []
281290
282291 # -------------------------------------------------------------------------
@@ -299,7 +308,7 @@ def _resolve_explicit_inline(self, scope_dict):
299308
300309 # Validate that these are actual registrants (sudo for model reads - callers may be unprivileged)
301310 valid_ids = (
302- self .env ["res.partner" ]
311+ self .env ["res.partner" ] # nosemgrep: odoo-sudo-without-context, odoo-sudo-on-sensitive-models
303312 .sudo ()
304313 .search (
305314 [
0 commit comments