fase(15): reporting module with pdf generation
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
/**
|
||||
* ReportWorker — handles 'report:generate' jobs.
|
||||
* Generates reports in the background (full implementation in Phase 15).
|
||||
* Generates HTML, JSON, or PDF reports in the background.
|
||||
*/
|
||||
import { JobHandler } from '../JobQueue';
|
||||
import { Logger } from '../../shared/infrastructure/Logger';
|
||||
import { IReportRepository } from '../../modules/reporting/domain/ports/IReportRepository';
|
||||
import { IFindingRepository } from '../../modules/findings/domain/ports/IFindingRepository';
|
||||
import { HTMLReportGenerator } from '../../modules/reporting/infrastructure/generators/HTMLReportGenerator';
|
||||
import { JSONReportGenerator } from '../../modules/reporting/infrastructure/generators/JSONReportGenerator';
|
||||
import { PDFReportGenerator } from '../../modules/reporting/infrastructure/generators/PDFReportGenerator';
|
||||
|
||||
export const REPORT_JOB_TYPE = 'report:generate';
|
||||
|
||||
@@ -25,16 +30,51 @@ export interface ReportJobResult {
|
||||
|
||||
export function createReportJobHandler(deps: {
|
||||
logger: Logger;
|
||||
reportRepository: IReportRepository;
|
||||
findingRepository: IFindingRepository;
|
||||
}): JobHandler<ReportJobPayload, ReportJobResult> {
|
||||
const htmlGen = new HTMLReportGenerator();
|
||||
const jsonGen = new JSONReportGenerator();
|
||||
const pdfGen = new PDFReportGenerator();
|
||||
|
||||
return async (payload: ReportJobPayload): Promise<ReportJobResult> => {
|
||||
const log = deps.logger.child({ jobType: REPORT_JOB_TYPE, reportId: payload.reportId });
|
||||
log.info({ format: payload.format }, 'Report generation job executing');
|
||||
|
||||
// Full implementation in Phase 15 (Reporting Module)
|
||||
// For now, return a placeholder result
|
||||
const filePath = `./reports/${payload.reportId}.${payload.format}`;
|
||||
log.info({ filePath }, 'Report job complete');
|
||||
const report = await deps.reportRepository.findById(payload.reportId);
|
||||
if (!report) {
|
||||
throw new Error(`Report not found: ${payload.reportId}`);
|
||||
}
|
||||
|
||||
report.markGenerating();
|
||||
await deps.reportRepository.update(report);
|
||||
|
||||
// Load findings with filters from report
|
||||
const findings = await deps.findingRepository.findAll({
|
||||
sessionId: report.filters.sessionId,
|
||||
severity: report.filters.severity,
|
||||
});
|
||||
|
||||
let filePath: string;
|
||||
try {
|
||||
if (payload.format === 'pdf') {
|
||||
filePath = await pdfGen.generate(report, findings);
|
||||
} else if (payload.format === 'json') {
|
||||
filePath = await jsonGen.generate(report, findings);
|
||||
} else {
|
||||
filePath = await htmlGen.generate(report, findings);
|
||||
}
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
report.markFailed(msg);
|
||||
await deps.reportRepository.update(report);
|
||||
throw err;
|
||||
}
|
||||
|
||||
report.markReady(filePath, findings.length);
|
||||
await deps.reportRepository.update(report);
|
||||
|
||||
log.info({ filePath, totalFindings: findings.length }, 'Report job complete');
|
||||
return { reportId: payload.reportId, filePath };
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user