The one v1 report missing from #145's five sub-reports. v1's Invoice Aging shows, per client, the open balance bucketed by days past due — the standard collections tool.
Behavioral spec: v1 application/modules/reports/models/Mdl_reports.php:125-181, controllers/Reports.php:86-101, views/invoice_aging_index.php.
Specific
An Invoice Aging report page in the company panel Reports group (same pattern as #145 / PR #609): one row per client with open balances, columns:
- 1–15 days — sum of open invoice balances due 1–15 days ago (v1
range_1)
- 16–30 days — due 16–30 days ago (
range_2)
- 31+ days — due 31+ days ago (
range_3)
- Total balance — all past-due balance (
total_balance)
Only clients with any bucket > 0 appear (v1 HAVING clause :175-178). No date-range picker — aging is always relative to today.
Measurable
- Report reachable from the Reports navigation group; read-only.
- Bucket math matches the v1 definitions above against a seeded fixture.
- Summary/totals line across all clients at the bottom.
- Export CSV action downloads header + one row per client + totals.
- Company-scoped; other tenants' invoices never counted.
Achievable
One Filament page + custom query following the #145 page pattern: Invoice::forCompany()->whereDate('due_at', '<', today()) with conditional SUM aggregates per bucket, grouped by relation. CSV export reuses the #145 CSV action.
Relevant
Track B of epic #506 (v1 parity required before launch). Collections/aging is the report accountants ask for first.
Time-Bound
Half a sprint once PR #609 merges (pattern + CSV plumbing exist then).
Arrange
- Client A: open invoices due 5 days ago (balance 100) and 20 days ago (balance 200).
- Client B: open invoice due 45 days ago (balance 300).
- Client C: only a fully paid past-due invoice (balance 0) and a future-due invoice.
- Another company with an overdue invoice (leak check).
Act
- Open the Invoice Aging report page; trigger Export CSV.
Assert
The one v1 report missing from #145's five sub-reports. v1's Invoice Aging shows, per client, the open balance bucketed by days past due — the standard collections tool.
Behavioral spec: v1
application/modules/reports/models/Mdl_reports.php:125-181,controllers/Reports.php:86-101,views/invoice_aging_index.php.Specific
An Invoice Aging report page in the company panel Reports group (same pattern as #145 / PR #609): one row per client with open balances, columns:
range_1)range_2)range_3)total_balance)Only clients with any bucket > 0 appear (v1 HAVING clause
:175-178). No date-range picker — aging is always relative to today.Measurable
Achievable
One Filament page + custom query following the #145 page pattern:
Invoice::forCompany()->whereDate('due_at', '<', today())with conditional SUM aggregates per bucket, grouped by relation. CSV export reuses the #145 CSV action.Relevant
Track B of epic #506 (v1 parity required before launch). Collections/aging is the report accountants ask for first.
Time-Bound
Half a sprint once PR #609 merges (pattern + CSV plumbing exist then).
Arrange
Act
Assert