Skip to content

Fix: missing staged meds when using save and print functionality with multiple different patient Rx related pages (Medications, Allergies) open - LEGACY BUG#75

Open
LiamStanziani wants to merge 16 commits intoMagentaHealth:release/2026-01-19from
openo-beta:bug/missing-meds-when-saving
Open

Conversation

@LiamStanziani
Copy link
Copy Markdown
Collaborator

@LiamStanziani LiamStanziani commented Feb 3, 2026

In this PR, I have fixed:

  • Missing meds when saving the staged meds (happens with multiple Rx sessions overwriting each other)
  • General code upgrades (Encoding, error handling, bugs with stash reset when overwriting isn't an issue)

I have tested this by:

  • Creating medications, searching for medications, having multiple instances of Rx tabs open, Save & Print functionality

Summary by Sourcery

Isolate prescription session data per patient to support multiple Medications tabs safely and improve robustness of Rx operations.

Bug Fixes:

  • Prevent missing or wrong medications when saving or viewing prescriptions while multiple patient tabs are open by scoping RxSessionBean per demographic and clearing stale stash data appropriately.
  • Handle invalid or missing prescription identifiers during quantity updates by returning structured error responses instead of failing silently.

Enhancements:

  • Introduce RxSessionFilter and client-side rxSessionInterceptor to consistently propagate demographicNo through forms, AJAX calls, and previews so the correct RxSessionBean is selected per request.
  • Refine demographic number handling across Rx actions and JSPs to parse and pass demographicNo explicitly and securely-encoded in URLs and form fields.
  • Simplify RxPrescriptionData logging for empty drug special values and improve logging and validation around demographic parsing and session lookup.

Documentation:

  • Add Javadoc documentation for new RxSessionBean session helpers and RxSessionFilter behavior explaining multi-patient tab support.

Summary by Sourcery

Isolate prescription session data per patient to support multiple concurrent Medications/Allergies tabs and make Rx operations more robust and secure.

Bug Fixes:

  • Prevent medications from going missing or being associated with the wrong patient when saving, printing, or previewing prescriptions across multiple patient tabs by scoping Rx session data per demographic.
  • Return clear JSON errors when updating prescription quantities with invalid or stale identifiers instead of failing silently or corrupting state.
  • Validate and safely parse demographic numbers in Rx actions and views to avoid crashes or misrouting of session state.

Enhancements:

  • Introduce RxSessionFilter and client-side rxSessionInterceptor to consistently propagate demographicNo so the correct per-patient RxSessionBean and Patient context are selected for each request.
  • Add helper methods on RxSessionBean for storing and retrieving per-patient session beans while maintaining backward compatibility with the legacy session key.
  • Propagate demographicNo through Rx-related JSPs, forms, iframes, and AJAX calls, and align Patient session swapping with the active demographic.
  • Improve logging around prescription drug special values to better surface potential data issues without redundant escaping logic.

…eeded for fixes to this issue when reproducing the workflow
…ate as needed for fixes to this issue when reproducing the workflow"

This reverts commit 8d3b9b7.
…providers, will need to update to iron out bugs and less memory usage
…working fully, but works for most actions inside of the Medications module
@LiamStanziani LiamStanziani self-assigned this Feb 3, 2026
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Feb 3, 2026

Reviewer's Guide

Scopes Rx prescription session state per patient via a new RxSessionFilter, per-patient RxSessionBean session keys, and a client-side rxSessionInterceptor so multiple Medications/Allergies tabs can coexist without overwriting each other, while tightening parameter parsing, error reporting, and logging.

Sequence diagram for multi-tab Rx request with RxSessionFilter and rxSessionInterceptor

sequenceDiagram
    actor User
    participant Browser
    participant RxJS as rxSessionInterceptor_js
    participant Filter as RxSessionFilter
    participant Struts as Struts2_and_RxAction
    participant Session as HttpSession
    participant Bean as RxSessionBean_per_patient

    User->>Browser: Open_Medications_tab_for_patient_123
    Browser->>RxJS: Load_page_and_scripts
    RxJS->>Browser: Set_currentDemographicNo_123

    User->>Browser: Click_Save_and_Print
    Browser->>RxJS: Trigger_AJAX_or_form_submit
    RxJS->>Browser: Attach_demographicNo=123_to_request

    Browser->>Filter: HTTP_request_with_demographicNo=123
    Filter->>Session: getAttribute(RxSessionBean_123)
    alt per_patient_bean_exists
        Session-->>Filter: Bean_for_123
        Filter->>Session: setAttribute(RxSessionBean, Bean_for_123)
    else no_per_patient_bean
        Filter->>Session: removeAttribute(RxSessionBean)
    end
    Filter->>Session: sync_Patient_attribute_for_123
    Filter->>Struts: chain_doFilter

    Struts->>Session: getAttribute(RxSessionBean)
    Struts-->>Bean: use_correct_patient_context
    Struts-->>Browser: Response_with_correct_staged_and_printed_meds
Loading

Updated class diagram for RxSessionBean and RxSessionFilter multi-patient support

classDiagram
    class RxSessionBean {
        <<Serializable>>
        -Logger logger
        -String SESSION_KEY_PREFIX
        -String LEGACY_SESSION_KEY
        -String providerNo
        -int demographicNo
        +static String getSessionKey(int demographicNo)
        +static RxSessionBean getFromSession(HttpSession session, int demographicNo)
        +static RxSessionBean getFromSession(HttpServletRequest request, int demographicNo)
        +static void saveToSession(HttpSession session, RxSessionBean bean)
        +static void saveToSession(HttpServletRequest request, RxSessionBean bean)
        +String getProviderNo()
        +void setProviderNo(String providerNo)
        +int getDemographicNo()
        +void setDemographicNo(String RHS)
    }

    class RxSessionFilter {
        <<Filter>>
        -Logger logger
        -String LEGACY_KEY
        -String PATIENT_KEY
        +void init(FilterConfig filterConfig)
        +void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        +void destroy()
        -static int parseDemographicNo(String param)
    }

    class RxPatientData {
    }

    class RxPatientData_Patient {
        +int getDemographicNo()
        +Object getDemographic()
    }

    class LoggedInInfo {
        +static LoggedInInfo getLoggedInInfoFromSession(HttpServletRequest request)
    }

    class RxWriteScript2Action {
        -HttpServletRequest request
        -HttpServletResponse response
        -RxSessionBean bean
        +String updateDrug()
        +int getDemographicNo()
        +void setDemographicNo(String RHS)
    }

    class RxShowAllergy2Action {
        -HttpServletRequest request
        +String execute()
    }

    class RxChoosePatient2Action {
        -HttpServletRequest request
        +String execute()
    }

    class CaseManagementView2Action {
        -HttpServletRequest request
        +String view()
    }

    RxSessionFilter --> RxSessionBean : selects_and_swaps_per_patient_beans
    RxSessionFilter --> RxPatientData_Patient : loads_Patient_from_demographicNo
    RxSessionFilter --> LoggedInInfo : reads_logged_in_user
    RxPatientData_Patient ..> RxPatientData : nested_type

    RxWriteScript2Action --> RxSessionBean : uses_bean_from_session
    RxShowAllergy2Action --> RxSessionBean : uses_bean_from_session
    RxChoosePatient2Action --> RxSessionBean : creates_and_saves_per_patient_bean
    CaseManagementView2Action --> RxSessionBean : creates_and_saves_per_patient_bean
Loading

File-Level Changes

Change Details Files
Introduce per-patient RxSessionBean storage and server-side filter to select the correct session bean and patient context per request.
  • Add static helpers on RxSessionBean to compute per-patient session keys, retrieve, and save beans while preserving the legacy RxSessionBean key for backward compatibility.
  • Implement RxSessionFilter to read demographicNo from requests, swap the correct per-patient RxSessionBean into the legacy session key, update the Patient session attribute, and avoid cross-patient leakage if no matching bean exists.
  • Register RxSessionFilter in web.xml for /oscarRx/*, CaseManagementView.do, and messenger/generatePreviewPDF.jsp so all Rx flows get the correct session bean.
  • Update various actions and JSPs (RxShowAllergy2Action, RxChoosePatient2Action, CaseManagementView2Action, StaticScript2.jsp, generatePreviewPDF.jsp) to use RxSessionBean.saveToSession instead of writing the legacy key directly and to validate/parse demographic numbers more carefully.
src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java
src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java
src/main/webapp/WEB-INF/web.xml
src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java
src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java
src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java
src/main/webapp/oscarRx/StaticScript2.jsp
src/main/webapp/messenger/generatePreviewPDF.jsp
Propagate demographicNo through Rx JSPs, previews, and forms and introduce a client-side interceptor so all Rx-related requests carry patient context.
  • Add currentDemographicNo JS variable and include rxSessionInterceptor.js in key Rx JSPs (SearchDrug3.jsp, ViewScript.jsp, ViewScript2.jsp) to ensure AJAX, fetch, and Rx forms automatically include demographicNo.
  • Update hidden fields and URLs in SearchDrug3.jsp, ViewScript.jsp, and ViewScript2.jsp to pass demographicNo using proper OWASP Encode-based encoding for HTML attributes, JavaScript, and URI components.
  • Ensure preview iframes (Preview.jsp, Preview2.jsp) and clearPending forms include demographicNo so the correct RxSessionBean is used when saving/printing or clearing staged prescriptions.
src/main/webapp/oscarRx/SearchDrug3.jsp
src/main/webapp/oscarRx/ViewScript.jsp
src/main/webapp/oscarRx/ViewScript2.jsp
src/main/webapp/oscarRx/js/rxSessionInterceptor.js
Strengthen request parameter handling and error reporting in Rx actions to avoid silent failures and bad input.
  • Change RxWriteScript2Action.setDemographicNo to accept a String and safely parse it with NumberFormatException handling, aligning with Struts2 parameter binding.
  • In RxWriteScript2Action.updateDrug, validate randomId, return HTTP 400 with a JSON error body for invalid IDs or missing stash entries, and log detailed error messages using OWASP Encode for safe logging.
  • Add demographicNo parsing and validation with error logging in RxShowAllergy2Action and RxChoosePatient2Action, returning failure/redirect on invalid values instead of throwing.
  • In generatePreviewPDF.jsp, validate demographic_no and throw a ServletException if it cannot be parsed to an int before constructing the RxSessionBean.
src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java
src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java
src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java
src/main/webapp/messenger/generatePreviewPDF.jsp
Tighten logging and minor Rx-related JSP behaviors while removing obsolete encoding.
  • Simplify RxPrescriptionData logging when drug special values are null/short, logging the raw length instead of doing SQL escaping and redundant checks.
  • Minor JSP cleanups such as using demoNo instead of patient.getDemographicNo where appropriate, adjusting form names/IDs for clearPending handlers, and whitespace tweaks.
  • Use OWASP Encode for JavaScript and HTML attribute contexts in Rx JSPs to reduce XSS risk when emitting demographic numbers and other dynamic values.
src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java
src/main/webapp/oscarRx/SearchDrug3.jsp
src/main/webapp/oscarRx/ViewScript.jsp
src/main/webapp/oscarRx/ViewScript2.jsp
src/main/webapp/oscarRx/ListDrugs.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

…icNo and there was no per-patient session bean for the connected demographicNo, meaning a bean was never created in the first place
@LiamStanziani LiamStanziani marked this pull request as ready for review February 3, 2026 16:40
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 left some high level feedback:

  • In RxSessionFilter.parseDemographicNo, an invalid (non-numeric) demographicNo parameter causes a fallback to the legacy bean instead of being treated as an explicit mismatch; consider treating invalid values the same as an explicit demographic change (e.g., clearing the legacy bean) to avoid potential cross-patient leakage when a bad param is sent.
  • The form auto-wiring in rxSessionInterceptor.js only adds demographicNo when the form action contains '/oscarRx/' or 'Rx'; verify that all prescription-related forms (including newer endpoints like clearPending.do or others without 'Rx' in the path) match these heuristics, or broaden the matching criteria to avoid missing demographicNo on some flows.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In RxSessionFilter.parseDemographicNo, an invalid (non-numeric) demographicNo parameter causes a fallback to the legacy bean instead of being treated as an explicit mismatch; consider treating invalid values the same as an explicit demographic change (e.g., clearing the legacy bean) to avoid potential cross-patient leakage when a bad param is sent.
- The form auto-wiring in rxSessionInterceptor.js only adds demographicNo when the form action contains '/oscarRx/' or 'Rx'; verify that all prescription-related forms (including newer endpoints like clearPending.do or others without 'Rx' in the path) match these heuristics, or broaden the matching criteria to avoid missing demographicNo on some flows.

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.

@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

Ticket link for manual testing: openo-beta#2237

@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

@lacarmen

Deval has reviewed this PR, see the comment from the other PR (openo-beta#2261)

image

@LiamStanziani LiamStanziani changed the title Fix: missing meds when saving Fix: missing meds when saving - LEGACY BUG Feb 6, 2026
@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

LiamStanziani commented Feb 26, 2026

I'm a bit worried that this might still persist when looking at recent messages about this issue, I think I will do some extra testing soon to see if I can trigger the issue in other circumstances, which are more plausible for users to run into (testing with custom instructions in different ways, seeing if that can trigger the issue as explained)

@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

LiamStanziani commented Mar 11, 2026

For now, I think I will set this PR (and its openo-beta equivilant) to draft, I need to update some parts (remove added prototype usage) and will run some investigations (see previous comment) that might cause more updates later on, I think it's best this sits for a bit before more review

@LiamStanziani LiamStanziani changed the title Fix: missing meds when saving - LEGACY BUG Fix: missing staged meds when using save and print functionality with multiple different patient Rx related pages (Medications, Allergies) open - LEGACY BUG Mar 17, 2026
  - Move RxSessionFilter after auth filters in web.xml to prevent
    unauthenticated session mutation
  - Add Patient session attribute swapping to RxSessionFilter, removing
    redundant manual lookups in ListDrugs.jsp
  - Support both demographicNo and demographic_no params in filter
  - Fix fetch interceptor to preserve Request object properties
  - Revert generatePreviewPDF.jsp bean read to use filter-swapped legacy key
  - Remove deferred stash clearing fix (resetStashAndClose) from
    ViewScript.jsp and ViewScript2.jsp
  - Revert RxSessionFilter mappings to before Struts2 in web.xml.
    Struts2 short-circuits chain.doFilter() for .do action URLs,
    so placing the filter after Struts2 prevented bean swapping
    for actions like RxWriteScript2Action. Auth for .do URLs is
    handled by SecurityInfoManager inside actions, not LoginFilter.
  - Simplify CaseManagementView2Action and RxChoosePatient2Action
    bean setup — remove redundant getFromSession lookups since
    the filter handles per-request swapping.
  - Restore RxShowAllergy2Action's original provider/demographic
    match check to preserve existing bean state (stash, view).
  - All three actions now use saveToSession instead of setAttribute
    for per-patient key storage.
…pt to new save to session method usual setup
@LiamStanziani LiamStanziani marked this pull request as ready for review March 17, 2026 21:20
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 2 issues, and left some high level feedback:

  • The rxSessionInterceptor.js fetch/jQuery/Prototype interception currently appends demographicNo to all URLs, including non-Rx and potentially third‑party endpoints; consider restricting this behavior to same-origin Rx URLs (e.g., paths under /oscarRx/) to avoid leaking patient identifiers to unrelated requests.
  • Now that RxSessionBean.getFromSession/saveToSession exist, some places (e.g., RxShowAllergy2Action, JSPs like generatePreviewPDF.jsp and StaticScript2.jsp) still manually work with the "RxSessionBean" session attribute; consider refactoring them to consistently use the helper methods to reduce duplication and future session-handling bugs.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `rxSessionInterceptor.js` fetch/jQuery/Prototype interception currently appends `demographicNo` to all URLs, including non-Rx and potentially third‑party endpoints; consider restricting this behavior to same-origin Rx URLs (e.g., paths under `/oscarRx/`) to avoid leaking patient identifiers to unrelated requests.
- Now that `RxSessionBean.getFromSession`/`saveToSession` exist, some places (e.g., `RxShowAllergy2Action`, JSPs like `generatePreviewPDF.jsp` and `StaticScript2.jsp`) still manually work with the `"RxSessionBean"` session attribute; consider refactoring them to consistently use the helper methods to reduce duplication and future session-handling bugs.

## Individual Comments

### Comment 1
<location path="src/main/webapp/oscarRx/js/rxSessionInterceptor.js" line_range="81-89" />
<code_context>
+    }
+
+    // Intercept fetch API
+    if (typeof window.fetch === 'function') {
+        var originalFetch = window.fetch;
+        window.fetch = function(url, options) {
+            var isRequest = url instanceof Request;
+            var urlStr = isRequest ? url.url : String(url);
+            if (urlStr.indexOf('demographicNo=') === -1) {
+                var separator = urlStr.indexOf('?') === -1 ? '?' : '&';
+                var newUrl = urlStr + separator + 'demographicNo=' + encodeURIComponent(demoNo);
+                if (isRequest) {
+                    url = new Request(newUrl, url);
+                } else {
</code_context>
<issue_to_address>
**issue (bug_risk):** Rebuilding Request objects in the fetch interceptor is incorrect and may throw at runtime.

When `url` is a `Request`, calling `new Request(newUrl, url)` is invalid: the second argument must be a `RequestInit`, not a `Request`. This can cause runtime errors or drop properties (method, headers, body, etc.), and behavior may vary across browsers. Either:
- Only modify the URL when `url` is a string and leave `Request` objects unchanged, or
- Properly clone the `Request` by constructing `new Request(newUrl, { method: url.method, headers: url.headers, body: url.body, credentials: url.credentials, cache: url.cache, redirect: url.redirect, referrer: url.referrer })` (or equivalent) so all important fields are preserved.
</issue_to_address>

### Comment 2
<location path="src/main/webapp/oscarRx/js/rxSessionInterceptor.js" line_range="12" />
<code_context>
+ *
+ * @since 2026-01-30
+ */
+(function() {
+    'use strict';
+
</code_context>
<issue_to_address>
**issue (complexity):** Consider refactoring the interceptor into smaller per-framework functions, scoping fetch interception to Rx URLs, and possibly removing redundant Ajax.Updater wrapping to make the module easier to understand and maintain.

You can keep all behavior but reduce complexity and coupling a bit with some small restructurings.

### 1. Split per‑framework interception into small functions

Right now everything sits in a single IIFE body. You can move each framework’s interception into its own function and just invoke them, which makes the file easier to scan and reason about without changing behavior:

```js
(function () {
  'use strict';

  if (typeof currentDemographicNo === 'undefined' || !currentDemographicNo) return;
  var demoNo = String(currentDemographicNo);

  function hasDemographicNo(params) { /* existing implementation */ }
  function addDemographicNo(params) { /* existing implementation */ }

  function interceptPrototypeAjax() {
    if (typeof Ajax === 'undefined') return;

    if (Ajax.Request && Ajax.Request.prototype.initialize) {
      var origRequestInit = Ajax.Request.prototype.initialize;
      Ajax.Request.prototype.initialize = function (url, options) {
        options = options || {};
        if (!hasDemographicNo(options.parameters)) {
          options.parameters = addDemographicNo(options.parameters);
        }
        if (options.postBody && !hasDemographicNo(options.postBody)) {
          options.postBody = addDemographicNo(options.postBody);
        }
        origRequestInit.call(this, url, options);
      };
    }

    if (Ajax.Updater && Ajax.Updater.prototype.initialize) {
      var origUpdaterInit = Ajax.Updater.prototype.initialize;
      Ajax.Updater.prototype.initialize = function (container, url, options) {
        options = options || {};
        if (!hasDemographicNo(options.parameters)) {
          options.parameters = addDemographicNo(options.parameters);
        }
        origUpdaterInit.call(this, container, url, options);
      };
    }
  }

  function interceptFetch() {
    if (typeof window.fetch !== 'function') return;

    var originalFetch = window.fetch;
    window.fetch = function (url, options) {
      var isRequest = url instanceof Request;
      var urlStr = isRequest ? url.url : String(url);

      if (urlStr.indexOf('demographicNo=') === -1) {
        var separator = urlStr.indexOf('?') === -1 ? '?' : '&';
        var newUrl = urlStr + separator + 'demographicNo=' + encodeURIComponent(demoNo);
        url = isRequest ? new Request(newUrl, url) : newUrl;
      }

      return originalFetch.call(this, url, options || {});
    };
  }

  function interceptJQueryAjax() {
    if (typeof jQuery === 'undefined') return;

    jQuery.ajaxPrefilter(function (options) {
      if (!hasDemographicNo(options.data)) {
        options.data = addDemographicNo(options.data);
      }
    });
  }

  function injectDemographicIntoForms() {
    function processAllForms() {
      var forms = document.querySelectorAll('form');
      for (var i = 0; i < forms.length; i++) {
        var form = forms[i];
        if (form.querySelector('input[name="demographicNo"]')) continue;
        var action = form.getAttribute('action') || '';
        if (action.indexOf('/oscarRx/') === -1 && action.indexOf('Rx') === -1 && action !== '') continue;
        var input = document.createElement('input');
        input.type = 'hidden';
        input.name = 'demographicNo';
        input.value = demoNo;
        form.appendChild(input);
      }
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', processAllForms);
    } else {
      processAllForms();
    }
  }

  // Single entry point
  interceptPrototypeAjax();
  interceptFetch();
  interceptJQueryAjax();
  injectDemographicIntoForms();
})();
```

This keeps all logic and helpers exactly as you have them, but limits the “everything in one place” effect that makes the module feel dense.

### 2. Restrict global `fetch` interception to Rx URLs (optional tightening)

If most of the *intended* usage is Rx‑related, you can keep functionality while reducing cross‑cutting impact and complexity by only touching Rx URLs. That also makes the behavior easier to reason about:

```js
function interceptFetch() {
  if (typeof window.fetch !== 'function') return;

  var originalFetch = window.fetch;
  window.fetch = function (url, options) {
    var isRequest = url instanceof Request;
    var urlStr = isRequest ? url.url : String(url);

    // Only touch Rx‑related endpoints
    if (urlStr.indexOf('/oscarRx/') === -1 && urlStr.indexOf('Rx') === -1) {
      return originalFetch.call(this, url, options || {});
    }

    if (urlStr.indexOf('demographicNo=') === -1) {
      var separator = urlStr.indexOf('?') === -1 ? '?' : '&';
      var newUrl = urlStr + separator + 'demographicNo=' + encodeURIComponent(demoNo);
      url = isRequest ? new Request(newUrl, url) : newUrl;
    }

    return originalFetch.call(this, url, options || {});
  };
}
```

This doesn’t remove any Rx behavior; it just avoids rewriting unrelated `fetch` calls, which simplifies the mental model of what the interceptor is doing.

### 3. Re‑evaluate necessity of `Ajax.Updater` interception

Since `Ajax.Updater` delegates to `Ajax.Request`, you might find the `Ajax.Updater.prototype.initialize` wrapper redundant in your Prototype version. If, after verifying in your environment, `Ajax.Request` interception already covers all `Updater` cases, you can safely delete just this block:

```js
if (typeof Ajax !== 'undefined' && Ajax.Updater && Ajax.Updater.prototype.initialize) {
  var origUpdaterInit = Ajax.Updater.prototype.initialize;
  Ajax.Updater.prototype.initialize = function (container, url, options) {
    options = options || {};
    if (!hasDemographicNo(options.parameters)) {
      options.parameters = addDemographicNo(options.parameters);
    }
    origUpdaterInit.call(this, container, url, options);
  };
}
```

That would remove some duplication and one interception path without changing behavior.
</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.

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.

1 participant