BUG FIX: Modify Payments Silently Fails When Patient Looked Up via Bottom Search in Batch Payments

Version affected: OpenEMR 7.0.4 (likely affects earlier versions as well)
Files affected: interface/billing/payment_pat_sel.inc.php
Symptom: Clicking “Modify Payments” does nothing when a patient was added via the bottom patient search in Fees → Batch Payments → Distributed Edits
Root cause: $CountIndex is reset to 0 in payment_pat_sel.inc.php instead of continuing from $CountIndexAbove, causing JavaScript element ID mismatches
Fix: One-line change in payment_pat_sel.inc.php

The Scenario

When posting an insurance payment in Fees → Batch Payments, you search for a check, click it to open the Distributed Edits screen, and then use the bottom patient search box to look up a patient who was not already on the check (e.g., a patient whose payment was included in a bulk check but who does not appear in the top “above” rows).

You fill in the Allowed, Payment, Adj Amount, and Deductible fields for the patient’s encounters, then click Modify Payments — and nothing happens. No confirmation dialog, no error message, no page submission.


Diagnosis

Opening the browser developer console (F12 → Console) and clicking Modify Payments again reveals the following JavaScript error:

Uncaught TypeError: can't access property "value", document.getElementById(...) is null
    CompletlyBlankBelow  edit_payment.php:992
    ModifyPayments       edit_payment.php:902
    onclick              edit_payment.php:1

The CompletlyBlankBelow() function in edit_payment.php is crashing because document.getElementById() is returning null — a required form element does not exist in the page’s DOM.

How the page builds its rows

edit_payment.php renders the “above” distribution rows (patients already in the database for this session/check) using a counter called $CountIndexAbove, which increments for each row rendered. These rows get element IDs like Allowed1, Allowed2, Payment1, Payment2, etc.

The “below” distribution rows (the new patient looked up via the bottom search) are rendered by an included file: payment_pat_sel.inc.php. At the top of this file, the counter is reset:

// payment_pat_sel.inc.php, line 94
$CountIndex = 0;
$CountIndexBelow = 0;

Because $CountIndex starts at 0 in the include file, the new “below” rows are always numbered starting from 1 — producing Allowed1, Allowed2, etc. — regardless of how many “above” rows were already rendered by the parent page.

The mismatch

The hidden form fields output by edit_payment.php are:

<input type='hidden' name='CountIndexAbove' id='CountIndexAbove' value='3' />
<input type='hidden' name='CountIndexBelow' id='CountIndexBelow' value='2' />

The JavaScript validation function CompletlyBlankBelow() then loops:

let CountIndexAbove = document.getElementById('CountIndexAbove').value * 1; // = 3
let CountIndexBelow = document.getElementById('CountIndexBelow').value * 1; // = 2
for (RowCount = CountIndexAbove + 1; RowCount <= CountIndexAbove + CountIndexBelow; RowCount++) {
    // Tries to find: Allowed4, Allowed5
    if (document.getElementById('Allowed' + RowCount).value == '' ...

It tries to find Allowed4 and Allowed5 — but the “below” rows were rendered with IDs Allowed1 and Allowed2. The elements don’t exist. getElementById() returns null. The crash prevents the form from submitting.


The Fix

In payment_pat_sel.inc.php, change line 94 from:

$CountIndex = 0;

to:

$CountIndex = $CountIndexAbove ?? 0;

The ?? 0 null coalescing operator ensures that if $CountIndexAbove is not set (for example, on the New Payment screen where there are no above rows), it safely falls back to 0. This means the fix does not break the new payment workflow.

With this change, the “below” rows continue numbering from where the “above” rows left off, so the JavaScript loop finds the correct element IDs.


Step-by-Step Repair Instructions

1. Back up the file

sudo cp /var/www/html/openemr/interface/billing/payment_pat_sel.inc.php \
        /var/www/html/openemr/interface/billing/payment_pat_sel.inc.php.bak.$(date +%F)

2. Apply the fix

sudo sed -i 's/\$CountIndex = 0;/\$CountIndex = $CountIndexAbove ?? 0;/' \
    /var/www/html/openemr/interface/billing/payment_pat_sel.inc.php

3. Verify the change

grep -n "CountIndex = " /var/www/html/openemr/interface/billing/payment_pat_sel.inc.php

Expected output:

94:                $CountIndex = $CountIndexAbove ?? 0;

4. Test

Go to Fees → Batch Payments, search for a check, open Distributed Edits, look up a patient via the bottom patient search, fill in their payment fields, and click Modify Payments. The confirmation dialog should now appear and the payment should post successfully.


Summary

Item Detail
File interface/billing/payment_pat_sel.inc.php
Line 94
Before $CountIndex = 0;
After $CountIndex = $CountIndexAbove ?? 0;
Impact Fixes silent failure of Modify Payments when patient is added via bottom search
Risk Low — ?? 0 fallback preserves existing behavior on New Payment screen

Reported and fixed by Jeffrey Guillory, DNP, APRN, FNP-BC — NP Health Clinic, PLLC, Lumberton, TX
OpenEMR version 7.0.4 — April 2026

Hi @nursejeff

Did you submit this bug fix to the code base on GitHub?

No sir. I have never done that before. How do I do it?