import { Controller, Get, Post, Body, Param, Query, HttpCode, HttpStatus, NotFoundException, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, } from '@nestjs/swagger'; import { GenerateReportDto } from '../dto/request/generate-report.dto'; import { QueryReportDto } from '../dto/request/query-report.dto'; import { ReportSnapshotResponseDto } from '../dto/response/report-snapshot.dto'; import { ReportDefinitionResponseDto } from '../dto/response/report-definition.dto'; import { GenerateReportHandler } from '../../application/commands/generate-report/generate-report.handler'; import { GenerateReportCommand } from '../../application/commands/generate-report/generate-report.command'; import { ReportingApplicationService } from '../../application/services/reporting-application.service'; @ApiTags('Reports') @Controller('reports') @ApiBearerAuth() export class ReportController { constructor( private readonly generateReportHandler: GenerateReportHandler, private readonly reportingService: ReportingApplicationService, ) {} @Get('definitions') @ApiOperation({ summary: '获取所有报表定义' }) @ApiResponse({ status: 200, description: '报表定义列表', type: [ReportDefinitionResponseDto], }) async getDefinitions(): Promise { return this.reportingService.getReportDefinitions(); } @Get('definitions/:code') @ApiOperation({ summary: '获取报表定义详情' }) @ApiResponse({ status: 200, description: '报表定义详情', type: ReportDefinitionResponseDto, }) @ApiResponse({ status: 404, description: '报表定义不存在' }) async getDefinition( @Param('code') code: string, ): Promise { const definition = await this.reportingService.getReportDefinitionByCode(code); if (!definition) { throw new NotFoundException(`Report definition not found: ${code}`); } return definition; } @Post('generate') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: '生成报表' }) @ApiResponse({ status: 200, description: '报表生成成功', type: ReportSnapshotResponseDto, }) async generateReport( @Body() dto: GenerateReportDto, ): Promise { const command = new GenerateReportCommand( dto.reportCode, dto.reportPeriod, new Date(dto.startDate), new Date(dto.endDate), dto.dimensions, dto.filters, ); const snapshot = await this.generateReportHandler.execute(command); return { id: snapshot.id?.toString() || '', reportType: snapshot.reportType, reportCode: snapshot.reportCode, reportPeriod: snapshot.reportPeriod, periodKey: snapshot.periodKey, rowCount: snapshot.rowCount, summary: snapshot.snapshotData.summary, rows: snapshot.snapshotData.rows, periodStartAt: snapshot.periodStartAt, periodEndAt: snapshot.periodEndAt, generatedAt: snapshot.generatedAt, }; } @Get('snapshots') @ApiOperation({ summary: '查询报表快照' }) @ApiResponse({ status: 200, description: '报表快照列表', type: [ReportSnapshotResponseDto], }) async getSnapshots( @Query() query: QueryReportDto, ): Promise { if (query.reportCode) { const snapshots = await this.reportingService.getReportSnapshots( query.reportCode, ); return snapshots.map((s) => ({ ...s, rows: undefined, })); } if (query.reportPeriod) { const snapshots = await this.reportingService.getSnapshotsByPeriod( query.reportPeriod, ); return snapshots.map((s) => ({ ...s, rows: undefined, })); } return []; } @Get('snapshots/:code/latest') @ApiOperation({ summary: '获取最新报表快照' }) @ApiResponse({ status: 200, description: '最新报表快照', type: ReportSnapshotResponseDto, }) @ApiResponse({ status: 404, description: '快照不存在' }) async getLatestSnapshot( @Param('code') code: string, ): Promise { const snapshot = await this.reportingService.getLatestSnapshot(code); if (!snapshot) { throw new NotFoundException(`No snapshot found for report: ${code}`); } return { ...snapshot, rows: undefined, }; } }