User Tools

Site Tools


openemr_manual

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
openemr_manual [2026/05/06 16:39] – Add MBI Finder mutex / payers fix to v2.1.2 changelog brad.sharpopenemr_manual [2026/05/22 22:34] (current) – Fix Method 2: OE Manage Modules has no zip-upload UI for custom modules — extract zip and drop files into custom_modules/ via SFTP instead brad.sharp
Line 37: Line 37:
   * An active ClaimRev account with API credentials   * An active ClaimRev account with API credentials
  
-==== Download ====+==== Choose Your Install Method ====
  
-Two builds are available — pick the one that matches your OpenEMR major version. The 7.x build adds small compatibility shim layer for classes introduced in 8.x; on 8.x installs that layer is not needed and not included.+The ClaimRev Connect module is published on Packagist as ''claimrevolution/oe-module-claimrev-connect''Starting with v2.1.3 **single build** runs on both OpenEMR 7.x and OpenEMR 8.x — runtime compatibility shims in ''src/Compat/'' activate only when the host core lacks the newer APIs. Pick the install method that matches your environment.
  
-**Current Version: 2.1.2**+**Current Version: 2.1.3**
  
-~~NOTOC~~+=== Method 1: Composer (Recommended) ===
  
-=== For OpenEMR 8.x ===+If you have CLI access to your OpenEMR install:
  
-| **Module File** | {{ :oe-module-claimrev-connect-v2.1.2-openemr-8.zip | OpenEMR 8.x Module}} | +<code bash> 
-| **Compatible with** | OpenEMR 8.0 and later | +cd /path/to/openemr 
-| **Released** | May 6, 2026 | +composer require claimrevolution/oe-module-claimrev-connect:^2.1 
-| **Notes** | Targets OpenEMR 8.x natively (no compatibility shims) |+sudo systemctl reload php-fpm   # or restart Apache 
 +</code>
  
-=== For OpenEMR 7.x ===+Composer downloads the latest v2.1.x release, drops it into ''interface/modules/custom_modules/oe-module-claimrev-connect/'', and updates the autoloader. Continue with [[#Activation|Activation]] below.
  
-**Module File** | {{ :oe-module-claimrev-connect-v2.1.2-openemr-7.zip | OpenEMR 7.x Module}} | +To **update** the module later:
-| **Compatible with** | OpenEMR 7.0.0 through 7.x | +
-| **Released** | May 6, 2026 | +
-| **Notes** | Includes the ''src/Compat/'' shim layer for ''OEGlobalsBag'', ''ServiceContainer'', and ''CryptoInterface''; ''CsrfHelper'' detects which ''CsrfUtils'' signature is in use at runtime |+
  
-**Changelog**: See [[#Changelog|Changelog]] below.+<code bash> 
 +composer update claimrevolution/oe-module-claimrev-connect 
 +sudo systemctl reload php-fpm 
 +</code>
  
-**Note:** If you do not yet have a ClaimRev account, visit [[https://www.claimrev.com|claimrev.com]] or contact us at [[mailto:sales@claimrev.com|sales@claimrev.com]] to get started.+=== Method 2Manual File Drop (Shared Hosting No CLI) ===
  
-==== Installation Steps ====+OpenEMR's //Manage Modules// page does not have a zip-upload feature for custom modules — it scans ''interface/modules/custom_modules/'' on every page load and lists whatever directories it finds. For installs without CLI access (shared hosting, restricted environments), drop the files into place via SFTP/FTP:
  
-  - Download the appropriate zip for your OpenEMR version from the section above+  - Download the current release zip from [[https://github.com/claimrevolution/oe-module-claimrev-connect/releases|the GitHub releases page]]
-  - Log into OpenEMR as an administrator+  - Unzip it locally. You should see a folder named ''oe-module-claimrev-connect/'' containing ''composer.json'', ''info.txt'', ''src/'', ''public/'', ''templates/'', etc
-  - Navigate to **Modules > Manage Modules**+  - Connect to your OpenEMR server with SFTP, FTP, or your hosting control panel's file manager
-  - Click the **Install** tabthen click **Upload Module** and select the downloaded zip file+  - Upload the entire ''oe-module-claimrev-connect/'' folder into ''interface/modules/custom_modules/'' so the resulting path is ''interface/modules/custom_modules/oe-module-claimrev-connect/composer.json'' (and so on for the other files). 
-  - After upload completes, find **ClaimRev Connect** in the module list and click **Install**+  - Continue with [[#Activation|Activation]] below — OpenEMR will see the new directory on the next page load. 
-  - Once installedclick **Enable** to activate the module.+ 
 +**Note:** Updates with this method are the same flow — replace the contents of the ''oe-module-claimrev-connect/'' folder with the contents of the new zip. Method 1 (Composer) is much easier if you have any way to run shell commands on the server. 
 + 
 +=== Method 3: Release Tarball === 
 + 
 +If you installed OpenEMR via an official release tarball that already bundles ''claimrevolution/oe-module-claimrev-connect'' in its ''composer.json''the module arrives pre-extracted at ''interface/modules/custom_modules/oe-module-claimrev-connect/''. No additional download step. 
 + 
 +==== Activation (all methods) ==== 
 + 
 +  - In OpenEMR, navigate to **Modules > Manage Modules**. 
 +  - Find **ClaimRev Connect** in the module list. Click **Install**, then **Enable**.
   - Navigate to **ClaimRev Connect > Setup** and click **Run Upgrade** to create the required database tables.   - Navigate to **ClaimRev Connect > Setup** and click **Run Upgrade** to create the required database tables.
 +
 +**Note:** If you do not yet have a ClaimRev account, visit [[https://www.claimrev.com|claimrev.com]] or contact us at [[mailto:sales@claimrev.com|sales@claimrev.com]] to get started.
  
 --- ---
Line 220: Line 233:
  
 === Test Mode === === Test Mode ===
-**Test Mode** toggle is available below the search button. When enabled: +When the **Enable Test Mode** global is on (Admin > Globals > ClaimRev Connect), the Payment Advice, ERA, and Reconciliation pages return **mock data** generated from local OpenEMR billing rows. Useful for demostraining, and posting-workflow rehearsal without hitting the live ClaimRev API.
-  * The search returns **mock data** instead of calling the ClaimRev APIallowing you to practice the posting workflow without real data. +
-  * Posting still writes to OpenEMR (useful for testing with a development database). +
-  * Claims are **not** marked as worked in ClaimRev when test mode is active. +
-  * A yellow warning banner is displayed to remind you that test mode is active.+
  
-**Important:** Only use test mode in development or training environments. Do not enable test mode in production with real patient data unless you understand that mock ERA data will be posted to OpenEMR.+  * Posting still writes to OpenEMR — useful when running against a development database. 
 +  * Claims are **not** marked as worked in ClaimRev while the global is on. 
 +  * Reconciliation row actions (Sync rejected status, Requeue) short-circuit to a fake-success response. 
 +  * ERA Download returns a 0-byte placeholder file. 
 + 
 +**Important:** Only enable the global in development or training environments. The global is the only switch — there is no longer a per-search checkbox.
  
 ==== Reconciliation ==== ==== Reconciliation ====
Line 533: Line 547:
   - Select one or more products to check using the checkboxes.   - Select one or more products to check using the checkboxes.
   - Click **Check Now** for immediate results, or **Queue Check** to process in the background.   - Click **Check Now** for immediate results, or **Queue Check** to process in the background.
-  - Results appear in tabbed sections: Quick Info, Deductibles, Benefits, Medicare, and Validations.+  - Results appear in tabbed sections: Quick Info, Deductibles, Benefits, Medicare, and Validations. The same layout is used for both Eligibility and Coverage Discovery results, since the payer returns the same response shape for both. 
 + 
 +=== Patients With No Insurance === 
 +Coverage Discovery, Demographics, and MBI Finder query the payer using patient demographic data and don't need an insurance row, so the eligibility tab is still available for patients who have no insurance entered. In that case the tab is labelled **No Insurance**, the **Eligibility** option is hidden, and **Coverage Discovery** is pre-selected. Add the matched coverage afterwards through the normal Insurance card workflow if you want to keep it. 
 + 
 +=== Reset Cached Results === 
 +A red **Reset** button next to **Check Now** clears every cached eligibility row for the current patient (across all payer responsibilities). Useful when re-testing a fresh check or after fixing patient demographics that produced a bad result. The button asks for confirmation before deleting.
  
 === Eligibility AI Assistant === === Eligibility AI Assistant ===
Line 551: Line 571:
   * Search for available ERA files by date range   * Search for available ERA files by date range
   * Download individual files for import into the OpenEMR billing system   * Download individual files for import into the OpenEMR billing system
 +  * When **Enable Test Mode** is on, the ERA tab returns mock search results from local billing data and the Download button returns a 0-byte placeholder file.
  
 ==== X12 Tracker ==== ==== X12 Tracker ====
Line 662: Line 683:
  
 ==== Supported OpenEMR Versions ==== ==== Supported OpenEMR Versions ====
-The ClaimRev Connect module supports+The ClaimRev Connect module ships as a **single binary** covering
-  * **OpenEMR 8.x** — Full native support (use the //OpenEMR 8.x// build above) +  * **OpenEMR 8.x** (master and the 8.0.x patch line) — verified against ''openemr/openemr:flex'' and ''openemr/openemr:8.0.0.3-2026-03-25''. 
-  * **OpenEMR 7.x** — Supported via a small compatibility shim layer (use the //OpenEMR 7.x// build above)+  * **OpenEMR 7.x** (7.0.0 and later— verified against ''openemr/openemr:7.0.2''.
  
-The OpenEMR 7.x build includes a ''src/Compat/'' directory with class_alias-based shims for classes and interfaces introduced in OpenEMR 8.x. On OpenEMR 7.x these shims provide equivalent functionality by wrapping legacy APIs directlyThe OpenEMR 8.x build does not ship the shim layer at all — it targets the native classes directly.+The ''src/Compat/'' shim layer activates per-host. On OE 8.x cores that already expose the modern APIs the shims are no-ops; on OE 7.x or older 8.0.x cores the shims provide ''OEGlobalsBag'', ''CryptoInterface'', and ''ServiceContainer'' via ''class_alias'', and ''CsrfHelper'' detects the active ''CsrfUtils'' signature at runtime.
  
-=== Shimmed Components (7.x build only) ===+=== Shimmed Components ===
  
-| **Component** | **What the shim does on 7.x** | +| **Component** | **What the shim does on older cores** | 
-| ''OEGlobalsBag'' | Wraps ''$GLOBALS'' with typed getters |+| ''OEGlobalsBag'' | Wraps ''$GLOBALS'' with typed getters (used directly on 7.x; on 8.0.x patch line the module imports the shim explicitly because the core's ''OEGlobalsBag'' is thinner than expected) |
 | ''ServiceContainer'' | Wraps ''CryptoGen'' and other services directly | | ''ServiceContainer'' | Wraps ''CryptoGen'' and other services directly |
 | ''LoggerInterface'' (''getLogger'') | Provides a PSR-3 logger via OpenEMR's ''SystemLogger'' | | ''LoggerInterface'' (''getLogger'') | Provides a PSR-3 logger via OpenEMR's ''SystemLogger'' |
 | ''ClockInterface'' (''getClock'') | Provides a PSR-20 clock returning the current time | | ''ClockInterface'' (''getClock'') | Provides a PSR-20 clock returning the current time |
 | ''CryptoInterface'' | Wraps ''CryptoGen'' behind the 8.x crypto interface | | ''CryptoInterface'' | Wraps ''CryptoGen'' behind the 8.x crypto interface |
-| ''CsrfHelper''Reflects on ''CsrfUtils::collectCsrfToken'' and dispatches to either the 7.x ''($subject, ?$session)'' or 8.x ''(SessionInterface$subject)'' signature |+| ''CsrfHelper''Detects whether ''SessionWrapperFactory::getActiveSession'' exists; routes to ''CsrfUtils'' with the correct argument order and ''$_SESSION'' fallback when needed | 
 +| ''GlobalConfig::getClientSecret'' | Prefers ''CryptoGen::decryptFromDatabase'' (upstream PR #11956May 2026when available; falls back to ''decryptStandard'' on older cores |
  
 ==== Compatibility Check ==== ==== Compatibility Check ====
Line 690: Line 712:
     * OpenEMR version and PHP version     * OpenEMR version and PHP version
  
-If all checks show green, the module is fully operational. If any check shows "Using ClaimRev shim (7.x mode)", the module is running with compatibility shims — all features work normally.+If all checks show green, the module is fully operational. If any check shows "Using ClaimRev shim", the module is running with compatibility shims — all features work normally.
  
 --- ---
Line 706: Line 728:
   * Ensure the payer is enrolled for eligibility transactions — see [[payer_enrollment|Payer Enrollments]]   * Ensure the payer is enrolled for eligibility transactions — see [[payer_enrollment|Payer Enrollments]]
   * Check that the subscriber ID and patient demographics are accurate   * Check that the subscriber ID and patient demographics are accurate
 +
 +==== "Error communicating with server" When Running Check Now ====
 +  * Most common cause is the upstream ClaimRev API taking longer than the script's allowed run time. The 2.1.2 build raises the script time limit and adds OAuth retries — make sure you're on 2.1.2 or later.
 +  * Click **Reset** next to **Check Now** to clear cached results and try again. A retry usually succeeds because the previous request finished server-side after the browser gave up.
 +  * If the error reproduces every time on a specific patient, capture the OpenEMR error log entry around the failed check (see **Connectivity** for log location) and contact ClaimRev support.
  
 ==== Claims Not Appearing in ClaimRev ==== ==== Claims Not Appearing in ClaimRev ====
Line 752: Line 779:
  
 ===== Changelog ===== ===== Changelog =====
 +
 +== Version 2.1.3 — May 22, 2026 (Packagist edition) ==
 +  * **Now published on Packagist** as ''claimrevolution/oe-module-claimrev-connect''. Install via ''composer require claimrevolution/oe-module-claimrev-connect:^2.1''. Replaces the previous May 12 (OE 7.x) and May 13 (OE 8.0.x rebuild) separate-zip builds with a single binary.
 +  * **Single-binary cross-version compatibility** — the ''src/Compat/'' shim layer lives in the module's own repo on GitHub, not duplicated across two build branches. Same code path runs on OE 8.x master, the OE 8.0.x patch line, and OE 7.x.
 +  * **Crypto helper hardened for cross-version** — ''GlobalConfig::getClientSecret'' uses ''CryptoGen::decryptStandard'' (works on both OE 7.x and 8.x) instead of the OE 8.x-only ''decryptFromDatabase''.
 +  * **X12_SFTP install fix** — module enable no longer references the non-existent ''background_services.last_run'' column that had been breaking installs on OE 8.x master.
 +
 +== Version 2.1.3 — May 13, 2026 rebuild for OE 8.0.x ==
 +  * **OpenEMR 8.x build rebuilt from the ''release/v8-0'' branch.** The previous 8.x build assumed every 8.x core exposed ''OEGlobalsBag::getKernel'', ''SessionWrapperFactory::getActiveSession'', and ''CsrfUtils::collectCsrfToken(session, subject)''. The OE 8.0.x patch line has none of those — its ''OEGlobalsBag'' is thin, ''SessionWrapperFactory'' uses a different acquisition pattern, and ''CsrfUtils::collectCsrfToken'' takes ''(subject, ?session)'' with a ''$_SESSION'' fallback. The new build ships the ''src/Compat/'' shim layer with runtime-detection for the divergent APIs so the same zip works on 8.0.0.3 and on newer 8.x / master.
 +  * **Verified against ''openemr/openemr:8.0.0.3-2026-03-25''** with full patient + encounter + billing data copied from a flex install. Login, navigation, Claims tab, Reconciliation, Payment Advice, ERA, and Setup all load cleanly.
 +  * **Cross-core crypto handling** — ''GlobalConfig::getClientSecret'' now prefers the newer ''CryptoGen::decryptFromDatabase'' (upstream PR #11956, May 2026) when present and falls back to ''decryptStandard'' transparently. The 2.1.3 hotfix-only revert in the original 8.x build (which always called ''decryptStandard'') is no longer needed.
 +  * Module version constant stays at **2.1.3**; this is a rebuild of the same release for the actual 8.0.x patch line.
 +
 +== Version 2.1.3 (May 2026) ==
 +  * **Security release** — Closes the ten findings raised by the Aisle security review on the upstream PR. The fixes are layered:
 +    * **IDOR guards on eligibility endpoints** — A new ''PatientContext'' helper resolves the session-active patient and the //Check Now// (''eligibility_check_now''), //Reset// (''eligibility_clear''), and //AI chat// (''eligibility_chat'') endpoints now refuse a ''pid'' that does not match. The chat endpoint additionally re-verifies the supplied ''sharpRevenueObjectId'' belongs to that patient via the stored response payload.
 +    * **CSRF on appointment queue actions** — ''appointments.php'' now verifies the existing eligibility CSRF token before either bulk or single ''Queue'' POST handler runs and emits the hidden token in ''#bulkForm''.
 +    * **Authoritative re-fetch for posting + status sync** — ''payment_advice_post.php'' accepts only ''paymentAdviceId'' (single) or ''paymentAdviceIds'' (batch JSON) and re-fetches the authoritative ''ClaimPaymentAggregation'' from ClaimRev before posting. ''claim_sync_status.php'' accepts only ''claimrevObjectId'' and derives the status fields from a re-fetched claim. Browser-supplied amounts, encounter PCNs, or status codes can no longer drive an OE write.
 +    * **Test-mode gating** — The ''skipMarkWorked'' POST flag on payment posting is only honored when ''isTestModeEnabled()'' is true, so a regular user can't suppress the upstream mark-as-worked side effect.
 +    * **Path traversal hardening** — ''EligibilityTransfer'' allowlists ''claimRevResultId'' to ''[A-Za-z0-9_-]'' (with a server-generated fallback) before composing the raw 271 save path.
 +    * **CSV export header sanitization** — ''claim_export_csv'' basename-strips control characters and restricts the API-supplied filename to a conservative charset before emitting it in ''Content-Disposition''. The header is no longer susceptible to CR/LF injection.
 +    * **Module-enable consent** — ''ClaimRevModuleSetup::ensureCoreSftpEnabled'' only flips the X12_SFTP background service to ''active = 1'' on a truly fresh install (''last_run IS NULL''). An admin who deliberately disabled the service keeps that setting across module re-enables.
 +    * **Payment posting race window** — ''PaymentAdvicePostingService::post'' wraps the duplicate check and ''arPostSession'' insert in a MySQL named lock keyed by ''paymentAdviceId''. Concurrent submits of the same advice can no longer post twice; the second call returns a clear //concurrent post in progress// message.
 +  * **Cross-core crypto compatibility** — ''GlobalConfig::getClientSecret'' originally kept calling ''CryptoGen::decryptStandard'' (the legacy API) instead of the newer ''decryptFromDatabase'' that upstream PR #11956 introduced in May 2026. The new method does not exist on older OpenEMR cores most installs still run, and using it would break the Connectivity tab on those installs. //(The May 13 rebuild above changes this to a runtime-detected fallback so the same module works on both.)//
  
 == Version 2.1.2 (May 2026) == == Version 2.1.2 (May 2026) ==
-  * **Bug fix** — Send ''serviceTypeCodes'' as a JSON array (''List<string>'') instead of a comma-separated string. The ClaimRev API tightened request validation and started rejecting the old shape with HTTP 400, breaking the **Check Now** eligibility button. Empty configuration still asks for all benefits. +  * **Eligibility request body** — Send ''serviceTypeCodes'' as a JSON array (''List<string>'') instead of a comma-separated string, and always emit ''isRevenueToolsPayerId: false'' on each payer entry. The ClaimRev API tightened request validation and started rejecting the older shape with HTTP 400, breaking **Check Now**. Empty service-type-code configuration still asks for all benefits. 
-  * **Bug fix** — Always emit ''isRevenueToolsPayerId: false'' on each payer in the eligibility request so the API can disambiguate ClaimRev-internal payer IDs from clearinghouse payer numbers. +  * **MBI Finder mutex + request shape** — MBI Finder is now mutually exclusive with Eligibility (matching the existing Coverage Discovery / Eligibility mutex). The ''payers'' array is omitted when only non-eligibility products are selected, since the API ignores it for those products and its presence corrupts MBI Finder results. When MBI Finder is requested, the subscriber number is copied to the top-level ''subscriberId'' field where MBI Finder reads it. 
-  * **Bug fix** — Make MBI Finder mutually exclusive with Eligibility (matches the existing Coverage Discovery / Eligibility mutex). Drop the ''payers'' array from the request when only non-eligibility products are selected, since the API ignores it for those products and the presence corrupts MBI Finder results. When MBI Finder is requested, copy the subscriber number to the top-level ''subscriberId'' field.+  * **Coverage Discovery results render correctly** — Coverage Discovery now renders with the full Quick Info / Deductibles / Benefits / Medicare / Validations layout. The API returns the same response shape as Eligibility, but the old Coverage Discovery view only showed the flat top-level coverage fields and dropped the nested benefit and deductible data. 
 +  * **Run without insurance** — Coverage Discovery, Demographics, and MBI Finder can now be run on patients who have no insurance entered. The eligibility tab shows a **No Insurance** view that hides the Eligibility option, pre-selects Coverage Discovery, and submits a request built from patient demographics alone. 
 +  * **Stop "Error communicating with server" on slow checks** — The eligibility AJAX endpoint can sit through a Cloud Run cold start (~60s) plus a ''retryLater'' poll loop (~60s) on Coverage Discovery, which exceeded PHP's default 30-second ''max_execution_time''. The Check Now and Appointment Check Now endpoints now allow up to 180 seconds, the Guzzle clients have explicit ''connect_timeout'' / ''timeout'' set so a stuck call can't burn the whole budget, and the OAuth token POST is retried up to two extra times on transient B2C hiccups. 
 +  * **Reset button** — A red **Reset** button next to **Check Now** clears every cached eligibility row for the current patient (across all payer responsibilities) after a confirmation prompt. Useful when re-testing a check from a clean slate.
  
 == Version 2.1.1 (May 2026) == == Version 2.1.1 (May 2026) ==
Line 790: Line 844:
 == Version 1.0.0 == == Version 1.0.0 ==
   * Initial release   * Initial release
-  * Claims passing (837P/837I)+  * Claims submission (837P/837I)
   * Real-time eligibility verification (Eligibility, Coverage Discovery, Demographics, MBI Finder)   * Real-time eligibility verification (Eligibility, Coverage Discovery, Demographics, MBI Finder)
   * AI-powered eligibility assistant   * AI-powered eligibility assistant
openemr_manual.1778085548.txt.gz · Last modified: by brad.sharp

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki