Skip to content

Conversation

@Mohamed-Hacene
Copy link
Collaborator

@Mohamed-Hacene Mohamed-Hacene commented Dec 18, 2025

Summary by CodeRabbit

  • New Features

    • Added a third-party respondent checkbox in the user edit UI with help text and optional schema support.
    • Added localization keys and translations for the third-party respondent label and help text across many languages.
  • Refactor

    • Centralized and unified how related items are classified and displayed in cascade views, streamlining cascade-info flow and payloads; minor wording/spacing adjustments.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

Walkthrough

Centralizes cascade classification in backend core views (FORCED_CASCADE_FIELDS, add_with_classification) and unifies cascade-info display/processing; adds optional is_third_party to the user edit schema and an edit-mode checkbox in the UserForm; introduces thirdPartyRespondent and thirdPartyRespondentHelpText translation keys across locale files.

Changes

Cohort / File(s) Change Summary
Backend cascade logic refactor
backend/core/views.py
Adds FORCED_CASCADE_FIELDS and add_with_classification; centralizes classification of objects into deleted vs affected buckets (including forced cascade cases), unifies display string generation, and propagates classification through through-model endpoints, field_updates, and outgoing link handling; minor comment/whitespace updates.
Frontend user form
frontend/src/lib/components/Forms/ModelForm/UserForm.svelte
Adds an is_third_party checkbox rendered in edit (non-create) mode with label and help text sourced from messages; UI-only markup addition.
Frontend schema
frontend/src/lib/utils/schemas.ts
Extends UserEditSchema with is_third_party: z.boolean().optional().
Frontend translations (many locales)
frontend/messages/*.json
frontend/messages/en.json, frontend/messages/ar.json, frontend/messages/cs.json, frontend/messages/da.json, frontend/messages/de.json, frontend/messages/el.json, frontend/messages/es.json, frontend/messages/fr.json, frontend/messages/hi.json, frontend/messages/hr.json, frontend/messages/hu.json, frontend/messages/id.json, frontend/messages/it.json, frontend/messages/nl.json, frontend/messages/pl.json, frontend/messages/pt.json, frontend/messages/ro.json, frontend/messages/sv.json, frontend/messages/tr.json, frontend/messages/uk.json, frontend/messages/ur.json
Adds thirdPartyRespondent and thirdPartyRespondentHelpText keys to locale files; adjusts punctuation/wording in some cascadeAffectedHint entries to accommodate the new keys.
Manifest (context only)
package.json
Listed in diff context; no functional changes shown.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review focus:
    • backend/core/views.py: verify add_with_classification preserves prior cascade semantics across FK/O2O/M2M and through-model cases, including forced cascade pairs and payload shape changes.
    • Confirm display string normalization (name/email/str(obj)) still matches UI and downstream consumers.
    • Frontend: ensure UserForm.svelte checkbox binds correctly and the API accepts is_third_party per UserEditSchema.
    • Validate all modified locale JSON files for syntax (commas) and presence of new keys.

Poem

🐇 I hopped through code with a joyful twitch,

Collected cascades and sorted each stitch,
A checkbox for strangers, new phrases to say,
Tiny keys scattered across every language way,
— A rabbit’s cheer for a tidy new switch.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the primary change: adding a feature to allow users to be designated as third-party respondents, which is evident across backend cascade logic updates, frontend schema changes, UI form additions, and multi-language translation key additions.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch CA-1454-Handle-is_third_party-flag-in-user-edition

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05caa4d and e8d52ca.

📒 Files selected for processing (1)
  • backend/core/views.py (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
backend/core/views.py (1)
backend/tprm/models.py (2)
  • Entity (35-168)
  • Representative (218-239)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: build_enterprise_frontend
  • GitHub Check: build_community_frontend
  • GitHub Check: build (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: Analyze (python)
🔇 Additional comments (1)
backend/core/views.py (1)

140-140: Representative import usage looks correct

Importing Representative here is appropriate for the new FORCED_CASCADE_FIELDS usage in cascade_info, and introduces no obvious coupling or correctness issues.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/core/views.py (1)

717-942: Cascade classification: messaging inconsistency and FORCED_CASCADE_FIELDS brittleness

The refactor centralizes cascade classification effectively and resolves several issues (through-model handling, deduplication, consistent field update routing). However, two maintainability concerns warrant attention:

  1. "Deleted" bucket messaging conflicts with SET_NULL behavior
    Objects with on_delete=models.SET_NULL relationships (e.g., Representative.user) are routed to the deleted bucket via FORCED_CASCADE_FIELDS, but the payload message says "The following objects will be permanently deleted." This is factually incorrect—those objects are not deleted, only their foreign keys are cleared. Either adjust the messages in both the docstring and payload["deleted"]["message"] to clarify "deleted or logically removed due to business rules," or introduce a separate classification so the UI can distinguish actual deletions from relationship removals.

  2. String-based FORCED_CASCADE_FIELDS is fragile
    FORCED_CASCADE_FIELDS = {("Representative", "user")} relies on hard-coded model and field names matched via source_model.__name__ and string comparison. Renaming the model or field will silently break this behavior without static tooling to catch it. Consider using model metadata instead, such as comparing against source_model is Representative (if imports permit) or deriving tuples from model._meta.label for more robust matching.

The add_with_classification logic, _iter_objs iterator handling, and outgoing link classification (section 2c) all look solid.

🧹 Nitpick comments (1)
frontend/src/lib/utils/schemas.ts (1)

368-368: Consider adding a default value for consistency.

The is_third_party field is defined as z.boolean().optional() without a default value. Many similar boolean fields in this schema file use explicit defaults (e.g., is_active, is_locked, is_enabled with .default(false) or .default(true)).

Without a default, the field can be undefined, which might require additional handling in the backend. Consider whether .default(false) would be more appropriate for consistency.

🔎 Apply this diff if a default is preferred:
-	is_third_party: z.boolean().optional(),
+	is_third_party: z.boolean().optional().default(false),
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b4e6fa and 13bf936.

📒 Files selected for processing (4)
  • backend/core/views.py (5 hunks)
  • frontend/messages/en.json (1 hunks)
  • frontend/src/lib/components/Forms/ModelForm/UserForm.svelte (1 hunks)
  • frontend/src/lib/utils/schemas.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Frontend Linters
frontend/messages/en.json

[error] 2931-2931: Prettier check failed: SyntaxError in messages/en.json. Unexpected token, expected ','. (2931:1). Command: pnpm exec prettier --check .

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: Analyze (python)
🔇 Additional comments (2)
frontend/src/lib/components/Forms/ModelForm/UserForm.svelte (1)

76-81: The is_third_party field is intentionally available only during user editing, not creation.

This aligns with the schema design—UserCreateSchema excludes this field, while it remains available for updates. The system appears to follow a pattern where users are created as regular users and can be designated as third-party respondents through editing afterward. No changes needed.

backend/core/views.py (1)

5158-5199: UserFilter: adding is_third_party to filterable fields

Including "is_third_party" in UserFilter.Meta.fields is a straightforward way to expose the new flag for API‑level filtering and aligns with the frontend changes around third‑party respondents. Assuming User indeed has a Boolean is_third_party field and default lookup (exact) is intended, this looks correct and non‑breaking.

To double‑check that this filter is usable end‑to‑end, you can hit the list endpoint with a query like ?is_third_party=true and verify that only third‑party users are returned.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (7)
frontend/messages/ar.json (1)

1030-1032: Refine Arabic label to describe the user, not the responses

thirdPartyRespondent is currently "الردود الخارجية", which describes responses rather than the responding user. Consider changing it to something like "مجيب تابع لجهة خارجية" (or "مستجيب تابع لجهة خارجية") to match the user‑role semantics while keeping the existing help text.

frontend/messages/nl.json (1)

2927-2929: Translations look correct; consider slightly more idiomatic Dutch and inclusive wording

  • cascadeAffectedHint is clear and matches the intended meaning of "items remain but links are removed".
  • thirdPartyRespondent / thirdPartyRespondentHelpText correctly convey the restricted-respondent concept.

If you want slightly more natural and gender‑neutral Dutch, you could consider:

Optional wording tweak
- "thirdPartyRespondent": "Derdepartij-respondent",
- "thirdPartyRespondentHelpText": "Beperk de gebruiker tot het reageren op vragenlijsten/audits waartoe hij toegang heeft; geen andere acties zijn beschikbaar."
+ "thirdPartyRespondent": "Respondent van derde partij",
+ "thirdPartyRespondentHelpText": "Beperk deze gebruiker tot het reageren op vragenlijsten/audits waartoe hij toegang heeft; geen andere acties zijn beschikbaar."
frontend/messages/tr.json (1)

1795-1797: Polish Turkish label/help wording for ‘thirdPartyRespondent’ (optional)

Anlam doğru ama “Üçüncü Taraflı Yanıtlayıcı” kulağa biraz yapay geliyor; genelde “taraflı” önyargılı anlamını çağrıştırıyor. Daha doğal bir ifade ve yardım metni için aşağıdakini düşünebilirsiniz:

Önerilen diff
- "thirdPartyRespondent": "Üçüncü Taraflı Yanıtlayıcı",
- "thirdPartyRespondentHelpText": "Kullanıcıyı, erişebileceği anketler/denetimlere yanıt vermeye sınırlayın; başka bir işlem yoktur."
+ "thirdPartyRespondent": "Üçüncü taraf yanıtlayıcısı",
+ "thirdPartyRespondentHelpText": "Kullanıcıyı erişebileceği anketler/denetimlere yanıt vermekle sınırlandırın; başka işlemler yapamaz."
frontend/messages/cs.json (1)

1050-1052: Tighten Czech label to better match ‘third‑party respondent’ (optional)

Současný text „Třetí strana - odpovědná osoba“ evokuje spíš „odpovědná osoba“ než „respondent“. Pro přesnější význam můžete použít např.:

Navrhovaný diff
- "thirdPartyRespondent": "Třetí strana - odpovědná osoba",
+ "thirdPartyRespondent": "Respondent třetí strany",
frontend/messages/ur.json (1)

1030-1032: Optional Urdu phrasing improvements for cascade hint and respondent help

پیغام سمجھ میں آتا ہے، لیکن اردو قدرے زیادہ فصیح ہو سکتی ہے؛ مثلاً:

مجوزہ diff
- "cascadeAffectedHint": "نیچے دیے گئے اشیاء نظام میں باقی ہیں لیکن ان کی اس اشیاء سے لنکس ہٹا دیے جائیں گے۔",
- "thirdPartyRespondent": "تیسرے فریق کا جواب دہندہ",
- "thirdPartyRespondentHelpText": "صارف کو صرف ان سوالناموں/آڈٹس کا جواب دینے کی اجازت دیں جن تک وہ رسائی حاصل کر سکتے ہیں؛ کوئی دوسرا عمل دستیاب نہیں ہے۔"
+ "cascadeAffectedHint": "نیچے دی گئی اشیاء نظام میں موجود رہیں گی لیکن ان کے اس شے سے روابط ہٹا دیے جائیں گے۔",
+ "thirdPartyRespondent": "تیسرے فریق کا جواب دہندہ",
+ "thirdPartyRespondentHelpText": "صارف کو صرف ان سوالناموں/آڈٹس کے جوابات تک محدود کریں جن تک اسے رسائی حاصل ہے؛ کوئی دیگر کارروائی دستیاب نہیں ہوگی۔"
frontend/messages/de.json (1)

2928-2930: New German strings are correct; label could be phrased more naturally

Semantics and behavior description look good:

  • cascadeAffectedHint clearly explains that objects remain but links are removed.
  • thirdPartyRespondentHelpText accurately describes the restriction to answering questionnaires/audits only.

If you want slightly more natural UI German for the role label, you could consider e.g.:

  • "thirdPartyRespondent": "Drittanbieter-Befragter"
    or
  • "thirdPartyRespondent": "Externer Antwortender"

and optionally align the help text style with other toggles:

  • "thirdPartyRespondentHelpText": "Beschränkt diesen Benutzer darauf, nur Fragebögen/Audits zu beantworten, auf die er Zugriff hat; keine weiteren Aktionen sind verfügbar."

These are purely wording tweaks; current text is acceptable as-is.

Optional diff for wording
-  "thirdPartyRespondent": "Drittanbieter-Antwortverantwortlicher",
-  "thirdPartyRespondentHelpText": "Begrenzen Sie den Benutzer darauf, auf Fragebögen/Audits zu antworten, auf die er Zugriff hat; keine anderen Aktionen sind verfügbar."
+  "thirdPartyRespondent": "Drittanbieter-Befragter",
+  "thirdPartyRespondentHelpText": "Beschränkt diesen Benutzer darauf, nur Fragebögen/Audits zu beantworten, auf die er Zugriff hat; keine weiteren Aktionen sind verfügbar."
frontend/messages/es.json (1)

2927-2929: Spanish strings are clear; only minor stylistic tweaks are optional

The new messages read correctly and match the intended behavior:

  • cascadeAffectedHint explains the impact on links vs. objects.
  • thirdPartyRespondent / thirdPartyRespondentHelpText correctly convey the “answer-only” third‑party role.

If you want to polish phrasing slightly (optional):

  • Add a comma before “pero” in the hint:
    • "cascadeAffectedHint": "Los elementos a continuación se mantendrán en el sistema, pero se eliminarán sus enlaces a este objeto."
  • Consider a slightly more common role label, e.g.:
    • "thirdPartyRespondent": "Respondedor de terceros"
      or
    • "thirdPartyRespondent": "Usuario de terceros (respondente)"

Current text is acceptable; these are non-blocking refinements.

Optional diff for wording
-  "cascadeAffectedHint": "Los elementos a continuación se mantendrán en el sistema pero se eliminarán sus enlaces a este objeto.",
-  "thirdPartyRespondent": "Respondente de Terceros",
+  "cascadeAffectedHint": "Los elementos a continuación se mantendrán en el sistema, pero se eliminarán sus enlaces a este objeto.",
+  "thirdPartyRespondent": "Respondedor de terceros",
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13bf936 and 978332e.

📒 Files selected for processing (21)
  • frontend/messages/ar.json (1 hunks)
  • frontend/messages/cs.json (1 hunks)
  • frontend/messages/da.json (1 hunks)
  • frontend/messages/de.json (1 hunks)
  • frontend/messages/el.json (1 hunks)
  • frontend/messages/en.json (1 hunks)
  • frontend/messages/es.json (1 hunks)
  • frontend/messages/fr.json (1 hunks)
  • frontend/messages/hi.json (1 hunks)
  • frontend/messages/hr.json (1 hunks)
  • frontend/messages/hu.json (1 hunks)
  • frontend/messages/id.json (1 hunks)
  • frontend/messages/it.json (1 hunks)
  • frontend/messages/nl.json (1 hunks)
  • frontend/messages/pl.json (1 hunks)
  • frontend/messages/pt.json (1 hunks)
  • frontend/messages/ro.json (1 hunks)
  • frontend/messages/sv.json (1 hunks)
  • frontend/messages/tr.json (1 hunks)
  • frontend/messages/uk.json (1 hunks)
  • frontend/messages/ur.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/messages/en.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: build (3.12)
  • GitHub Check: build_community_frontend
  • GitHub Check: build_enterprise_frontend
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: lint-community (22)
  • GitHub Check: test (3.12)
  • GitHub Check: Analyze (python)
🔇 Additional comments (11)
frontend/messages/ro.json (1)

1059-1061: New Romanian strings for third‑party respondent look correct

The hint and the new thirdPartyRespondent label/help text are clear, grammatically sound, and consistent with the intended behavior. JSON structure is also valid.

frontend/messages/sv.json (1)

1053-1055: Swedish translation for third‑party respondent is consistent and clear

The updated cascadeAffectedHint plus thirdPartyRespondent label/help text read naturally in Swedish and accurately reflect the feature; JSON remains valid.

frontend/messages/pt.json (1)

1062-1064: Portuguese third‑party respondent strings are well‑formed

The updated cascade hint and the new thirdPartyRespondent label/help text are idiomatic PT‑BR and consistent with related terminology elsewhere in this file; JSON syntax is correct.

frontend/messages/it.json (1)

1439-1441: Italian translations for third‑party respondent are accurate

The cascade hint plus thirdPartyRespondent label/help text are clear, idiomatic, and consistent with existing third‑party terminology; JSON remains valid.

frontend/messages/fr.json (1)

2928-2930: French keys align well with semantics and style

  • cascadeAffectedHint clearly mirrors the cascade notice behavior and reads naturally.
  • thirdPartyRespondent / thirdPartyRespondentHelpText accurately express a third‑party, respondent‑only user with limited actions, consistent with the new is_third_party behavior.

No changes needed here.

frontend/messages/hi.json (1)

1031-1034: LGTM! Translation keys added correctly.

The structural changes are sound:

  • Trailing comma added to cascadeAffectedHint to accommodate new keys
  • Two new translation keys (thirdPartyRespondent and thirdPartyRespondentHelpText) added consistently
  • JSON formatting is correct
frontend/messages/hu.json (1)

1062-1064: LGTM! Translation keys added correctly.

The changes are structurally correct:

  • Trailing comma properly added to cascadeAffectedHint
  • Two new translation keys added consistently with naming conventions
  • JSON formatting is valid
frontend/messages/id.json (1)

1247-1249: LGTM! Translation keys added correctly.

The structural changes are appropriate:

  • Trailing comma added to cascadeAffectedHint for proper JSON syntax
  • Two new translation keys (thirdPartyRespondent and thirdPartyRespondentHelpText) added consistently
  • Formatting aligns with the rest of the file
frontend/messages/hr.json (1)

2027-2029: LGTM! Translation additions are clean and consistent.

The changes correctly add two new translation keys (thirdPartyRespondent and thirdPartyRespondentHelpText) to support the new third-party respondent user attribute introduced in this PR. The trailing comma on line 2027 is properly added to maintain valid JSON syntax. The Croatian translations appear appropriate and align with the help text describing restricted permissions for third-party respondents.

frontend/messages/da.json (1)

1342-1344: LGTM! Danish translations properly added.

The changes mirror the same pattern applied across other locale files in this PR, adding the two new translation keys (thirdPartyRespondent and thirdPartyRespondentHelpText) for the third-party respondent feature. The JSON syntax is correct with the trailing comma on line 1342, and the Danish translations ("Tredjeparts respondent" and the help text) appear appropriate for describing the restricted permission model.

frontend/messages/pl.json (1)

1802-1802: Translation improvement looks good.

The simplified wording removes unnecessary specificity ("Poniższe") and uses more appropriate future tense, making the hint clearer and more concise.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/core/views.py (1)

717-944: Forced cascades may display misleading "deleted" status for SET_NULL relationships

The refactor improves clarity with the centralized add_with_classification logic. However, one UX issue needs attention:

FORCED_CASCADE_FIELDS = {(Representative, "user")} combined with add_with_classification places Representative objects in the deleted bucket when a User is deleted. Since Representative.user has on_delete=models.SET_NULL, the Representative row is not deleted—only the foreign key field is set to null. The payload message "The following objects will be permanently deleted." is therefore misleading for these cases.

Consider either adjusting the message to reflect that these objects lose relationships (matching the "affected" bucket behavior), or separating "logically affected" objects into a distinct category to communicate the actual impact more clearly.

Additionally, the direct import of Representative at module level (line 140) hard-couples core to tprm. While tprm is guaranteed in INSTALLED_APPS, consider using apps.get_model("tprm", "Representative") under a try/except if you want to reduce inter-app dependencies or enable optional app configurations in the future.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12d3393 and 05caa4d.

📒 Files selected for processing (1)
  • backend/core/views.py (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: build (3.12)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: build_enterprise_frontend
  • GitHub Check: build_community_frontend
  • GitHub Check: test (3.12)
  • GitHub Check: Analyze (python)
🔇 Additional comments (1)
backend/core/views.py (1)

140-140: Representative import usage is consistent with new cascade classification

Importing Representative from tprm.models is needed for FORCED_CASCADE_FIELDS in cascade_info, and the symbol is used there, so this addition is correct and necessary.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/core/views.py (1)

721-742: FORCED_CASCADE_FIELDS condition prevents (Representative, "user") from ever taking effect

The centralized classification and unified display in cascade_info are good improvements, but the current guard around FORCED_CASCADE_FIELDS makes the new (Representative, "user") entry effectively dead:

  • In the field_updates loop (2b), source_model is field.model, i.e. Representative for the Representative.user FK, while instance.__class__ is User when deleting a user.
  • add_with_classification only treats a forced pair as deleted when source_model == instance.__class__, so (Representative, "user") is never matched there.
  • Reverse relations from User to Representative don’t go through the 2c “outgoing links” branch either, because those auto‑created reverse fields are skipped.

Net effect: representatives whose user is set to NULL during user deletion are still classified as “affected”, not “deleted”, despite being listed in FORCED_CASCADE_FIELDS.

You can fix this by dropping the source_model == instance.__class__ constraint and relying solely on the (source_model, field_name) pair:

Suggested fix for forced‑cascade routing
@@ def cascade_info(self, request, pk=None):
-        def is_forced_cascade(source_model, field_name):
-            return (source_model, field_name) in FORCED_CASCADE_FIELDS
+        def is_forced_cascade(source_model, field_name):
+            return (source_model, field_name) in FORCED_CASCADE_FIELDS
@@
-        def add_with_classification(obj, source_model=None, source_field=None):
+        def add_with_classification(obj, source_model=None, source_field=None):
@@
-            if (
-                source_model == instance.__class__
-                and source_field
-                and is_forced_cascade(source_model, source_field)
-            ):
+            if source_model and source_field and is_forced_cascade(
+                source_model, source_field
+            ):
                 add_grouped(deleted_bucket, obj)
                 return

This will allow the (Representative, "user") rule to apply to field_updates when deleting a User, and any future forced pairs keyed by the referencing model.

Also applies to: 744-748, 749-755, 769-771, 795-812, 826-848, 849-882, 884-899, 902-908, 915-942

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05caa4d and e8d52ca.

📒 Files selected for processing (1)
  • backend/core/views.py (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
backend/core/views.py (1)
backend/tprm/models.py (2)
  • Entity (35-168)
  • Representative (218-239)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: build_enterprise_frontend
  • GitHub Check: build_community_frontend
  • GitHub Check: build (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: Analyze (python)
🔇 Additional comments (1)
backend/core/views.py (1)

140-140: Representative import usage looks correct

Importing Representative here is appropriate for the new FORCED_CASCADE_FIELDS usage in cascade_info, and introduces no obvious coupling or correctness issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants