Accounts Payable aging
Suppliers and agents we owe, bucketed by days past due. Creditor-side mirror of AR aging — same buckets, same row shape, same UI.
1. What it shows
Two groups of open-balance rows (src/lib/api.ts:25249-25458):
Supplier payables
One row per active supplier with a net-positive balance computed from
SupplierTransaction:
type = 'debit'→ raises the payable.type = 'credit' | 'refund'→ settles.type = 'adjustment'→ signed; trusts the recorded sign.
The bucket is driven by the oldest unsettled debit date
(transactionDate or createdAt). Zero-balance or credit-balance
suppliers are hidden.
Row referenceType = 'supplier_payable', referenceId = <supplierId>.
Agent payables
One row per agent with a net credit balance in their dedicated
AGP-xxxxxxxx ledger account (LIABILITY, see the chart of accounts).
- Credit lines → raise the payable (commission owed).
- Debit lines → settle.
- Non-approved journals are excluded (
entry.statusmust beapproved). - Bucket is driven by the oldest unsettled credit date.
Agent lookup is by the first 8 hex chars of Agent.id matched against
the AGP-xxxxxxxx suffix (src/lib/api.ts:25412-25416). Falls back to
the account name when an agent cannot be resolved.
Row referenceType = 'agent_payable', referenceId = <agentId | accountId>.
Buckets
Same as AR aging (src/lib/api.ts:25263-25269):
bucket |
Days past due |
|---|---|
current |
≤ 0 |
1-30 |
1 to 30 |
31-60 |
31 to 60 |
61-90 |
61 to 90 |
90+ |
> 90 |
Row shape (mirrors AR)
Field names mirror AR /finance/aging exactly so the shared aging UI
renders both reports without refactoring (src/lib/api.ts:25271-25291).
partyType: 'supplier' | 'agent' is the one extra field.
Approximation: 'oldest unsettled'
The aging date is the oldest debit (suppliers) / oldest credit (agents), not a true FIFO match of unsettled vouchers. Good enough for the dashboard; an audit against actual ageing would need voucher-level offset tracking.
2. Endpoint
| Method | Path | Handler | Permission |
|---|---|---|---|
GET |
/finance/aging-payables |
handleFinanceAgingPayables (src/lib/api.ts:25249) |
finance.reports.aging.view (UI), finance.view (RLS). |
Introduced in PR #115. No RPC variant — the aggregation is cheap enough to compute on the fly.
3. UI
Finance page → Reports tab → AP Aging button
(Finance.tsx:6490). Gated by finance.reports.aging.view (same gate
as AR Aging — one permission covers both reports).
The rendered table is the same component as AR, just fed the
AP-aging rows with partyType available for filters.
View modes
Same as AR (Finance.tsx:525, apAgingViewMode: 'invoice' | 'payer'):
- Invoice view — one row per aged party.
- Payer view — rolled up (degenerate here since each party is already one row; supplier vs agent split is the useful grouping).
4. Permission gate summary
| Action | Permission |
|---|---|
| View AP Aging button | finance.reports.aging.view |
| Export CSV | finance.reports.aging.export |
Read SupplierTransaction / JournalLine |
finance.view (RLS) |