Skip to content

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.status must be approved).
  • 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)

  • AR aging — debtor-side mirror.
  • Reports — full report catalog.
  • supabase/migrations/20260415180000_finance_aging_report_rpc.sql — RPC for bucketed totals (used by the summary cards).