Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions care/emr/api/viewsets/report/report_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
read_report_authorizer,
write_report_authorizer,
)
from care.emr.reports.context_builder.data_point_registry import DataPointRegistry
from care.emr.reports.renderer.generators import GeneratorRegistry
from care.emr.reports.renderer.renderer import Renderer
from care.emr.reports.report_type_registry import ReportTypeRegistry
from care.emr.reports.report_type_utils import validate_associating_id
from care.emr.resources.report.report_upload.spec import (
ReportUploadListSpec,
ReportUploadRetrieveSpec,
Expand Down Expand Up @@ -148,6 +152,53 @@ def generate(self, request, *args, **kwargs):
status=status.HTTP_201_CREATED,
)

@extend_schema(
request=GenerateReportRequest, responses={200: "Success"}, tags=["report"]
)
Comment on lines +156 to +158
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.

@action(detail=False, methods=["POST"])
def preview(self, request, *args, **kwargs):
if not AuthorizationController.call("can_preview_template", request.user):
raise PermissionDenied("You dont have permission to preview reports")

request_data = GenerateReportRequest.model_validate(request.data)

if not GeneratorRegistry.is_registered(request_data.output_format):
raise ValidationError("Invalid output format")

try:
generator_class = GeneratorRegistry.get(request_data.output_format)
generator = generator_class()
try:
template = Template.objects.get(external_id=request_data.template_id)
except Template.DoesNotExist as err:
msg = f"Template {request_data.template_id} does not exist"
raise ValidationError(msg) from err
validated_options = generator.options_model.model_validate(template.options)
try:
report_type_config = ReportTypeRegistry.get(template.template_type)

except Exception as err:
error_msg = f"Report Type '{template.template_type}' not found in ReportTypeRegistry"
raise ValidationError(error_msg) from err

context_class = DataPointRegistry.get(template.context)
context_key = context_class.context_key or template.context
associating_object = validate_associating_id(
associating_model=report_type_config.associating_model,
associating_id=str(request_data.associating_id),
report_type_key=template.template_type,
)
context = {context_key: context_class(context=associating_object)}

rendered_content = Renderer(generator).render(
template.template_data, context, validated_options
)

return generator.get_http_response(rendered_content)

except Exception as e:
raise ValidationError("Preview generation failed") from e

class ArchiveRequestSpec(BaseModel):
archive_reason: str

Expand Down