diff --git a/spp_api_v2_change_request/services/change_request_service.py b/spp_api_v2_change_request/services/change_request_service.py index 1b9220d6..e1db5971 100644 --- a/spp_api_v2_change_request/services/change_request_service.py +++ b/spp_api_v2_change_request/services/change_request_service.py @@ -204,10 +204,17 @@ def _serialize_detail(self, detail) -> dict[str, Any]: # Get fields from the model model_fields = detail._fields + # Field types that are skipped entirely — check BEFORE reading the + # value so that computed fields of these types are never triggered. + _SKIP_FIELD_TYPES = {"many2many", "one2many", "binary"} + for field_name, field in model_fields.items(): if field_name.startswith("_") or field_name in DETAIL_SKIP_FIELDS: continue + if field.type in _SKIP_FIELD_TYPES: + continue + value = getattr(detail, field_name) if field.type == "many2one": @@ -230,19 +237,10 @@ def _serialize_detail(self, detail) -> dict[str, Any]: } else: result[field_name] = value.name if hasattr(value, "name") else str(value.id) - elif field.type == "many2many": - # Skip many2many for now - continue - elif field.type == "one2many": - # Skip one2many for now - continue elif field.type == "date": result[field_name] = value.isoformat() if value else None elif field.type == "datetime": result[field_name] = value.isoformat() if value else None - elif field.type == "binary": - # Skip binary fields in API - continue else: result[field_name] = value diff --git a/spp_change_request_v2/models/change_request.py b/spp_change_request_v2/models/change_request.py index 6fa9c23e..9dc0d2f2 100644 --- a/spp_change_request_v2/models/change_request.py +++ b/spp_change_request_v2/models/change_request.py @@ -713,10 +713,15 @@ def _create_dms_directory(self): # ══════════════════════════════════════════════════════════════════════════ def get_detail(self): - """Get the detail record for this CR.""" + """Get the detail record for this CR. + + Uses with_prefetch() to isolate from _ensure_detail's sudo() + prefetch set — without this, non-stored computed fields can + trigger record-rule checks against the wrong user. + """ self.ensure_one() if self.detail_res_model and self.detail_res_id: - return self.env[self.detail_res_model].browse(self.detail_res_id) + return self.env[self.detail_res_model].browse(self.detail_res_id).with_prefetch() return None def _ensure_detail(self):