Reports
/reports — ReportsModule, rendered inside the ReportsComponent shell.
Reports are the densest part of the application and share a substantial amount of
infrastructure.
Report index
| Route | Module | Contents |
|---|---|---|
|
|
Fund transfers to the supplier. |
|
|
Seller Card transactions. |
|
|
Fee breakdown by type and date. |
|
|
Outstanding repayment balances. |
|
|
Instant Advance history and repayment. |
|
|
Daily revenue, repayment and net transfer. |
|
|
Payments received per marketplace. |
|
|
Transaction-level marketplace detail. |
|
|
Reconciliation between marketplace and Payability records. |
|
|
Outgoing vendor payments. |
|
|
Long Term Contract history. |
|
|
Same report, gated by |
|
|
Permissions
|
Granted when |
|
Same condition; enforced as a route guard on the top-level daily-summary route. |
|
Granted when |
|
Declared for element-level gating; not currently granted. |
Individual report routes are not individually guarded — the gating is on the menu and on the permission-driven data availability.
ReportBase
views/pages/reports/report-base.class.ts is the abstract base every report page
extends. It extends Subscriber and owns the AG Grid lifecycle.
export abstract class ReportBase extends Subscriber implements AfterViewInit {
gridApi: GridApi;
dataSource: BaseDataSource;
viewInit$ = this.viewInitSubject.asObservable();
clickClearListener$: Observable<void>;
hasFilter: boolean;
hasItems: boolean;
hasError: boolean;
registeredActions = new Map<ReportActionEnum, ReportAction>();
abstract isDesktopReportVisible(): boolean;
abstract get pageSize(): number;
abstract get pageIndex(): number;
abstract get filterConfiguration();
exportCSV(): void { throw new NotImplementedError('exportCSV'); }
applyFilter(): void { throw new NotImplementedError('applyFilter'); }
clearFilter(): void { throw new NotImplementedError('clearFilter'); }
registerAction(actionType: ReportActionEnum, action: (param?: any) => void, param?: any) {
this.registeredActions.set(actionType, new ReportAction(actionType, action, param));
}
}
|
|
isDesktopReportVisible() is the responsive switch — below the breakpoint the
grid is replaced by ReportsMobileContentRowComponent, which renders each row as
a stacked label/value card.
Actions are registered rather than hardcoded:
export enum ReportActionEnum { ExportAll, ExportCSV }
Data sources
BaseDataSource (core/pyb/models/base/data-source/) adapts a paginated API to
AG Grid’s server-side model, using QueryParamsModel / QueryResultsModel from
core/_base/crud.
Page sizes are fixed:
export enum ReportsPageSizes {
Desktop = 50,
Mobile = 6,
DailySummaryMobile = 4,
}
export enum ReportsFilter {
DateFormat = 'yyyy-MM-dd',
}
Grid infrastructure
Two layers cooperate.
core/pyb/components/grid/
PybGridModule — the application’s grid wrapper, imported by AppModule.
|
The wrapper component and |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Shared cell behaviour. |
|
Column-header filter overlay. |
core/reports/
PybNg2ReportsLibModule — lower-level report infrastructure.
|
Renderers and header components. |
|
No-rows and loading overlays. |
|
Grid status bar. |
|
Shared value formatters. |
|
Grid theming. |
|
Report-specific helpers. |
|
Base URL injection for report data services. |
PybPaginationModule (core/pyb/components/pagination/) provides the pagination
control below each grid.
AG Grid Enterprise is licensed at bootstrap through
initializeAgGridLicenseProvider — see Bootstrap.
Column configuration by DI token
Column sets are provided rather than hardcoded, so one grid component serves
several reports. ReportsModule provides:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The incoming and outgoing Vendor Pay reports are the clearest example — identical component, different injected column set.
Export
ExportService (core/pyb/services/export-service.ts) opens dialogs; it does not
generate files itself.
export(title = 'Export', description: string, waitDesciption = 'Your report is preparing', loading$: Observable<boolean>) {
return this.dialog.open<ExportDialogModal>(ExportDialogModal, {
data: { title, description, waitDesciption, loading$ },
width: DIALOG_SIZE.SMALL.width,
});
}
exportModal(): PybDialogRef<ExportFormDialogComponent> {
return this.dialog.open<ExportFormDialogComponent>(ExportFormDialogComponent, { width: DIALOG_SIZE.SMALL.width });
}
|
Progress dialog driven by the caller’s |
|
Extended dialog with date range and filter options. |
|
The default strings ( |
The report itself performs the download; the dialog only reports progress.
Daily Summary
The only report with its own NgRX entity slice
(reports.dailySummaryReports, keyed by xactPostDate) — see
Entity Slices. It uses class-based actions and
carries the QueryParamsModel page descriptor alongside the data.
Load failures are counted as a CloudWatch metric through
initializeDailySummaryLoadDataErrorTrackerProvider, so a broken data pipeline
raises an operational alarm rather than only a UI error.
A condensed version appears on the dashboard as the daily-summary widget.