---
name: evolution_ledger_filter_left_join
description: "Why the General Ledger filter (ledgersave.php?call=filter) must LEFT JOIN accounts, not inner join"
metadata: 
  node_type: memory
  type: project
  originSessionId: f8718217-a73b-4cf0-8201-71bc272bf1b2
---

`ledgersave.php?call=filter` renders the General Ledger register for `ledger.inc`. It originally did `inner join accounts on gledger.accountid = accounts.id`, which **silently dropped any posted gledger line whose accountid had no chart row** — so those entries never appeared in the ledger at all. This bit AP bill-payment lines, which were posted to a hardcoded account id that didn't match the tenant's configured accPay (see [[evolution_xero_ap_payment_sync]]).

Fix: use **`left join accounts`** (branches was already a left join). A GL view must show every journaled line in the date range regardless of whether its account still resolves. Display falls back: gledger.accname → accounts.accountname → `"Account #<id>"` (AP payment lines don't stamp accname, so the chart name fills in).

Rule of thumb: any register/report that lists raw `gledger` rows should LEFT JOIN reference tables (accounts/branches), never inner join — an inner join turns "missing lookup row" into "missing ledger entry", which hides money.
