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>
39 lines
703 B
TypeScript
39 lines
703 B
TypeScript
import { Type } from 'class-transformer';
|
|
import { IsDateString, IsIn, IsInt, IsOptional, IsString, Max, Min } from 'class-validator';
|
|
import { LOGEVENT, LOGEVENT_VALUES, LOGLEVEL, LOGLEVEL_VALUES } from '../model/logging-event.type';
|
|
|
|
export class AdminLogQueryDto {
|
|
@IsOptional()
|
|
@IsIn(LOGLEVEL_VALUES)
|
|
level?: LOGLEVEL;
|
|
|
|
@IsOptional()
|
|
@IsIn(LOGEVENT_VALUES)
|
|
event?: LOGEVENT;
|
|
|
|
@IsOptional()
|
|
@IsDateString()
|
|
from?: string;
|
|
|
|
@IsOptional()
|
|
@IsDateString()
|
|
to?: string;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
search?: string;
|
|
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
@IsInt()
|
|
@Min(1)
|
|
page = 1;
|
|
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
@IsInt()
|
|
@Min(1)
|
|
@Max(200)
|
|
limit = 50;
|
|
}
|