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

/reports/transfer

TransferReportPageModule

Fund transfers to the supplier.

/reports/card-transactions

CardTransactionsPageComponent (eager)

Seller Card transactions.

/reports/fee-report

FeeReportPageModule

Fee breakdown by type and date.

/reports/outstanding-balance

OutstandingBalancePageModule

Outstanding repayment balances.

/reports/instant-advance-report

InstantAdvanceReportPageModule

Instant Advance history and repayment.

/reports/daily-summary-report

DailySummaryModule

Daily revenue, repayment and net transfer.

/reports/marketplace-payment-report

MarketplacePaymentPageModule

Payments received per marketplace.

/reports/marketplace-transaction-details

MarketplaceTransactionPageModule

Transaction-level marketplace detail.

/reports/reconciliation-view

ReconciliationViewReportModule

Reconciliation between marketplace and Payability records.

/reports/vendor-pay-report

VendorpayReportsModule

Outgoing vendor payments.

/reports/contracts-overview-report

ContractsOverviewPageModule

Long Term Contract history.

/daily-summary-report (top level)

DailySummaryModule

Same report, gated by NgxPermissionsGuard on REPORTS.DAILY_SUMMARY.

instant-advance-report is declared twice in reports-routing.module.ts — once near the top and once at the bottom, both pointing at InstantAdvanceReportPageModule. The second is unreachable.

Permissions

REPORTS

Granted when hasPaymentHistory and not onboarding. Gates the menu entry.

REPORTS.DAILY_SUMMARY

Same condition; enforced as a route guard on the top-level daily-summary route.

REPORTS.INSTANT_ADVANCE_REPORT / .INSTANT_ADVANCE_REPORT_MVP

Granted when hasInstantAdvHistory.

REPORTS.VIEW_INSTANT_ADVANCE_REPORT_MVP_ELEMENT

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));
    }
}

exportCSV, applyFilter and clearFilter throw NotImplementedError rather than being abstract, so a report only implements what it actually offers. A report that exposes an export button without overriding exportCSV() throws at runtime, not compile time.

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.

grid.component.ts

The wrapper component and GridOptions handling.

cells/currency/

CurrencyCellComponent — currency formatting.

cells/date/

DateCellComponent — locale-aware dates.

cells/translate/

TranslateCellComponent — routes cell values through @ngx-translate.

cells/progress-bar/

ProgressBarCellComponent — inline repayment progress.

cells/actions/

ActionsCellComponent — per-row buttons.

cells/toggle/

ToggleCellComponent — row-level switches.

cells/cell/

CellComponent — the generic base.

cells/base-cell.component.ts

Shared cell behaviour.

filter-popup/

Column-header filter overlay.

core/reports/

PybNg2ReportsLibModule — lower-level report infrastructure.

ag-grid/cells/, headers/, row/

Renderers and header components.

ag-grid/overlay/

No-rows and loading overlays.

ag-grid/status-bar/

Grid status bar.

ag-grid/value-formatters/

Shared value formatters.

ag-grid/styles/, styles/

Grid theming.

daily-summary-report/, fee-report/

Report-specific helpers.

tokens/base-url.token.ts

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:

FEE_REPORT_COLUMNS_CONFIG_TOKEN

feeReportColumnsConfig

FEE_REPORT_AUTO_COLUMN_GROUP_CONFIG_TOKEN

feeReportAutoColumnGroupConfig

OUTSTANDING_BALANCE_COLUMNS_CONFIG_TOKEN

outstandingBalanceColumnsConfig

OUTSTANDING_BALANCE_AUTO_COLUMN_GROUP_CONFIG_TOKEN

outstandingBalanceAutoColumnGroupConfig

VENDOR_PAY_INCOMING_REPORT_COLUMNS_CONFIG_TOKEN

vendorPayIncomingColConfig

VENDOR_PAY_OUTGOING_REPORT_COLUMNS_CONFIG_TOKEN

vendorPayOutgoingColConfig

VENDOR_PAY_REPORT_AUTO_COLUMNS_CONFIG_TOKEN

vendorPayReportAutoColumnGroupConfig

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 });
}

ExportDialogModal

Progress dialog driven by the caller’s loading$.

ExportFormDialogComponent

Extended dialog with date range and filter options.

The default strings ('Export', 'Your report is preparing') are English literals in the service signature. Callers should pass translated values.

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.

Supplier key provider

views/pages/reports/supplier-key-provider.service.ts supplies the supplier key to report data services, so report components do not each select it from the store.