Uploading externally generated Cytology PDF reports in Results view and routing them through Validation

Hi Everyone,

We’re implementing OpenELIS Global [version, e.g. 3.2.2] integrated with [EMR, e.g. OpenMRS 3 via FHIR / Lab on FHIR], and we’d like the community’s input on a Cytology workflow.

Scenario

  • Cytology tests are ordered in OpenELIS (from the EMR or through order entry), and samples are received and accessioned as normal.
  • The cytology report itself is produced outside OpenELIS (by [e.g. a digital pathology system, a reporting tool, or a manual report]) as a PDF.
  • The lab wants to upload that PDF against the test in the Results view, then run the standard validation flow. The validator would review the PDF and accept or reject it before release.
  • After validation, the report should appear on the patient report and flow to the EMR.

What we’re considering

  1. Checking whether the Cytology/Pathology program modules in 3.x already support attaching external reports, or could be adapted to.
  2. If not, a small extension that:
    • adds a test-level flag such as “requires report attachment”,
    • adds an attachment table linked to analysis, with versioning so a rejected result keeps its earlier file,
    • adds an upload control in Results entry and a “View report” action in Validation,
    • merges the PDF into the Jasper patient report (for example with PDFBox),
    • adds the PDF to the FHIR DiagnosticReport.presentedForm (as a Binary reference) on finalization so the EMR receives it.
  3. Keeping a coded summary result (such as a Bethesda category) alongside the PDF so the data stays reportable.

Questions for the community

  1. Has anyone already implemented result attachments or external report uploads in OpenELIS? If so, is there a branch, PR, or fork we could look at?
  2. Does the current Cytology or Pathology module have file-attachment functionality we should reuse instead of building something new?
  3. Is there a preferred design from the core team, for example where attachments should be stored (database vs filesystem) or which entity they should link to?
  4. For EMR integration, has anyone sent PDFs to OpenMRS through DiagnosticReport.presentedForm or DocumentReference? How did you handle it on the OpenMRS side (complex Obs, the Attachments app, etc.)?
  5. Would the maintainers be open to this as an upstream contribution? We’d rather build it in a way that can be merged than maintain a fork.

Any guidance, pointers to existing work, or lessons learned would be much appreciated. We’re happy to share our design and code back with the community.

1 Like

Hi @Bhupesh_Gupta thanks for the detailed write-up. A good part of what you describe is already in OpenELIS 3.2.x, so here’s what exists today, what’s missing, and how we’d suggest building the rest.

1. How result attachments work today

Attachments are stored in the database (order_attachment table). Each file belongs to an order and can also be linked to a specific test. Accepted formats are PDF, JPG, PNG and TIFF, up to 10 MB per file.

Where files can be uploaded

Screen Available from What the upload is linked to
Order entry 3.2.2 The whole order (up to 5 files)
Results entry 3.2.2 That specific test (and result component, if the test has several)

Where files are visible

  • Files uploaded at order entry appear on every test of that order, in both Results entry and Validation. They carry an “Order” tag.
  • Files uploaded in Results entry appear only on that test, in both Results entry and Validation. They carry a “Results” tag.
  • Every file can be opened in the browser or downloaded from those screens.

Validation (3.2.3 and later)

The validation review panel for each test has an Attachments section. It lists the order’s files plus that test’s files, so the validator can open the PDF before accepting or rejecting the result. If you’re on 3.2.2, upgrade to 3.2.3 to get this.

So for your scenario, the external PDF can be uploaded either at order entry (then it’s visible on all tests) or against the cytology test in Results entry (then it’s visible on that test only). Either way the validator sees it during validation.

2. Pathology and Cytology modules

OpenELIS also has dedicated Pathology and Cytology modules (plus Immunohistochemistry), each with its own case view and workflow.

Pathology

  • Workflow statuses: Accessioned, Grossing, Decalcification, Processing, Embedding, Microtomy, Staining, Coverslipping & QC, Ready for Pathologist, Under Pathologist Review, Completed.
  • Tracks blocks and slides, and slide images can be uploaded.
  • Reports section: add a Pathology Report and either generate it from OpenELIS or upload an external PDF/JPEG/PNG.
  • Coded conclusions: dictionary-coded values, plus free text.
  • The pathologist marks the case “Ready for release”, which completes it.

Cytology

  • Workflow statuses: Preparing slides, Screening, Ready for Cytopathologist, Completed.
  • Tracks slides, and slide images can be uploaded.
  • Reports section: add a report (Cervical/Vaginal Cytology or Pap Smear) and either generate it or upload an external PDF/JPEG/PNG.
  • Coded diagnoses: dictionary-backed categories (epithelial cell abnormality, non-neoplastic variations, reactive changes, organisms, other) plus specimen adequacy. This covers your “coded summary alongside the PDF” requirement.

Important difference from the standard flow: neither module goes through the standard Validation page. When the case is completed, the test is finalized directly with a “See report” result, and the pathologist or cytopathologist sign-off acts as the review step.

Which to use

  • If pathologist/cytopathologist sign-off is your review step, the Pathology or Cytology module already supports uploading the external report.
  • If you need the standard Validation accept/reject step, order the test as a regular test and use the attachments described in section 1. Record the coded summary (for example a Bethesda category) as a dictionary result on the same test.

3. What’s missing today

These are the gaps we’d welcome contributions for:

  1. Patient report: attachments aren’t merged into the Jasper patient report yet.
  2. Sending to the EMR (FHIR): OpenELIS doesn’t yet put PDFs in DiagnosticReport.presentedForm or send a DocumentReference, so the PDF doesn’t reach the EMR. Currently completing a Pathology or Cytology case also doesn’t trigger the FHIR result push that the Results/Validation flow does.
  3. “Requires report attachment” flag: there’s no test-level setting that blocks validation until a report is attached.
  4. Version history: deleted files are soft-deleted (kept in the database), but nothing links a replacement file to the one it replaced. That’s the missing piece for “a rejected result keeps its earlier file”.

4. Design considerations

  • Reuse the existing attachment table. Please build on order_attachment instead of adding a new table. It already links a file to an order, a test and a result component.
  • Storage: keep files in the database, as today, so attachments are covered by the same backups and audit as the rest of the lab data.
  • Versioning: a small “supersedes” link on order_attachment would give you history across reject and re-upload without changing how files are shown.
  • Validation gate: the “requires attachment” flag fits naturally as a test setting, checked when results are saved and validated.
  • Patient report: merge the attached PDFs after the generated Jasper report, and only for tests that have been validated and released.
  • FHIR: put the PDF in presentedForm on the test’s existing DiagnosticReport (inline or as a Binary reference), sent when the result is finalized. That fits the current FHIR model better than a separate resource.
  • Pathology/Cytology: if you want these modules covered too, their completion step would need the same FHIR push and report attachment handling, so the EMR gets the same payload whichever workflow the lab uses.
  • OpenMRS side: Sending PDFs to OpenMRS is not supported but probably OpenMRS could better handle this as a Complex Obs

5. Contributing upstream

Yes, this would be welcome upstream, and it’s much better than maintaining a fork. The easiest path:

  1. Open a GitHub issue (or Jira ticket) describing your design for the gaps in section 3.
  2. We agree on the approach there before you write code.
  3. Open your pull requests against the develop branch, ideally one per gap.