← Knowledge library

Clinical care

Report & Templates

A Template defines reusable report markup and render options; a ReportUpload is one generated file produced from that template and linked to a subject resource. You author templates through the API; report uploads are created for you by the…

3.1 · versioned documentation · 8 min read

A Template defines reusable report markup and render options; a ReportUpload is one generated file (PDF/HTML/etc.) produced from that template and linked to a subject resource. You author templates through the API; report uploads are created for you by the file-upload flow.

Two layers back this:

Source:

Models

Model Purpose
ReportUpload An uploaded, generated report file (PDF/HTML/etc.) produced from a Template and linked to a subject resource via associating_id
Template A facility-scoped (or instance-wide) reusable report definition (markup + render options) used to generate reports

ReportUpload extends EMRBaseModel, the shared MANSOQ EMR base providing external_id, meta/history JSON, audit FKs, and soft-delete semantics.

Template extends SlugBaseModel, the facility-scoped slug variant (FACILITY_SCOPED = True, which adds slug handling on top of the EMR base). Slugs carry a prefix in storage: f-<facility_external_id>-<slug> when facility-scoped, i-<slug> when instance-wide (see base.py).

ReportUpload fields

Core

Field Type Notes
template FK → Template (PROTECT) Template the report was generated from. The template cannot be deleted while reports reference it
name CharField(2000) Display name of the report. Required in every spec
internal_name CharField(2000) Randomized storage key, auto-generated on save so the file name never leaks PII (see save behaviour). Exposed only in RetrieveSpec
associating_id CharField(100) Non-null. Free-form identifier linking the report to its subject resource (e.g. an encounter)
upload_completed BooleanField Default False. Flips to True once the file upload to storage finishes
report_type CharField(50) File/content type of the report; also exposed via the file_type property for S3FilesManager

Archival

Field Type Notes
is_archived BooleanField Default False
archive_reason TextField Blank allowed
archived_datetime DateTimeField Nullable; set when the report is archived
archived_by FK → User (PROTECT) Nullable. related_name="archived_reports"

Inherited / metadata

Field Type Notes
meta JSONField (default {}) Inherited from EMRBaseModel. Holds mime_type (surfaced by specs as mime_type) and other free-form metadata
history JSONField (default {}) Inherited audit history
created_by / updated_by FK → User (SET_NULL) Inherited audit FKs; serialized as created_by/updated_by UserSpec

Storage

ReportUpload declares a class-level files_manager = S3FilesManager(BucketType.REPORT). The file body lives in object storage (REPORT bucket), not the database — the model row holds only metadata and the internal_name storage key.

Template fields

The Django model stores most config as plain strings plus an opaque options JSONField. The constraints live in the spec layer: it pins status, default_format, and the slug, and validates the structure and mutual compatibility of template_type, context, and options.

Field Type (model) Spec constraint Notes
facility FK → Facility (PROTECT, nullable) UUID4 | None (write) Null → instance-wide template; set → facility-scoped. Excluded from base serialization (__exclude__); resolved server-side on write
slug CharField(255) written via slug_value: SlugType; read as slug + parsed slug_config Stored prefixed (f-…/i-…). slug_value must be 5–50 chars, URL-safe, and start and end alphanumeric
name CharField(255) str, required
status CharField(255) TemplateStatusOptions enum See status values
template_data TextField str, required (write) The report markup/body. Returned only by RetrieveSpec, not in list/read
template_type CharField(255) str, validated against ReportTypeRegistry Must be a registered report type, and compatible with context (matching associating_model)
default_format CharField(255) TemplateFormatOptions enum See format values. Selects which generator validates options
context CharField(100) (default "encounter_base") str, validated against DataPointRegistry Defaults to encounter_base, so reports are encounter-oriented unless overridden. Must be a registered context compatible with template_type
description TextField (blank, default "") str = ""
options JSONField (default {}) dict = {}, validated against the format generator's options_model Render/config options; accepted keys depend on default_format (PDF vs HTML generator)

TemplateStatusOptions values

status is bound to this enum (care/emr/resources/report/template/spec.py):

Value Meaning
draft Template being authored, not yet usable
active Published, usable for generating reports
retired Withdrawn from use

TemplateFormatOptions values

default_format is bound to this enum:

Value Meaning
pdf Render to PDF (uses the PDF generator's options_model)
html Render to HTML (uses the HTML generator's options_model)

slug_config shape (read)

On read, TemplateReadSpec parses the stored prefixed slug back into a slug_config dict:

slug_config (facility-scoped) → { facility: <facility_external_id>, slug_value: <slug> }
slug_config (instance-wide)   → { slug_value: <slug> }   # parsed from "i-<slug>"

Resource specs (API schema)

All specs subclass EMRResource. Read runs serialize() → DB-field copy → perform_extra_serialization() hook. Write runs de_serialize() → DB-field copy → perform_extra_deserialization() hook.

ReportUpload specs (report/report_upload/spec.py)

Spec class Role Fields / behaviour
ReportUploadBaseSpec shared id: UUID4 | None, name: str
ReportUploadListSpec read · list Adds template (nested TemplateReadSpec), report_type, associating_id, archived_by (UserSpec), archived_datetime, upload_completed, is_archived, archive_reason, created_date, extension, uploaded_by, mime_type
ReportUploadRetrieveSpec read · detail Extends list spec; adds signed_url, read_signed_url, internal_name

Server-maintained read behaviour (perform_extra_serialization):

ReportUpload has no CreateSpec/UpdateSpec in this module. Uploads come from the file-upload flow (File Upload), and the report metadata and internal_name are platform-maintained. See save behaviour.

Template specs (report/template/spec.py)

Spec class Role Fields / behaviour
TemplateBaseSpec shared id, name, status (TemplateStatusOptions), default_format (TemplateFormatOptions), description = "", options = {}. __exclude__ = ["facility"]
TemplateCreateSpec write · create Adds facility: UUID4 | None, slug_value: SlugType, template_data: str, template_type: str, context: str
TemplateUpdateSpec write · update Identical to TemplateCreateSpec (pass subclass)
TemplateReadSpec read · list Base fields + slug_config: dict, slug: str, template_type: str, context: str (no template_data)
TemplateRetrieveSpec read · detail Extends read spec; adds nested facility (FacilityBareMinimumSpec) and template_data: str

Write-side validation and side effects (TemplateCreateSpec):

Read-side behaviour:

Methods & save behaviour

ReportUpload.save()

On create (no id) or when internal_name is empty, save() generates a random internal_name from uuid4() plus the current epoch. This intermediate name decouples the stored object from the human-readable name, so a storage or data leak never exposes PII in file names.

ReportUpload.get_extension()

Returns the dotted extension(s) parsed from internal_name (e.g. .pdf), or "" if none. Surfaced as the extension field in read specs.

ReportUpload.file_type (property)

Alias for report_type, kept for compatibility with S3FilesManager.

Template slug methods (inherited from SlugBaseModel)

API integration notes

Related

Source evidence

References are pinned to the private MANSOQ source repository. Repository access is required to open these links.