Skip to content

Comments

feat:report preview api#3536

Open
nandkishorr wants to merge 4 commits intodevelopfrom
nandkishorr/report_live_preview
Open

feat:report preview api#3536
nandkishorr wants to merge 4 commits intodevelopfrom
nandkishorr/report_live_preview

Conversation

@nandkishorr
Copy link
Contributor

@nandkishorr nandkishorr commented Feb 18, 2026

Merge Checklist

  • Tests added/fixed
  • Update docs in /docs
  • Linting Complete
  • Any other necessary step

Only PR's with test cases included and passing lint and test pipelines will be reviewed

@ohcnetwork/care-backend-maintainers @ohcnetwork/care-backend-admins

Summary by CodeRabbit

  • New Features
    • Added report preview: users can preview reports in a chosen output format with validation of format, template selection, and required permissions; previews build context from the associated record and return a rendered response with consolidated error reporting.

@nandkishorr nandkishorr self-assigned this Feb 18, 2026
@nandkishorr nandkishorr requested a review from a team as a code owner February 18, 2026 15:35
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

Warning

Rate limit exceeded

@nandkishorr has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 18 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Adds a new preview POST action to ReportUploadViewSet that enforces preview permission, validates output format and template/options via registries, resolves report context with data-point resolution and associating_id validation, renders content with Renderer, and returns the generator’s HTTP response.

Changes

Cohort / File(s) Summary
Report Preview Action
care/emr/api/viewsets/report/report_upload.py
Introduces a new preview API action and related imports (DataPointRegistry, Renderer, ReportTypeRegistry, validate_associating_id, generator registry usage). Action checks can_preview_template, validates output_format and template existence, validates/derives template options from generator options model, retrieves report type config, resolves and builds context via data-point registry using associating_id, renders content with Renderer, returns generator HTTP response, and wraps errors as ValidationError responses.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is missing critical sections: no 'Proposed Changes', 'Associated Issue', or 'Architecture changes' details are provided despite the template requiring them. Add 'Proposed Changes' explaining the preview API implementation, link the associated GitHub issue, and include 'Architecture changes' describing the new endpoint and its workflow.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change—adding a preview API for reports—which aligns with the changeset's new preview action on ReportUploadViewSet.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nandkishorr/report_live_preview

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: 3

🧹 Nitpick comments (1)
care/emr/api/viewsets/report/report_upload.py (1)

34-34: CeleryTaskError import is unnecessary if the fix above is applied.

If you replace the CeleryTaskError usage on Line 176 with ValidationError (as suggested), this import becomes unused and can be removed.

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

In `@care/emr/api/viewsets/report/report_upload.py` at line 34, Remove the
now-unused import CeleryTaskError from the top import list (the symbol
CeleryTaskError) since the code path that used it was changed to raise
ValidationError instead; update the imports to only include ValidationError (and
any other remaining exceptions), ensuring there are no leftover unused imports
referencing CeleryTaskError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@care/emr/api/viewsets/report/report_upload.py`:
- Around line 156-158: The preview action currently omits the template.active
status validation present in the generate action (the check that fails when
template.status != "active"); either add the same status guard to the preview
handler (reject non-active templates the same way as generate) or, if previewing
drafts is intentional, add an explicit comment in the preview function noting
that skipping the template.status != "active" check is deliberate so designers
can preview non-active templates; reference the preview action and the generate
action's template.status check when making the change.
- Around line 178-182: Replace the ValueError raised when
ReportTypeRegistry.get(template.template_type) fails with a DRF ValidationError
so the API returns a 4xx client error; in the try/except around
ReportTypeRegistry.get (the block handling template.template_type) raise
rest_framework.exceptions.ValidationError (or the project's
serializers.ValidationError alias) with the same error_msg and update imports as
needed.
- Around line 156-200: In the preview action, fix three issues: (1) when
request_data.output_format is None, fallback to the template's default_format
like the generate action by resolving template before validating output_format
and using template.default_format if needed (look for GenerateReportRequest and
preview); (2) guard DataPointRegistry.get(template.context) for None before
accessing .context_key and raise a ValidationError with a clear message if the
context slug isn't registered (refer to DataPointRegistry.get and context_key
usage); (3) replace raising CeleryTaskError in the Template.DoesNotExist handler
with an appropriate DRF exception (ValidationError or Http404) and stop using a
blanket except Exception at the end — instead catch and re-raise known DRF
exceptions (e.g., ValidationError, PermissionDenied) and only catch unexpected
exceptions to log them and return a concise ValidationError, so real programming
errors aren't swallowed (refer to Template.DoesNotExist handling and the outer
try/except in preview).

---

Nitpick comments:
In `@care/emr/api/viewsets/report/report_upload.py`:
- Line 34: Remove the now-unused import CeleryTaskError from the top import list
(the symbol CeleryTaskError) since the code path that used it was changed to
raise ValidationError instead; update the imports to only include
ValidationError (and any other remaining exceptions), ensuring there are no
leftover unused imports referencing CeleryTaskError.

Comment on lines +156 to +158
@extend_schema(
request=GenerateReportRequest, responses={200: "Success"}, tags=["report"]
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing template status check for preview.

The generate action validates template.status != "active" (Line 125-126) before proceeding. The preview action skips this check entirely. This could allow previewing inactive or draft templates. If that's the intended behavior (designers previewing drafts), that's fine — but it's worth being explicit about it with a comment.

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

In `@care/emr/api/viewsets/report/report_upload.py` around lines 156 - 158, The
preview action currently omits the template.active status validation present in
the generate action (the check that fails when template.status != "active");
either add the same status guard to the preview handler (reject non-active
templates the same way as generate) or, if previewing drafts is intentional, add
an explicit comment in the preview function noting that skipping the
template.status != "active" check is deliberate so designers can preview
non-active templates; reference the preview action and the generate action's
template.status check when making the change.

@codecov
Copy link

codecov bot commented Feb 18, 2026

Codecov Report

❌ Patch coverage is 18.42105% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.34%. Comparing base (0d866d3) to head (a0523dd).

Files with missing lines Patch % Lines
care/emr/api/viewsets/report/report_upload.py 18.42% 31 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3536      +/-   ##
===========================================
- Coverage    75.45%   75.34%   -0.11%     
===========================================
  Files          473      473              
  Lines        21977    22015      +38     
  Branches      2293     2296       +3     
===========================================
+ Hits         16582    16587       +5     
- Misses        4877     4909      +32     
- Partials       518      519       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

🧹 Nitpick comments (1)
care/emr/api/viewsets/report/report_upload.py (1)

180-182: except Exception is broader than necessary — should be except KeyError

ReportTypeRegistry.get() raises KeyError when a type isn't registered. Catching Exception here also inadvertently masks unrelated runtime errors (e.g., an AttributeError inside get() itself). This is also moot when the outer except Exception swallows everything anyway (see below), but it's worth fixing regardless.

♻️ Proposed fix
-            except Exception as err:
+            except KeyError as err:
                 error_msg = f"Report Type '{template.template_type}' not found in ReportTypeRegistry"
                 raise ValidationError(error_msg) from err
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@care/emr/api/viewsets/report/report_upload.py` around lines 180 - 182, The
except block catching Exception around the call to ReportTypeRegistry.get()
should be narrowed to except KeyError so only missing-report-type errors are
handled; update the handler that currently builds error_msg using
template.template_type and raises ValidationError to catch KeyError (from
ReportTypeRegistry.get) and preserve other exceptions (i.e., do not swallow
them), keeping the original error context when raising ValidationError from the
caught KeyError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@care/emr/api/viewsets/report/report_upload.py`:
- Line 161: Update the user-facing permission denial message in the raise
PermissionDenied(...) call to fix the typo: change "You dont have permission to
preview reports" to include the apostrophe ("don't"); locate the raise
PermissionDenied(...) in report_upload.py (the permission check/preview report
path) and replace the string accordingly.

---

Duplicate comments:
In `@care/emr/api/viewsets/report/report_upload.py`:
- Around line 184-185: DataPointRegistry.get(template.context) can return None,
causing an AttributeError when accessing context_class.context_key; update the
code around the lookup (the call to DataPointRegistry.get, the context_class
variable and subsequent use of context_key) to guard against None by checking if
context_class is truthy and handling the unregistered slug explicitly (e.g.,
raise a clear error or return/skip with a descriptive message referencing
template.context) before accessing context_class.context_key so the outer
exception handler does not mask the real cause.
- Around line 165-166: The preview path incorrectly rejects requests where
request_data.output_format is None because
GeneratorRegistry.is_registered(request_data.output_format) returns False;
update the preview handling to mirror generate by falling back to
template.default_format when output_format is falsy (or perform the same
conditional used in GenerateReportRequest.validate_output_format: only call
GeneratorRegistry.is_registered when v is truthy). Locate the preview action and
the check using GeneratorRegistry.is_registered and change it to use
request_data.output_format or template.default_format (or guard the check with
"if v and ...") so None input uses template.default_format and avoids the
misleading ValidationError.
- Around line 168-200: The outer except Exception in the report preview flow is
catching and replacing specific DRF ValidationError messages raised earlier
(e.g., Template.DoesNotExist -> ValidationError in the Template lookup,
ReportTypeRegistry.get -> ValidationError) with a generic "Preview generation
failed"; change the exception handling in the viewset so that inside the
try/except around
GeneratorRegistry/Template/ReportTypeRegistry/DataPointRegistry/Renderer you
first re-raise known DRF/API exceptions (e.g., ValidationError, APIException)
unchanged, and only convert unexpected exceptions into a new ValidationError;
specifically adjust the except block that wraps GeneratorRegistry,
Template.objects.get, ReportTypeRegistry.get, DataPointRegistry.get,
Renderer(generator).render and generator.get_http_response to check for
isinstance(e, (ValidationError, APIException)) and re-raise it, otherwise raise
ValidationError("Preview generation failed") from e so that the precise messages
from Template/ReportType errors are preserved.

---

Nitpick comments:
In `@care/emr/api/viewsets/report/report_upload.py`:
- Around line 180-182: The except block catching Exception around the call to
ReportTypeRegistry.get() should be narrowed to except KeyError so only
missing-report-type errors are handled; update the handler that currently builds
error_msg using template.template_type and raises ValidationError to catch
KeyError (from ReportTypeRegistry.get) and preserve other exceptions (i.e., do
not swallow them), keeping the original error context when raising
ValidationError from the caught KeyError.

@vigneshhari
Copy link
Member

No AuthZ present

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.

2 participants