Skip to content

fix(data_wizard): Make audit and risk assessment perimeter optional#3799

Open
monsieurswag wants to merge 2 commits intomainfrom
fix/make_data_wizard_assessments_perimeter_optional
Open

fix(data_wizard): Make audit and risk assessment perimeter optional#3799
monsieurswag wants to merge 2 commits intomainfrom
fix/make_data_wizard_assessments_perimeter_optional

Conversation

@monsieurswag
Copy link
Copy Markdown
Contributor

@monsieurswag monsieurswag commented Mar 27, 2026

Currently CLI users are forced to specify a Perimeter when using import-risk-assessment or import-compliance-assessment commands.
This is wrong as both the RiskAssessment.perimeter and ComplianceAssessment.perimeter fields are optional (they are ForeignKey with null=True).

Now users can either specify a perimeter, or only specify the folder if they want no perimeter.

Summary by CodeRabbit

Release Notes

  • New Features
    • The ComplianceAssessment and RiskAssessment commands no longer require a perimeter identifier. Both commands are now more flexible—you can run them using only a folder identifier when perimeter information is unavailable. This enhancement improves usability for import operations in scenarios where perimeter data may not be available or when working with alternative organizational structures.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 38ba77a4-7f71-4260-879b-d273d6ad0b34

📥 Commits

Reviewing files that changed from the base of the PR and between daa14f2 and d244eb7.

📒 Files selected for processing (1)
  • backend/data_wizard/views.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/data_wizard/views.py

📝 Walkthrough

Walkthrough

Perimeter is now optional for compliance and risk assessment imports. Backend helpers conditionally resolve Perimeter and/or folder_id/domain, raising if neither is provided. CLI flags for ComplianceAssessment and RiskAssessment no longer require --perimeter.

Changes

Cohort / File(s) Summary
Backend perimeter resolution
backend/data_wizard/views.py
Made perimeter_id optional in _process_compliance_assessment and _process_risk_assessment; conditionally load Perimeter when present, derive folder_id/domain from it, or require folder_id fallback; assert if both missing.
CLI command configuration
cli/clica.py
Relaxed CLI requirements by setting requires_perimeter = False for ComplianceAssessment and RiskAssessment commands, removing mandatory --perimeter.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 I hopped from perimeter to folder bright,

Made optional paths beneath the light,
When fences fade, a fallback springs,
Flexible paws and careful things,
A tiny rabbit cheers the new flight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 describes the main change: making perimeter optional for audit and risk assessment in the data wizard, which aligns with the backend logic changes and CLI configuration updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/make_data_wizard_assessments_perimeter_optional

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
Copy Markdown
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)
cli/clica.py (1)

324-330: ⚠️ Potential issue | 🟠 Major

These commands now hide every target selector.

register_data_wizard_command() derives show_perimeter_option from requires_perimeter, and show_folder_option is already false for ComplianceAssessment/RiskAssessment. After this change, --help shows neither --perimeter nor --folder, while the backend still requires one of them. The CLI also stops catching that invalid combination before uploading the file.

💡 At minimum, keep the selectors visible again
     {
         "command": "import_compliance_assessments",
         "model_type": "ComplianceAssessment",
         "help": "Import compliance assessments using the Data Wizard backend.",
         "requires_folder": False,
         "requires_perimeter": False,
+        "show_folder_option": True,
+        "show_perimeter_option": True,
         "requires_framework": True,
         "requires_matrix": False,
     },
@@
     {
         "command": "import_risk_assessment",
         "model_type": "RiskAssessment",
         "help": "Import risk assessments using the Data Wizard backend.",
         "requires_folder": False,
         "requires_perimeter": False,
+        "show_folder_option": True,
+        "show_perimeter_option": True,
         "requires_framework": False,
         "requires_matrix": True,
     },

Also applies to: 342-348

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/clica.py` around lines 324 - 330, The CLI command dict for
"import_compliance_assessments" (and the similar block at 342-348) hides
selector flags because register_data_wizard_command derives
show_perimeter_option from requires_perimeter and folder is already false;
explicitly enable the selector visibility so users see the options and the CLI
can validate them: update the command config passed to
register_data_wizard_command (for "import_compliance_assessments" and the other
affected command) to include an explicit show_perimeter_option: True (or
otherwise set the appropriate requires_perimeter/ show_folder_option flags) so
the --perimeter/--folder options are shown and the CLI can validate the
combination before upload.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/data_wizard/views.py`:
- Around line 2529-2541: The code currently raises an AssertionError when
neither perimeter nor folder_id is provided; instead, return a normal import
result dict (the same shape as the existing results variable) so callers like
process_excel_file() receive a dict not an exception-wrapped Response. In the
branch where perimeter is None and folder_id is None, populate results["failed"]
(e.g., set to 1) and append an explanatory message to results["errors"] (e.g.,
"A folder must be specified when there's no perimeter"), then return results
immediately; update the block around Perimeter.objects.get, perimeter, folder_id
to perform this return rather than raising. Ensure the returned shape matches
the existing results dict.

---

Outside diff comments:
In `@cli/clica.py`:
- Around line 324-330: The CLI command dict for "import_compliance_assessments"
(and the similar block at 342-348) hides selector flags because
register_data_wizard_command derives show_perimeter_option from
requires_perimeter and folder is already false; explicitly enable the selector
visibility so users see the options and the CLI can validate them: update the
command config passed to register_data_wizard_command (for
"import_compliance_assessments" and the other affected command) to include an
explicit show_perimeter_option: True (or otherwise set the appropriate
requires_perimeter/ show_folder_option flags) so the --perimeter/--folder
options are shown and the CLI can validate the combination before upload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 09b25df8-ce4f-455c-80b8-4178cdfc4344

📥 Commits

Reviewing files that changed from the base of the PR and between de549d9 and daa14f2.

📒 Files selected for processing (2)
  • backend/data_wizard/views.py
  • cli/clica.py

Comment on lines 2529 to +2541
results = {"successful": 0, "failed": 0, "errors": []}
try:
# Get the perimeter object to extract its folder ID
perimeter = Perimeter.objects.get(id=perimeter_id)
folder_id = perimeter.folder.id
perimeter = None
if perimeter_id is not None:
perimeter = Perimeter.objects.get(id=perimeter_id)

if perimeter is not None:
folder_id = perimeter.folder.id
elif folder_id is None:
raise AssertionError(
"A folder must be specified when there's no perimeter!"
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Return a normal import result here instead of raising.

This branch is newly reachable now that perimeter is optional. Raising here falls into the broad except below, which returns a DRF Response from a helper that otherwise returns a dict; process_excel_file() then wraps that value in another response. Please fail with the same result shape as the other import helpers.

💡 Minimal fix
-            elif folder_id is None:
-                raise AssertionError(
-                    "A folder must be specified when there's no perimeter!"
-                )
+            elif folder_id is None:
+                results["failed"] = len(records)
+                results["errors"].append(
+                    {"error": "A folder must be specified when there's no perimeter."}
+                )
+                return results
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/data_wizard/views.py` around lines 2529 - 2541, The code currently
raises an AssertionError when neither perimeter nor folder_id is provided;
instead, return a normal import result dict (the same shape as the existing
results variable) so callers like process_excel_file() receive a dict not an
exception-wrapped Response. In the branch where perimeter is None and folder_id
is None, populate results["failed"] (e.g., set to 1) and append an explanatory
message to results["errors"] (e.g., "A folder must be specified when there's no
perimeter"), then return results immediately; update the block around
Perimeter.objects.get, perimeter, folder_id to perform this return rather than
raising. Ensure the returned shape matches the existing results dict.

"help": "Import compliance assessments using the Data Wizard backend.",
"requires_folder": False,
"requires_perimeter": True,
"requires_perimeter": False,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

almost, now we're in a situation where domain (folder) and perimeter are optional

Copy link
Copy Markdown

@JiwaniZakir JiwaniZakir left a comment

Choose a reason for hiding this comment

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

The use of AssertionError in both _process_compliance_assessment and _process_risk_assessment is inappropriate for input validation — AssertionError is intended for internal invariant checks and can be silently disabled when Python runs with the -O optimization flag. A ValueError (or a domain-specific exception) would be more semantically correct and safer here.

More critically, in cli/clica.py, both model type configs still have "requires_folder": False even after setting "requires_perimeter": False. This means a user can now invoke the CLI without providing either a perimeter or a folder, and the error won't surface until the request hits the backend and raises that AssertionError. The CLI should enforce the "at least one of perimeter or folder is required" constraint at the argument-parsing level, or at minimum requires_folder should be conditionally tied to whether a perimeter is provided.

It's also worth adding a test scenario where perimeter_id=None and folder_id=None are both passed to each function, to verify the error path behaves as expected rather than producing an unhandled ObjectDoesNotExist or silent failure.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants