// src/excel/excel.controller.ts import { Controller, Post, UploadedFile, UseInterceptors, BadRequestException, Request, Get, Res, HttpStatus, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { ExcelService } from './excel.service'; import { ExcelDocumentation } from './excel.documentation'; import { MovimientoService } from 'src/movimiento/movimiento.service'; import { Response } from 'express'; @Controller('excel') export class ExcelController { constructor( private readonly excelService: ExcelService, private readonly movimientoService: MovimientoService, ) {} @Post('verify') @UseInterceptors(FileInterceptor('file')) @ExcelDocumentation.verifyExcel() async verifyExcel(@UploadedFile() file: Express.Multer.File, @Request() req) { if (!file) throw new BadRequestException('Se requiere un archivo .xlsx'); const userId = req.user.userId; const errors = await this.excelService.validateFile(file.buffer); await this.movimientoService.log( userId, 'VERIFY', errors.length ? 'FAILED' : 'SUCCESS', errors.join('; '), ); return { valid: errors.length === 0, errors }; } @Post('load') @UseInterceptors(FileInterceptor('file')) @ExcelDocumentation.loadExcel() async loadExcel(@UploadedFile() file: Express.Multer.File, @Request() req) { const userId = req.user.userId; try { const { inserted } = await this.excelService.loadFile(file.buffer); await this.movimientoService.log( userId, 'LOAD', 'SUCCESS', undefined, `inserted=${inserted}`, ); return { inserted }; } catch (err) { await this.movimientoService.log(userId, 'LOAD', 'FAILED', err.message); throw err; } } @ExcelDocumentation.downloadExcel() // <-- decorador correcto @Get('download') async downloadData(@Request() req, @Res() res: Response) { const userId: number = req.user.userId; // asegúrate de que sea primitivo try { // 1) Genera los datos const data = await this.excelService.generateCsv(); // 2) Log SUCCESS await this.movimientoService.log( userId, // <-- solo el valor, no userId() 'DOWNLOAD', 'SUCCESS', undefined, `size=${data.length}`, ); // 3) Devuelve la respuesta return res .status(HttpStatus.OK) // <-- HttpStatus importado .header('Content-Type', 'text/tab-separated-values') .header('Content-Disposition', 'attachment; filename="usuarios.tsv"') .send(data); } catch (err) { // 4) Log FAILED await this.movimientoService.log( userId, 'DOWNLOAD', 'FAILED', err.message, ); // 5) Responde el error return res .status(HttpStatus.INTERNAL_SERVER_ERROR) .json({ statusCode: 500, message: 'Error generando descarga.' }); } } }