---
tags: [reports, service]
module: Reports
---

# [Service]CustomerAgingService

## Connections
[[_Reports]] · [[[Model]Models]] · [[[Controller]Controllers]] · [[[Job]Jobs]] · [[[Cross]CrossModuleDependencies]]

## Source
`Modules/Reports/Services/ReportsAgingCustomerService.php`

---

## ReportsAgingCustomerService

The most complex service in the module. Reads from the pre-computed `report_customer_aging` cache table and applies dynamic aging bucket logic in-memory.

### Trait
Uses `TenantConnectionOnRuntime` — switches DB connection at runtime.

### Public Methods

| Method | Purpose |
|---|---|
| getSummaryByCustomer() | Paginated list of customers with outstanding balances + aging bucket breakdown |
| getDetailTransactionsByCustomer() | Paginated transaction rows for a single customer |
| getCustomerNetBalance() | Net balance for one customer (amount - paid_amount sum) |
| getGrandTotalSummary() | Aggregated totals + aging buckets across all filtered customers |
| updateTransactionRecord() | Called when a payment changes — updates or deletes the cached row |
| getAgingPeriodLabels() | Returns bucket labels (e.g. "1–30 days", "31–60 days", etc.) |

### Key Parameters (from request)
`customer_ids` · `cost_center_ids` · `fiscal_year_id` · `as_of_date` · `aging_method` (due_date / transaction_date) · `days_per_period` · `number_of_periods` · `sort_by / sort_direction` · `per_page / page`

### Aging Calculation
```
days_overdue = as_of_date − reference_date
reference_date = due_date  (if aging_method = 'due_date')
               = transaction_date (if aging_method = 'transaction_date')

Buckets: [current, 1–30, 31–60, 61–90, 91+] (configurable via days_per_period / number_of_periods)
```

### Performance Notes
- Batch-loads customers + transactions; single-pass aggregation
- Permission enforcement via `sanitizeCostCenterIds()` — filters cost centers by user's `costCenterPermissions('view')`
- `resolveAsOfDate()` falls back to fiscal year end date if not provided
- Cost center `null` in DB = main center; passed as `0` in request

### Data Source
`ReportCustomerAging` model (cache table). Populated offline by [[[Job]Jobs#PopulateAgingReportForTenantJob]] and [[[Command]Commands]].
