rwadurian/backend/services/reporting-service/src/application/schedulers/report-generation.scheduler.ts

171 lines
5.0 KiB
TypeScript

import { Injectable, Inject, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import {
IReportDefinitionRepository,
REPORT_DEFINITION_REPOSITORY,
} from '../../domain/repositories';
import { GenerateReportHandler } from '../commands/generate-report/generate-report.handler';
import { GenerateReportCommand } from '../commands/generate-report/generate-report.command';
import { DateRange, ReportPeriod } from '../../domain/value-objects';
@Injectable()
export class ReportGenerationScheduler {
private readonly logger = new Logger(ReportGenerationScheduler.name);
constructor(
@Inject(REPORT_DEFINITION_REPOSITORY)
private readonly definitionRepo: IReportDefinitionRepository,
private readonly generateReportHandler: GenerateReportHandler,
) {}
@Cron(CronExpression.EVERY_DAY_AT_1AM)
async generateDailyReports(): Promise<void> {
this.logger.log('Starting daily report generation...');
try {
const definitions = await this.definitionRepo.findScheduled();
const yesterday = this.getYesterday();
const dateRange = DateRange.create(yesterday.start, yesterday.end);
for (const definition of definitions) {
try {
const command = new GenerateReportCommand(
definition.reportCode,
ReportPeriod.DAILY,
yesterday.start,
yesterday.end,
);
await this.generateReportHandler.execute(command);
this.logger.log(`Daily report generated: ${definition.reportCode}`);
} catch (error) {
this.logger.error(
`Failed to generate daily report: ${definition.reportCode}`,
error,
);
}
}
this.logger.log('Daily report generation completed');
} catch (error) {
this.logger.error('Daily report generation failed', error);
}
}
@Cron(CronExpression.EVERY_WEEK)
async generateWeeklyReports(): Promise<void> {
this.logger.log('Starting weekly report generation...');
try {
const definitions = await this.definitionRepo.findScheduled();
const lastWeek = this.getLastWeek();
for (const definition of definitions) {
try {
const command = new GenerateReportCommand(
definition.reportCode,
ReportPeriod.WEEKLY,
lastWeek.start,
lastWeek.end,
);
await this.generateReportHandler.execute(command);
this.logger.log(`Weekly report generated: ${definition.reportCode}`);
} catch (error) {
this.logger.error(
`Failed to generate weekly report: ${definition.reportCode}`,
error,
);
}
}
this.logger.log('Weekly report generation completed');
} catch (error) {
this.logger.error('Weekly report generation failed', error);
}
}
@Cron('0 0 1 * *') // First day of month at midnight
async generateMonthlyReports(): Promise<void> {
this.logger.log('Starting monthly report generation...');
try {
const definitions = await this.definitionRepo.findScheduled();
const lastMonth = this.getLastMonth();
for (const definition of definitions) {
try {
const command = new GenerateReportCommand(
definition.reportCode,
ReportPeriod.MONTHLY,
lastMonth.start,
lastMonth.end,
);
await this.generateReportHandler.execute(command);
this.logger.log(`Monthly report generated: ${definition.reportCode}`);
} catch (error) {
this.logger.error(
`Failed to generate monthly report: ${definition.reportCode}`,
error,
);
}
}
this.logger.log('Monthly report generation completed');
} catch (error) {
this.logger.error('Monthly report generation failed', error);
}
}
private getYesterday(): { start: Date; end: Date } {
const now = new Date();
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() - 1);
const start = new Date(
yesterday.getFullYear(),
yesterday.getMonth(),
yesterday.getDate(),
0,
0,
0,
);
const end = new Date(
yesterday.getFullYear(),
yesterday.getMonth(),
yesterday.getDate(),
23,
59,
59,
999,
);
return { start, end };
}
private getLastWeek(): { start: Date; end: Date } {
const now = new Date();
const dayOfWeek = now.getDay();
const diffToLastMonday = dayOfWeek === 0 ? -13 : -6 - dayOfWeek;
const start = new Date(now);
start.setDate(now.getDate() + diffToLastMonday);
start.setHours(0, 0, 0, 0);
const end = new Date(start);
end.setDate(start.getDate() + 6);
end.setHours(23, 59, 59, 999);
return { start, end };
}
private getLastMonth(): { start: Date; end: Date } {
const now = new Date();
const start = new Date(now.getFullYear(), now.getMonth() - 1, 1, 0, 0, 0);
const end = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999);
return { start, end };
}
}