171 lines
5.0 KiB
TypeScript
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 };
|
|
}
|
|
}
|