movimientos logs con data de payload, refactor de controller

This commit is contained in:
Your Name
2025-06-18 15:44:55 -06:00
parent 6114fa2583
commit 2a1a3bc5c0
2 changed files with 92 additions and 162 deletions
+84 -155
View File
@@ -1,5 +1,5 @@
// src/excel/excel.controller.ts
import { Controller, Post, Get, UseGuards, Request, Res, UploadedFile, UseInterceptors, HttpStatus } from '@nestjs/common';
import { Controller, Post, Get, UseGuards, Request, Res, UploadedFile, UseInterceptors, HttpStatus, ForbiddenException } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth } from '@nestjs/swagger';
import { FileInterceptor } from '@nestjs/platform-express';
@@ -41,161 +41,90 @@ async verifyExcel(
}
@Post('load')
@UseInterceptors(FileInterceptor('file'))
@ExcelDocumentation.loadExcel()
async loadExcel(@Request() req, @UploadedFile() file: Express.Multer.File) {
const origen = req.user.origen; // ahora sí existe
if (origen != 'LOAD') {
await this.movimientoService.log(
'LOAD',
'FAILED',
'Origen no permitido para carga'
);
throw new Error('Origen no permitido para carga.');
}
try {
const result = await this.excelService.loadFile(file.buffer);
await this.movimientoService.log(
'LOAD',
'SUCCESS',
undefined,
`inserted=${result.inserted}`
);
return result;
} catch (err) {
await this.movimientoService.log(
'LOAD',
'FAILED',
err.message
);
throw err;
}
@Post('load')
@UseGuards(AuthGuard('jwt'))
@UseInterceptors(FileInterceptor('file'))
@ExcelDocumentation.loadExcel()
async loadExcel(
@UploadedFile() file: Express.Multer.File,
@Request() req,
) {
const { userId, tipo } = req.user; // userId es number, tipo tu fuente
if (tipo !== 'LOAD') {
await this.movimientoService.log(
userId,
tipo,
'FAILED',
'Origen no permitido para carga',
);
throw new ForbiddenException('Origen no permitido para carga.');
}
@Get('download')
@ExcelDocumentation.downloadExcel()
async downloadData(@Request() req, @Res() res: Response) {
const origen = req.user.origen; // ahora sí existe
console.log('Origen de descarga:', origen);
console.log('Usuario:', req.user);
if (origen == 'SOLICITA') {
try {
const csv = await this.excelService.generateCsvSolicita();
await this.movimientoService.log(
origen,
'SUCCESS',
undefined,
`size=${csv.length}`
);
return res
.status(HttpStatus.OK)
.header('Content-Type', 'text/tab-separated-values')
.header('Content-Disposition', 'attachment; filename="usuarios_solicita.tsv"')
.send(csv);
} catch (err) {
await this.movimientoService.log(
origen,
'FAILED',
'Origen no permitido para descarga'
);
return res
.status(HttpStatus.FORBIDDEN)
.json({ statusCode: 403, message: 'Origen no permitido para descarga.' });
}
} else if (origen == 'CORREO') {
try {
const csv = await this.excelService.generateCsvCorreo();
await this.movimientoService.log(
origen,
'SUCCESS',
undefined,
`size=${csv.length}`
);
return res
.status(HttpStatus.OK)
.header('Content-Type', 'text/tab-separated-values')
.header('Content-Disposition', 'attachment; filename="usuarios.tsv"')
.send(csv);
} catch (err) {
await this.movimientoService.log(
origen,
'FAILED',
err.message
);
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json({ statusCode: 500, message: 'Error generando descarga.' });
}
} else if (origen == 'AT') {
try {
const csv = await this.excelService.generateCsvAT();
await this.movimientoService.log(
origen,
'SUCCESS',
undefined,
`size=${csv.length}`
);
return res
.status(HttpStatus.OK)
.header('Content-Type', 'text/tab-separated-values')
.header('Content-Disposition', 'attachment; filename="usuarios_at.tsv"')
.send(csv);
} catch (err) {
await this.movimientoService.log(
origen,
'FAILED',
err.message
);
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json({ statusCode: 500, message: 'Error generando descarga.' });
}
} else if (origen == 'RED') {
try {
const csv = await this.excelService.generateCsvRed();
await this.movimientoService.log(
origen,
'SUCCESS',
undefined,
`size=${csv.length}`
);
return res
.status(HttpStatus.OK)
.header('Content-Type', 'text/tab-separated-values')
.header('Content-Disposition', 'attachment; filename="usuarios_red.tsv"')
.send(csv);
} catch (err) {
await this.movimientoService.log(
origen,
'FAILED',
err.message
);
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json({ statusCode: 500, message: 'Error generando descarga.' });
}
} else {
await this.movimientoService.log(
origen,
'FAILED',
'Origen no permitido para descarga'
);
return res
.status(HttpStatus.FORBIDDEN)
.json({ statusCode: 403, message: 'Origen no permitido para descarga.' });
}
try {
const { inserted } = await this.excelService.loadFile(file.buffer);
await this.movimientoService.log(
userId,
tipo,
'SUCCESS',
undefined,
`inserted=${inserted}`,
);
return { inserted };
} catch (err) {
await this.movimientoService.log(
userId,
tipo,
'FAILED',
err.message,
);
throw err;
}
}
@Get('download')
@UseGuards(AuthGuard('jwt'))
@ApiBearerAuth('bearer')
@ExcelDocumentation.downloadExcel()
async downloadData(@Request() req, @Res() res: Response) {
const { userId, tipo } = req.user;
// Mapeo: tipo → [método de ExcelService, sufijo de filename]
const generators: Record<string, [() => Promise<string>, string]> = {
SOLICITA: [() => this.excelService.generateCsvSolicita(), 'solicita'],
CORREO: [() => this.excelService.generateCsvCorreo(), 'correo'],
AT: [() => this.excelService.generateCsvAT(), 'at'],
RED: [() => this.excelService.generateCsvRed(), 'red'],
};
const entry = generators[tipo];
if (!entry) {
await this.movimientoService.log(userId, tipo, 'FAILED', 'Origen no permitido para descarga');
return res
.status(HttpStatus.FORBIDDEN)
.json({ statusCode: 403, message: 'Origen no permitido para descarga.' });
}
const [generateCsv, suffix] = entry;
try {
const csv = await generateCsv();
await this.movimientoService.log(userId, tipo, 'SUCCESS', undefined, `size=${csv.length}`);
return res
.status(HttpStatus.OK)
.header('Content-Type', 'text/tab-separated-values')
.header('Content-Disposition', `attachment; filename="usuarios_${suffix}.tsv"`)
.send(csv);
} catch (err) {
await this.movimientoService.log(userId, tipo, 'FAILED', err.message);
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json({ statusCode: 500, message: 'Error generando descarga.' });
}
}
}
+8 -7
View File
@@ -15,15 +15,16 @@ export class MovimientoService {
/** Crea un registro de movimiento */
async log(
origen: string,
status: string,
observaciones?: string,
reporte?: string,
flag = false,
usuarioId: number,
fuente: string,
status: string,
observaciones?: string,
reporte?: string,
flag = false,
) {
// 1) Obtén el origen o falla si no existe
const origin = await this.origenRepo.findOne({ where: { origen } });
if (!origin) throw new Error(`Origen desconocido: ${origen}`);
const origin = await this.origenRepo.findOne({ where: { origen:fuente } });
if (!origin) throw new Error(`Origen desconocido: ${fuente}`);
// 2) Inserta directamente usando los campos de FK
await this.movRepo.insert({