runDueRecurringTransactions() always logs a start/finish marker for
observability, even when nothing is due, but the "does nothing" test
still asserted logger.info was never called. Pre-existing baseline
failure, unrelated to the notification-center work about to start.
Global admins couldn't see the app's event log (no read endpoint or UI
existed for it) and had no way to clean up old entries or re-run a
scheduled job without touching the database or server directly.
Backend:
- LoggingService.findLogs() + admin-only LogsController (GET
admin/logs) with level/event/date-range/search filtering and
pagination, mirroring AdminUsersService.findPlayers().
- LogRetentionScheduler deletes log entries older than
LOG_RETENTION_DAYS (default 365, via app.config.ts), following the
existing @Cron scheduler pattern.
- Admin-only POST admin/run endpoints on CashboxExportController and
RecurringTransactionsController that invoke the existing schedulers'
public run methods on demand - both are safe to re-run since their
"due" queries advance nextRunDate only after a successful run.
Frontend:
- New /logs page (global-admin gated, same pattern as /users): AG-Grid
infinite-scroll table with level/event/date-range/search filters,
plus buttons to trigger the two jobs now and see the result land in
the grid immediately.
- LogsApi, and triggerRunNow() added to the existing CashboxExportApi
and RecurringTransactionApi.
- Discoverability link from /users to /logs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lets treasurers/captains/coaches define recurring fee/levy dues that
are automatically booked for all active players on a monthly,
quarterly, or yearly schedule via a daily cron job, instead of having
to book them manually every cycle.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>