Bug 42060

Summary: Error 500 when attempting to pay overdue fines for returned items, with phantom credits accumulating on patron accounts
Product: Koha Reporter: amanda <amanda>
Component: Fines and feesAssignee: Bugs List <koha-bugs>
Status: NEW --- QA Contact: Testopia <testopia>
Severity: major    
Priority: P5 - low CC: dcook, didier.gautheron, fridolin.somers, jonathan.druart, katrin.fischer, laurent.ducos, lisette, lucas, m.de.rooy, martin.renvoize, nick, phil, tomascohen
Version: 25.05   
Hardware: All   
OS: Linux   
GIT URL: Initiative type: ---
Sponsorship status: --- Comma delimited list of Sponsors:
Crowdfunding goal: 0 Crowdfunding committed: 0
Crowdfunding contact: Patch complexity: ---
Documentation contact: Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function:

Description amanda@koalan.com.br 2026-03-10 19:56:31 UTC
When a librarian attempts to pay an overdue fine for a returned item via the staff interface (Circulation > Accounting > Make a payment), the system throws an HTTP 500 error instead of processing the payment.

Each failed payment attempt creates a PAYMENT credit entry in accountlines with a negative amountoutstanding (e.g. -1.50), without applying it to the debit. Over time, these phantom credits accumulate, displaying an unrealistic credit balance on the patron's account (e.g. 20.00, 50.00...) while the original fine remains outstanding.

---

**Steps to reproduce:**

1. Create an overdue fine for a patron (item must be returned — status RETURNED in accountlines)
2. Go to the patron's account in the staff interface
3. Click "Make a payment", select the fine, click "Confirm"
4. Observe HTTP 500 error
5. Repeat step 3 — each attempt adds a new phantom PAYMENT credit

---

**Expected behavior:**

The fine should be marked as paid (amountoutstanding = 0, status = PAID) and a PAYMENT credit record should be created with amountoutstanding = 0.

**Actual behavior:**

HTTP 500 error is thrown. The fine remains pending. A PAYMENT credit is created with amountoutstanding < 0 (phantom credit).

---

**Root cause:**

When an item is returned, the loan record is moved from `issues` to `old_issues`. The corresponding fine in `accountlines` retains `old_issue_id` but has `issue_id = NULL`.

During payment processing, `Koha/Account/Line.pm` (line ~692) calls:

```
$debit->item->itemlost(...)
```

This call chain goes through `C4/Circulation.pm` line 3176 (`CanBookBeRenewed`), which calls `$issue->item`. Since `issue_id` is NULL, `$issue` is undefined, causing the fatal error:

```
Can't call method "item" on an undefined value at /usr/share/koha/lib/C4/Circulation.pm line 3176
```

The foreign key constraint on `accountlines.issue_id` only accepts IDs from the `issues` table (active loans), so it is not possible to populate `issue_id` with values from `old_issues` as a workaround.

---

**Plack error log:**

```
{UNKNOWN}: Can't call method "item" on an undefined value at /usr/share/koha/lib/C4/Circulation.pm line 3176. at /usr/share/koha/lib/Koha/Account/Line.pm line 692
```

---

**Workaround (database-level):**

```sql
-- Zero out phantom credits
UPDATE accountlines SET amountoutstanding = 0
WHERE borrowernumber = <borrowernumber>
AND credit_type_code = 'PAYMENT'
AND amountoutstanding < 0;

-- Mark affected fines as paid
UPDATE accountlines SET amountoutstanding = 0, status = 'PAID'
WHERE borrowernumber = <borrowernumber>
AND debit_type_code = 'OVERDUE'
AND amountoutstanding > 0
AND issue_id IS NULL
AND old_issue_id IS NOT NULL;
```

---

**Affected patrons query:**

```sql
SELECT DISTINCT a.borrowernumber, p.surname, p.firstname,
    COUNT(*) AS pending_fines,
    SUM(a.amountoutstanding) AS total_outstanding
FROM accountlines a
JOIN borrowers p ON a.borrowernumber = p.borrowernumber
WHERE a.debit_type_code = 'OVERDUE'
AND a.amountoutstanding > 0
AND a.issue_id IS NULL
AND a.old_issue_id IS NOT NULL
GROUP BY a.borrowernumber, p.surname, p.firstname
ORDER BY total_outstanding DESC;
```

---

**Severity:** Major — prevents librarians from processing fine payments for any returned item.

**Component:** Circulation / Accounting
Comment 1 Katrin Fischer 2026-03-11 10:33:03 UTC
I think this probably doesn't need to be in Koha security, but could be public in the Koha product.

Can you share which Koha version you are using please?
Comment 2 amanda@koalan.com.br 2026-03-11 12:02:06 UTC
Yes. Its 25.05.05. 
And I agree with you, its koha not security