Skip to content

Report Rendering

The render pipeline turns a report record into a PDF. Two flavours exist:

  • Preview renders — unsigned PDFs produced on demand during review. Overwritten at reports/{slug}/ on each render.
  • Signed render — a single immutable PDF produced atomically by Approve-and-Sign and written to orders/{slug}/signed-report.pdf.

What the render consumes

Every render assembles a context dictionary from:

  1. The report itself — summary, status, signer, template type.
  2. The order (fetched from Miner over HTTP) — display id, priority, ordering provider and facility.
  3. The subject and samples associated with the order.
  4. The variant associations — each with its per-report snapshot, classification override, and curator notes.
  5. Project-scoped boilerplate — laboratory name, certifications, signoff block, annotation source dates.

This context is fed into the selected DOCX template (see Templates) and the DOCX is converted to PDF.

Variant table assembly

Variants on the report are grouped by tier and sorted using the shared flow_core.clinical.tier_sort_key. The expected ordering on the rendered PDF:

  1. Tier IA — FDA-approved / guideline-level evidence.
  2. Tier IB — strong clinical evidence.
  3. Tier II — potential clinical significance.
  4. Tier III — unknown significance (if explicitly included).
  5. Germline ACMG classifications in the hereditary template.
  6. Benign / Tier IV — only if manually added.

Each row shows:

  • Gene symbol (the ISEQ_REPORT_GENE_SYMBOL field preferred; falls back to ISEQ_GENES_NAMES).
  • HGVS cDNA and protein.
  • Zygosity (hereditary) or VAF (somatic).
  • Final classification.
  • Evidence references (NCCN, CKB, CIViC, FDA as applicable).

Preview render path

  1. Curator or approver clicks "Preview" or auto-triggers on a state change.
  2. Report service renders the DOCX against the current state.
  3. PDF is converted and uploaded to reports/{slug}/preview.pdf (or a versioned path).
  4. UI links to the rendered PDF.

Preview renders are not audited beyond the normal Report table updated_at. They are not attached to any report state transition.

Signed render path

The signed render is driven by the sign-off routes:

  1. GET /{report_id}/signoff/confirm-modal — opens the confirmation modal and kicks off an asynchronous preview render. Any stale preview state on the report is cleared first so the render always reflects the latest report data and signer profile.
  2. POST /{report_id}/signoff/prepare-pdf — re-run the render on demand (for example if the template was updated).
  3. GET /{report_id}/signoff/pdf-status — polled by the modal spinner until the preview finishes.
  4. POST /{report_id}/signoff/commit — atomic finalize:
    • Validate the report is approved or pending_review.
    • Re-render the PDF once into signed_pdf_path.
    • Upload to orders/{slug}/signed-report.pdf using admin credentials.
    • Set status = signed, signed_by, signed_at, signed_pdf_path.
    • Ask Miner to advance the order to completed.
    • Commit the whole transaction.
  5. GET /{report_id}/signoff/completed-modal — post-finalize popup with a link to download the signed PDF.

Between DOCX→PDF conversion and the GCS upload, the preview render also stamps the signer's display name, optional job title, and signature PNG onto the last-table placeholder on the final page — if the template contains one. Templates without a placeholder pass through unchanged. See Sign-off PDF — E-signature stamping for the profile requirements and failure handling.

Signed renders are immutable

The signed PDF path is written once by the atomic Approve-and-Sign commit. No subsequent render will overwrite it. Corrections require an amendment.

Failure handling

  • A render failure during preview leaves the report in its current state.
  • A render failure during sign-off rolls back the transaction; no PDF is written and the report status does not change.
  • If Miner rejects the order transition with 409 (already advanced), the signoff routine treats it as success and proceeds; any other error causes rollback.