Skip to content

Allow providers to file results on behalf of other providers#88

Open
D3V41 wants to merge 12 commits intoMagentaHealth:release/2026-01-19from
openo-beta:feature/remove-flagged-providers-from-lab-updated-base-release
Open

Allow providers to file results on behalf of other providers#88
D3V41 wants to merge 12 commits intoMagentaHealth:release/2026-01-19from
openo-beta:feature/remove-flagged-providers-from-lab-updated-base-release

Conversation

@D3V41
Copy link
Copy Markdown
Collaborator

@D3V41 D3V41 commented Feb 23, 2026

Status Quo

Currently, a logged-in provider cannot file lab results on behalf of another provider.


Change

We have added functionality to allow a provider to file results on behalf of other providers.
(Example shown logged in as doctor oscardoc.)

Important

This PR is designed to minimize support burden on OpenOSP.

  • By default, this PR will NOT change any behaviour because the functionality defaults to "off" for all providers.
  • Only if providers actively turn on this feature within the user preferences will this option to "file on their behalf" become enabled.
  • Note that for Magenta, we decided to turn on this feature for all providers automatically in our production, without any significant complaints.

Main Workflow

Case 1: 0 or 1 provider attached to the lab:

  • Clicking Acknowledge opens the updated acknowledgement dialog, but no file options are shown.
    • image

Case 2: More than 1 provider attached to the lab:

  • Clicking Acknowledge opens a combined modal where the user selects providers to file for and adds an acknowledgement comment.

    • image
    • image
  • User adds comment and selects providers to file on their behalf, then clicks Submit.

    • image
  • After confirmation, the UI updates accordingly:

    • image

Preferences

Providers can configure the behavior under Preferences:

image
  1. Control the file dialog accordion
    Toggle the option:
    "Automatically offer to file results on behalf of other providers when acknowledging HL7 lab results"

    • If disabled, the accordion is collapsed by default when the modal opens:
      • image
    • If enabled, the accordion is expanded by default when the modal opens:
      • image
  2. Prevent others from filing on your behalf
    Turn off the option:
    "Allow other providers to file results on your behalf when they acknowledge HL7 lab results"

    • image

Additional Features

  1. Even if a user has already acknowledged a lab, they can still file it for other providers using the File for… button.

    • image
    • image
    • image
  2. If the provider has acknowledged version 1 and, after some time, version 2 is released.
    image

    • If the provider then acknowledges version 2:
    • Old behaviour: The status of version 1 was changed from A → F.
      • image
    • New behaviour: The status of version 1 is not changed if it is already A.
      • image

  - Add combined "Acknowledge/File Document" modal (comment + provider selection in one step)
  - Add separate "File Document" dialog for the "File for..." button (no comment needed)
  - Fix isLabNotFiledOrAckFlag not being set when logged-in provider appeared first in ackList
  - Improve code comments and add full flow documentation for the ack/filing feature
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Feb 23, 2026

Reviewer's Guide

Refactors the HL7 lab acknowledgement and filing UX so the main Acknowledge button now opens a combined comment+optional filing modal, introduces a dedicated File Document dialog for the "File for..." flow, and flips the isHl7OfferFileForOthers preference default from true to false with matching UI text and extensive inline documentation.

Sequence diagram for the combined acknowledge/file modal flow

sequenceDiagram
  actor Provider
  participant BrowserUI
  participant LabDisplayJS
  participant AppServer

  Provider->>BrowserUI: Click Acknowledge button
  BrowserUI->>LabDisplayJS: openFileDialog(false)

  alt isFileOnly true (File for button)
    LabDisplayJS->>LabDisplayJS: openFileOnlyDialog()
    LabDisplayJS->>BrowserUI: Open File Document dialog fileDialog
    Provider->>BrowserUI: Select providers and click Submit
    BrowserUI->>LabDisplayJS: fileDialogOkButton click
    LabDisplayJS->>LabDisplayJS: fileOnBehalfOfMultipleProviders(selectedProviders)
    loop For each selected provider
      LabDisplayJS->>AppServer: POST FileLabs.do with auto filing comment
      AppServer-->>LabDisplayJS: Filing result
    end
    LabDisplayJS->>BrowserUI: location.reload()
    BrowserUI->>Provider: Updated filing status for selected providers
  else isFileOnly false and isHl7OfferFileForOthers false and or no linked providers or skipComment true
    LabDisplayJS->>BrowserUI: Trigger tempAckBtn click
    BrowserUI->>AppServer: handleLab acknowledgeForm ackLab or getComment then ackLab
    AppServer-->>BrowserUI: Lab acknowledged
    BrowserUI-->>Provider: Lab status Acknowledged
  else isFileOnly false and isHl7OfferFileForOthers true and skipComment false
    LabDisplayJS->>LabDisplayJS: openCombinedAckFileDialog(false)
    LabDisplayJS->>BrowserUI: Open combinedAckFileDialog
    BrowserUI->>Provider: Show comment field and optional provider list
    Provider->>BrowserUI: Enter comment and optionally select providers
    Provider->>BrowserUI: Click Submit
    BrowserUI->>LabDisplayJS: combinedAckOkButton click
    LabDisplayJS->>LabDisplayJS: Collect comment and selectedProviders
    alt At least one provider selected
      LabDisplayJS->>LabDisplayJS: fileOnBehalfOfMultipleProviders(selectedProviders)
      loop For each selected provider
        LabDisplayJS->>AppServer: POST FileLabs.do with auto filing comment
        AppServer-->>LabDisplayJS: Filing result
      end
      LabDisplayJS->>AppServer: handleLab acknowledgeWithComment(comment segmentId)
      AppServer-->>LabDisplayJS: Lab acknowledged
      LabDisplayJS-->>BrowserUI: Update lab status
      BrowserUI-->>Provider: Lab acknowledged and filed for others
    else No providers selected
      LabDisplayJS->>AppServer: handleLab acknowledgeWithComment(comment segmentId)
      AppServer-->>LabDisplayJS: Lab acknowledged
      LabDisplayJS-->>BrowserUI: Update lab status
      BrowserUI-->>Provider: Lab acknowledged only
    end
  end
Loading

Flow diagram for openFileDialog routing and dialog behaviors

flowchart TD
  Start["Click Acknowledge or File for button"]
  CallOpen["Call openFileDialog(isFileOnly)"]
  IsFileOnly{Is isFileOnly true?}

  Start --> CallOpen --> IsFileOnly

  %% File for flow
  IsFileOnly -- Yes (File for) --> OpenFileOnly["openFileOnlyDialog()
Open File Document dialog fileDialog"]
  OpenFileOnly --> WaitSelectFile["Provider selects providers (ackProviderCheckbox)"]
  WaitSelectFile --> EnableOk["Enable fileDialogOkButton when at least one provider is checked"]
  EnableOk --> SubmitFileOnly["Click Submit in File Document dialog"]
  SubmitFileOnly --> FileMultiFileOnly["fileOnBehalfOfMultipleProviders(selectedProviders)"]
  FileMultiFileOnly --> ParallelCallsFileOnly["Parallel POST FileLabs.do calls for each provider"]
  ParallelCallsFileOnly --> ReloadFileOnly["location.reload()"]
  ReloadFileOnly --> EndFileOnly["Page shows updated filing status"]

  %% Acknowledge branch
  IsFileOnly -- No (Acknowledge) --> CheckSkipComment{Is skipAckComment true?}
  CheckSkipComment -- Yes --> TriggerTemp["Trigger tempAckBtn (ackLabFunc)"]
  TriggerTemp --> LegacyAck["Legacy flow: handleLab ackLab or getComment then ackLab"]
  LegacyAck --> EndLegacy["Lab acknowledged"]

  CheckSkipComment -- No --> CombinedDialogPath{isHl7OfferFileForOthers true?}

  CombinedDialogPath -- No --> TriggerTemp2["Trigger tempAckBtn (no combined modal)"]
  TriggerTemp2 --> LegacyAck

  CombinedDialogPath -- Yes --> OpenCombined["openCombinedAckFileDialog(false)
Open Acknowledge/File Document modal"]
  OpenCombined --> PrefillComment["Prefill combinedAckComment from existing comment (if any)"]
  PrefillComment --> OptionalAccordion["Optional accordion: show providers if eligibleProviderCount > 0"]
  OptionalAccordion --> ProviderInput["Provider enters comment and optionally selects providers"]
  ProviderInput --> SubmitCombined["Click Submit in combined modal"]

  SubmitCombined --> HasProviders{Any providers selected?}

  HasProviders -- No --> AckOnly["acknowledgeWithComment(comment segmentId)
handleLab ackLab"]
  AckOnly --> EndAckOnly["Lab acknowledged only"]

  HasProviders -- Yes --> FileMultiCombined["fileOnBehalfOfMultipleProviders(selectedProviders)"]
  FileMultiCombined --> ParallelCallsCombined["Parallel POST FileLabs.do calls for each provider"]
  ParallelCallsCombined --> AckAfterFile["acknowledgeWithComment(comment segmentId)
handleLab ackLab"]
  AckAfterFile --> EndCombined["Lab acknowledged and filed for selected providers"]
Loading

File-Level Changes

Change Details Files
Split the acknowledge/file flows into a combined acknowledge+optional-file modal and a dedicated file-only dialog, with clear routing and shared filing logic.
  • Reworked openFileDialog() into an entry point that routes to openFileOnlyDialog() for the "File for..." button and openCombinedAckFileDialog() for the main Acknowledge button, honouring skip-comment behaviour.
  • Implemented openFileOnlyDialog() to show a "File Document" dialog where the user can select providers, enabling the OK button only when at least one provider is checked, and then calling fileOnBehalfOfMultipleProviders(selectedProviders) followed by a page reload.
  • Implemented openCombinedAckFileDialog() to show a new "Acknowledge/File Document" modal with a comment field and optional provider list, handling both acknowledge-only and acknowledge+file flows in one submit action.
  • Added acknowledgeWithComment() helper to write the comment into the acknowledgement form and trigger handleLab() with the ackLab action.
src/main/webapp/lab/CA/ALL/labDisplay.jsp
Centralized and hardened the "file on behalf" logic so both dialogs share a Promise-based multi-provider filing implementation with better error handling and comments.
  • Refactored fileOnBehalfOfMultipleProviders() to accept an explicit selectedProviders array, reject early when empty, and run all FileLabs.do AJAX requests in parallel via Promise.allSettled.
  • Updated provider name resolution to look up from both combinedAckProviderName and ackProviderName elements, supporting both dialogs.
  • Documented createFilingComment() and fileOnBehalfOfMultipleProviders() with detailed comments about generated comment format, parallel execution, and failure handling.
  • Removed the global doFileOnBehalfOfProviders flag and its associated branching, simplifying call sites to rely solely on the Promise contract.
src/main/webapp/lab/CA/ALL/labDisplay.jsp
Introduced the combined modal UI, accordion-based optional filing section, and CSS to visually integrate the new dialogs.
  • Added the #combinedAckFileDialog markup with a comment input and an optional accordion section listing eligible providers (excluding the logged-in provider and those already filed/acknowledged).
  • Within the accordion, added provider checkboxes that respect each provider's hl7AllowOthersFileForYou preference (disabled and greyed out when opted out) and a Select All checkbox wired to combinedAckProviderCheckbox elements.
  • Initialized a jQuery UI accordion (#combinedAckAccordion) that opens by default only if isHl7OfferFileForOthers is true and focused the comment field on open; wired Enter key in the comment field to trigger dialog submission.
  • Added CSS to give the dialogs a white background and box shadow, center the button pane for the combined dialog, style the primary Submit button, and normalize accordion header/content appearance and icon behaviour.
src/main/webapp/lab/CA/ALL/labDisplay.jsp
Clarified and tightened the acknowledge/file state handling and server-side flags used to decide when to show Acknowledge vs File for... and which providers are eligible for filing.
  • Refined ackFlag and isLabNotFiledOrAckFlag computation so ackFlag means the logged-in provider has acknowledged, while isLabNotFiledOrAckFlag tracks other linked providers that have not yet filed or acknowledged.
  • Set each ReportStatus.h7lAllowOthersFileForYou via providerManager.isHl7AllowOthersFileForYou() during ackList iteration so the UI can disable filing checkboxes for providers who opted out.
  • Updated button rendering comments and logic so when !ackFlag the Acknowledge button calls openFileDialog(false), and when ackFlag && isLabNotFiledOrAckFlag the "File for..." button is shown to launch the file-only dialog.
  • Moved and documented #tempAckBtn as a hidden fallback button used only when isHl7OfferFileForOthers is false, clarifying its relation to the skipComment preference and legacy flow.
src/main/webapp/lab/CA/ALL/labDisplay.jsp
Changed the default for the "offer to file for others" provider preference to be opt-in instead of opt-out, and synced the UI label text.
  • In ProviderManager2.isHl7OfferFileForOthers(), changed the Optional.orElse default from true to false and adjusted the method comment to match the new default.
  • Updated the helper text in setHl7LabResultPrefs.jsp from "(default: yes)" to "(default: no)" for the "Automatically offer to file results on behalf of other providers" switch.
src/main/java/ca/openosp/openo/managers/ProviderManager2.java
src/main/webapp/provider/setHl7LabResultPrefs.jsp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In the combined acknowledge/file modal, eligibleProviderCount is incremented for any non-self, non-F/A provider regardless of their hl7AllowOthersFileForYou setting, which means the accordion can appear even when all providers are disabled; consider basing the count only on providers who have actually allowed filing so the optional section is hidden when there are no selectable targets.
  • The CSS rules that style dialogs via .ui-dialog:has(#fileDialog) and .ui-dialog:has(#combinedAckFileDialog) rely on the :has() selector, which is not supported in some browsers; if you need broader compatibility, you may want to switch to a class-based approach applied in the dialog open callbacks instead of :has().
  • The openCombinedAckFileDialog(isFileOnly) function and its button logic include a code path for isFileOnly=true, but all callers currently invoke it only with false (file-only uses openFileOnlyDialog()), so you could simplify by removing the unused isFileOnly parameter/branches until you actually need combined file-only behaviour.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the combined acknowledge/file modal, `eligibleProviderCount` is incremented for any non-self, non-F/A provider regardless of their `hl7AllowOthersFileForYou` setting, which means the accordion can appear even when all providers are disabled; consider basing the count only on providers who have actually allowed filing so the optional section is hidden when there are no selectable targets.
- The CSS rules that style dialogs via `.ui-dialog:has(#fileDialog)` and `.ui-dialog:has(#combinedAckFileDialog)` rely on the `:has()` selector, which is not supported in some browsers; if you need broader compatibility, you may want to switch to a class-based approach applied in the dialog open callbacks instead of `:has()`.
- The `openCombinedAckFileDialog(isFileOnly)` function and its button logic include a code path for `isFileOnly=true`, but all callers currently invoke it only with `false` (file-only uses `openFileOnlyDialog()`), so you could simplify by removing the unused `isFileOnly` parameter/branches until you actually need combined file-only behaviour.

## Individual Comments

### Comment 1
<location path="src/main/webapp/lab/CA/ALL/labDisplay.jsp" line_range="1215-1226" />
<code_context>
+            const textEl = document.getElementById(providerNo + "_" + segmentId + "commentText");
+            jQuery("#combinedAckComment").val(textEl ? textEl.innerHTML : "");
+
+            // Persist isFileOnly on the dialog element so the checkbox change handler can read it
+            // without it needing to be in scope as a closure variable.
+            jQuery("#combinedAckFileDialog").data("isFileOnly", isFileOnly);
+
+            jQuery("#combinedAckFileDialog").dialog({
</code_context>
<issue_to_address>
**suggestion:** Remove unused isFileOnly dialog data or wire it up where needed

`isFileOnly` is written to `#combinedAckFileDialog` via `.data("isFileOnly", ...)` but never read. Since `openCombinedAckFileDialog` already uses the `isFileOnly` parameter directly, this looks redundant. Either remove the `.data(...)` call, or add the code that actually reads this value if a handler needs it.

```suggestion
        function openCombinedAckFileDialog(isFileOnly) {
            const segmentId = jQuery("#segmentID").val();

            // Pre-populate the comment field with any comment the provider has already saved for this lab.
            const textEl = document.getElementById(providerNo + "_" + segmentId + "commentText");
            jQuery("#combinedAckComment").val(textEl ? textEl.innerHTML : "");

            jQuery("#combinedAckFileDialog").dialog({
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +1215 to +1226
function openCombinedAckFileDialog(isFileOnly) {
const segmentId = jQuery("#segmentID").val();

// Pre-populate the comment field with any comment the provider has already saved for this lab.
const textEl = document.getElementById(providerNo + "_" + segmentId + "commentText");
jQuery("#combinedAckComment").val(textEl ? textEl.innerHTML : "");

// Persist isFileOnly on the dialog element so the checkbox change handler can read it
// without it needing to be in scope as a closure variable.
jQuery("#combinedAckFileDialog").data("isFileOnly", isFileOnly);

jQuery("#combinedAckFileDialog").dialog({
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: Remove unused isFileOnly dialog data or wire it up where needed

isFileOnly is written to #combinedAckFileDialog via .data("isFileOnly", ...) but never read. Since openCombinedAckFileDialog already uses the isFileOnly parameter directly, this looks redundant. Either remove the .data(...) call, or add the code that actually reads this value if a handler needs it.

Suggested change
function openCombinedAckFileDialog(isFileOnly) {
const segmentId = jQuery("#segmentID").val();
// Pre-populate the comment field with any comment the provider has already saved for this lab.
const textEl = document.getElementById(providerNo + "_" + segmentId + "commentText");
jQuery("#combinedAckComment").val(textEl ? textEl.innerHTML : "");
// Persist isFileOnly on the dialog element so the checkbox change handler can read it
// without it needing to be in scope as a closure variable.
jQuery("#combinedAckFileDialog").data("isFileOnly", isFileOnly);
jQuery("#combinedAckFileDialog").dialog({
function openCombinedAckFileDialog(isFileOnly) {
const segmentId = jQuery("#segmentID").val();
// Pre-populate the comment field with any comment the provider has already saved for this lab.
const textEl = document.getElementById(providerNo + "_" + segmentId + "commentText");
jQuery("#combinedAckComment").val(textEl ? textEl.innerHTML : "");
jQuery("#combinedAckFileDialog").dialog({

@D3V41 D3V41 changed the title Replace two-dialog ack flow with combined modal and default isHl7OfferFileForOthers to false Allow providers to file results on behalf of other providers Feb 23, 2026
…viders() with no args, which always rejected and blocked the acknowledge flow

  - Fix duplicate-ID DOM lookups by passing segmentId/labType as parameters through openFileDialog → openFileOnlyDialog/openCombinedAckFileDialog → fileOnBehalfOfMultipleProviders instead of reading #segmentID/#labType
  - Remove duplicate loggedInProviderNo/loggedInProviderName hidden inputs inside fileDialog loop that broke jQuery ID uniqueness
@lacarmen
Copy link
Copy Markdown

Closing this for now since there's still work to be done in the original branch.

@lacarmen lacarmen closed this Feb 27, 2026
@D3V41 D3V41 reopened this Mar 4, 2026
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