se cambio función

This commit is contained in:
Emilio-11
2026-02-06 13:49:36 -06:00
parent a288c37531
commit 2e7d01552d
5 changed files with 234 additions and 262 deletions
+1 -2
View File
@@ -1,4 +1,3 @@
services: services:
database: database:
image: mariadb:latest image: mariadb:latest
@@ -12,7 +11,7 @@ services:
env_file: env_file:
- ../.env - ../.env
ports: ports:
- "${DB_PORT}:3306" - '${DB_PORT}:3306'
volumes: volumes:
- mariadb_data:/var/lib/mysql - mariadb_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql - ./init.sql:/docker-entrypoint-initdb.d/init.sql
+26 -36
View File
@@ -37,11 +37,10 @@ export class ExcelController {
private readonly movimientoService: MovimientoService, private readonly movimientoService: MovimientoService,
private readonly mailService: MailService, private readonly mailService: MailService,
private readonly usuarioService: UsuariosService, // Asegúrate de importar el servicio de correo private readonly usuarioService: UsuariosService, // Asegúrate de importar el servicio de correo
) { } ) {}
@Post('carga') @Post('carga')
async cargaUsuario(@Request() req, @Body() usuario: CreateUsuarioDto) { async cargaUsuario(@Request() req, @Body() usuario: CreateUsuarioDto) {
if (req.user.origen != 'LOAD' && req.user.origen != 'EXTERNO') { if (req.user.origen != 'LOAD' && req.user.origen != 'EXTERNO') {
throw new Error('Origen no permitido para carga'); throw new Error('Origen no permitido para carga');
} }
@@ -110,7 +109,11 @@ export class ExcelController {
@Post('load') @Post('load')
@UseInterceptors(FileInterceptor('file')) @UseInterceptors(FileInterceptor('file'))
@ExcelDocumentation.loadExcel() @ExcelDocumentation.loadExcel()
async loadExcel(@Request() req, @UploadedFile() file: Express.Multer.File, @Query('function') funcion?: number) { async loadExcel(
@Request() req,
@UploadedFile() file: Express.Multer.File,
@Query('function') funcion?: number,
) {
const origen = req.user.origen; // ahora sí existe const origen = req.user.origen; // ahora sí existe
if (origen != 'LOAD') { if (origen != 'LOAD') {
@@ -123,19 +126,12 @@ export class ExcelController {
} }
try { try {
let result; let result;
if(funcion==2){ if (funcion == 2) {
result = await this.excelService.loadFile2( result = await this.excelService.loadFile2(file.buffer, req.user.email);
file.buffer, } else {
req.user.email, result = await this.excelService.loadFile(file.buffer, req.user.email);
);
}else{
result = await this.excelService.loadFile(
file.buffer,
req.user.email,
);
} }
//Actualizar el estado de los movimientos //Actualizar el estado de los movimientos
if (!result) { if (!result) {
this.mailService.sendMail({ this.mailService.sendMail({
@@ -248,12 +244,10 @@ export class ExcelController {
'FAILED', 'FAILED',
'Origen no permitido para descarga', 'Origen no permitido para descarga',
); );
return res return res.status(HttpStatus.FORBIDDEN).json({
.status(HttpStatus.FORBIDDEN) statusCode: 403,
.json({ message: 'Origen no permitido para descarga.',
statusCode: 403, });
message: 'Origen no permitido para descarga.',
});
} }
} else if (origen == 'CORREO' || origen == 'LOAD') { } else if (origen == 'CORREO' || origen == 'LOAD') {
try { try {
@@ -334,17 +328,16 @@ export class ExcelController {
'FAILED', 'FAILED',
'Origen no permitido para descarga', 'Origen no permitido para descarga',
); );
return res return res.status(HttpStatus.FORBIDDEN).json({
.status(HttpStatus.FORBIDDEN) statusCode: 403,
.json({ message: 'Origen no permitido para descarga.',
statusCode: 403, });
message: 'Origen no permitido para descarga.',
});
} }
} }
//Agregarlo en su propio controller //Agregarlo en su propio controller
@Get('movimientos') @Get('movimientos')
@ExcelDocumentation.getMovimientos()
async getMovimientos( async getMovimientos(
@Request() req, @Request() req,
@Query('page') page: number, @Query('page') page: number,
@@ -369,18 +362,15 @@ export class ExcelController {
return { message: 'Servicios activados correctamente' }; return { message: 'Servicios activados correctamente' };
} }
@Get('cargaIndividual')
async cargarIndividual(@Request() req) {
const origen = req.user.origen; // ahora sí existe
return this.movimientoService.findAllCargaIndv(origen);
}
@Get('serv_act') @Get('serv_act')
async serv(){ async serv() {
return await this.excelService.buscaAct() return await this.excelService.buscaAct();
} }
@Post('mov/:id_movimiento')
async MOV(@Param('id_movimiento', ParseIntPipe) id_movimiento: number) {
return await this.movimientoService.findAllWithRelations(id_movimiento);
}
// @Delete() // @Delete()
// async borrar(){ // async borrar(){
// return await this.excelService.borrarUsers() // return await this.excelService.borrarUsers()
+81 -50
View File
@@ -1,16 +1,55 @@
import { applyDecorators } from '@nestjs/common'; import { applyDecorators } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiConsumes, ApiBody, ApiResponse } from '@nestjs/swagger'; import {
ApiTags,
ApiOperation,
ApiConsumes,
ApiBody,
ApiResponse,
ApiBearerAuth,
ApiQuery,
} from '@nestjs/swagger';
export class ExcelDocumentation { export class ExcelDocumentation {
/** static getMovimientos() {
* Decorators Swagger para el endpoint POST /excel/verify return applyDecorators(
*/ ApiBearerAuth(),
ApiOperation({
summary: 'Obtener movimientos',
description:
'Obtiene un listado paginado de movimientos según el origen del usuario autenticado.',
}),
ApiQuery({
name: 'page',
required: false,
type: Number,
example: 1,
description: 'Número de página',
}),
ApiQuery({
name: 'limit',
required: false,
type: Number,
example: 10,
description: 'Cantidad de registros por página',
}),
ApiResponse({
status: 200,
description: 'Listado de movimientos obtenido correctamente',
}),
ApiResponse({
status: 401,
description: 'No autorizado',
}),
);
}
static verifyExcel() { static verifyExcel() {
return applyDecorators( return applyDecorators(
ApiTags('Excel'), ApiTags('Excel'),
ApiOperation({ ApiOperation({
summary: 'Verificar archivo Excel', summary: 'Verificar archivo Excel',
description: 'Valida duplicados, filas en blanco y formato básico de los datos sin realizar carga en la base.' description:
'Valida duplicados, filas en blanco y formato básico de los datos sin realizar carga en la base.',
}), }),
ApiConsumes('multipart/form-data'), ApiConsumes('multipart/form-data'),
ApiBody({ ApiBody({
@@ -20,10 +59,10 @@ export class ExcelDocumentation {
file: { file: {
type: 'string', type: 'string',
format: 'binary', format: 'binary',
description: 'Archivo Excel (.xlsx) con usuarios a validar' description: 'Archivo Excel (.xlsx) con usuarios a validar',
} },
} },
} },
}), }),
ApiResponse({ ApiResponse({
status: 200, status: 200,
@@ -35,12 +74,18 @@ export class ExcelDocumentation {
errors: { errors: {
type: 'array', type: 'array',
items: { type: 'string' }, items: { type: 'string' },
example: ['Fila 2: cuenta duplicada "42515101".', 'Fila 3: fecha de nacimiento inválida "1988051".'] example: [
} 'Fila 2: cuenta duplicada "42515101".',
} 'Fila 3: fecha de nacimiento inválida "1988051".',
} ],
},
},
},
}),
ApiResponse({
status: 400,
description: 'No se recibió archivo o formato inválido.',
}), }),
ApiResponse({ status: 400, description: 'No se recibió archivo o formato inválido.' })
); );
} }
@@ -52,7 +97,8 @@ export class ExcelDocumentation {
ApiTags('Excel'), ApiTags('Excel'),
ApiOperation({ ApiOperation({
summary: 'Cargar archivo Excel', summary: 'Cargar archivo Excel',
description: 'Valida y persiste los datos en la base de datos. Retorna el número de registros insertados.' description:
'Valida y persiste los datos en la base de datos. Retorna el número de registros insertados.',
}), }),
ApiConsumes('multipart/form-data'), ApiConsumes('multipart/form-data'),
ApiBody({ ApiBody({
@@ -62,10 +108,10 @@ export class ExcelDocumentation {
file: { file: {
type: 'string', type: 'string',
format: 'binary', format: 'binary',
description: 'Archivo Excel (.xlsx) con usuarios a cargar' description: 'Archivo Excel (.xlsx) con usuarios a cargar',
} },
} },
} },
}), }),
ApiResponse({ ApiResponse({
status: 201, status: 201,
@@ -73,9 +119,9 @@ export class ExcelDocumentation {
schema: { schema: {
type: 'object', type: 'object',
properties: { properties: {
inserted: { type: 'number', example: 3 } inserted: { type: 'number', example: 3 },
} },
} },
}), }),
ApiResponse({ ApiResponse({
status: 400, status: 400,
@@ -86,52 +132,37 @@ export class ExcelDocumentation {
errors: { errors: {
type: 'array', type: 'array',
items: { type: 'string' }, items: { type: 'string' },
example: ['Fila 5: rfc contiene caracteres inválidos.'] example: ['Fila 5: rfc contiene caracteres inválidos.'],
} },
} },
} },
}) }),
); );
} }
static downloadExcel() { static downloadExcel() {
return applyDecorators( return applyDecorators(
ApiTags('Excel'), ApiTags('Excel'),
//ApiBearerAuth('bearer'), //ApiBearerAuth('bearer'),
ApiOperation({ ApiOperation({
summary: 'Descargar usuarios', summary: 'Descargar usuarios',
description: 'Exporta todos los usuarios en un archivo TSV (o CSV) y registra el movimiento.' description:
'Exporta todos los usuarios en un archivo TSV (o CSV) y registra el movimiento.',
}), }),
ApiResponse({ ApiResponse({
status: 200, status: 200,
description: 'TSV generado correctamente', description: 'TSV generado correctamente',
content: { content: {
'text/tab-separated-values': { 'text/tab-separated-values': {
schema: { type: 'string', example: 'num_cuenta\\tnombre\\t...\\n...' } schema: {
} type: 'string',
} example: 'num_cuenta\\tnombre\\t...\\n...',
},
},
},
}), }),
ApiResponse({ status: 401, description: 'No autorizado' }), ApiResponse({ status: 401, description: 'No autorizado' }),
ApiResponse({ status: 500, description: 'Error al generar descarga' }), ApiResponse({ status: 500, description: 'Error al generar descarga' }),
); );
} }
} }
+89 -137
View File
@@ -34,7 +34,6 @@ export interface UsuarioRow {
@Injectable() @Injectable()
export class ExcelService { export class ExcelService {
private readonly logger = new Logger(ExcelService.name); private readonly logger = new Logger(ExcelService.name);
constructor( constructor(
@@ -59,7 +58,7 @@ export class ExcelService {
private readonly dataSource: DataSource, private readonly dataSource: DataSource,
// … inyecta otros repositorios si los usarás // … inyecta otros repositorios si los usarás
) { } ) {}
/** Lee el buffer del Excel y devuelve un arreglo de filas tipadas */ /** Lee el buffer del Excel y devuelve un arreglo de filas tipadas */
private async parseFile(buffer: Buffer): Promise<UsuarioRow[]> { private async parseFile(buffer: Buffer): Promise<UsuarioRow[]> {
@@ -278,9 +277,8 @@ export class ExcelService {
// 🔹 3. Arreglos para inserciones masivas // 🔹 3. Arreglos para inserciones masivas
const usuarios: Usuario[] = []; const usuarios: Usuario[] = [];
const carrerasUsuario: CarreraUsuario[] = [];
const usuariosTipos: UsuarioTipoUsuario[] = []; const usuariosConRow: { usuario: Usuario; row: any }[] = [];
const serviciosActivos: ServActivos[] = [];
let contador = 0; let contador = 0;
@@ -345,50 +343,84 @@ export class ExcelService {
}); });
usuarios.push(usuario); usuarios.push(usuario);
usuariosConRow.push({ usuario, row: r });
}
await queryRunner.manager.save([...mapGenero.values()]);
await queryRunner.manager.save([...mapCarreraClave.values()]);
await queryRunner.manager.save([...mapTipo.values()]);
await queryRunner.manager.save(usuarios);
const carrerasUsuarioFinal: CarreraUsuario[] = [];
for (const { usuario, row } of usuariosConRow) {
const carrera =
(row.clave && mapCarreraClave.get(row.clave)) ||
(row.nomCarr && mapCarreraNom.get(row.nomCarr));
if (carrera) { if (carrera) {
const carreraUsuario = queryRunner.manager.create(CarreraUsuario, { carrerasUsuarioFinal.push(
usuario, queryRunner.manager.create(CarreraUsuario, {
carrera, usuario,
}); carrera,
carrerasUsuario.push(carreraUsuario); }),
);
} }
}
usuariosTipos.push( await queryRunner.manager.save(carrerasUsuarioFinal);
const usuariosTiposFinal: UsuarioTipoUsuario[] = [];
for (const { usuario, row } of usuariosConRow) {
const tipo = mapTipo.get(row.tipo.trim());
if (!tipo) continue;
usuariosTiposFinal.push(
queryRunner.manager.create(UsuarioTipoUsuario, { queryRunner.manager.create(UsuarioTipoUsuario, {
usuario, usuario,
tipoUsuario: tipo, tipoUsuario: tipo,
}), }),
); );
}
// Servicios activos await queryRunner.manager.save(usuariosTiposFinal);
const servData: Partial<ServActivos> = {
const serviciosActivosFinal: ServActivos[] = [];
for (const { usuario, row } of usuariosConRow) {
const serv = queryRunner.manager.create(ServActivos, {
usuario, usuario,
Red: false,
AT: false,
Correo: false,
Prestamos: false,
RedStatus: 'Inactivo', RedStatus: 'Inactivo',
ATStatus: 'Inactivo', ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo', CorreoStatus: 'Inactivo',
PrestamosStatus: 'Inactivo', PrestamosStatus: 'Inactivo',
}; });
switch (r.tipo.trim()) { switch (row.tipo.trim()) {
case 'Diplomado': case 'Diplomado':
Object.assign(servData, { Correo: true }); Object.assign(serv, { Correo: true });
conteoTiposCorreo++; conteoTiposCorreo++;
break; break;
case 'Extra Largo': case 'Extra Largo':
Object.assign(servData, { Correo: true, Prestamos: true }); Object.assign(serv, { Correo: true, Prestamos: true });
conteoTiposCorreo++; conteoTiposCorreo++;
conteoTiposSolicita++; conteoTiposSolicita++;
break; break;
case 'Servicio Social': case 'Servicio Social':
Object.assign(servData, { Correo: true, AT: true, Red: true }); Object.assign(serv, { Correo: true, AT: true, Red: true });
conteoTiposCorreo++; conteoTiposCorreo++;
conteoTiposAt++; conteoTiposAt++;
conteoTiposRed++; conteoTiposRed++;
break; break;
case 'Idiomas R (UNAM)': case 'Idiomas R (UNAM)':
case 'Idiomas Sabatino': case 'Idiomas Sabatino':
Object.assign(servData, { Correo: true, Red: true }); Object.assign(serv, { Correo: true, Red: true });
conteoTiposCorreo++; conteoTiposCorreo++;
conteoTiposRed++; conteoTiposRed++;
break; break;
@@ -399,7 +431,7 @@ export class ExcelService {
case 'Ampliación de Conocimiento': case 'Ampliación de Conocimiento':
case 'Licenciatura': case 'Licenciatura':
case 'Profesor': case 'Profesor':
Object.assign(servData, { Object.assign(serv, {
Correo: true, Correo: true,
AT: true, AT: true,
Red: true, Red: true,
@@ -411,79 +443,17 @@ export class ExcelService {
conteoTiposSolicita++; conteoTiposSolicita++;
break; break;
case 'Trabajadores': case 'Trabajadores':
Object.assign(servData, { Red: true }); Object.assign(serv, { Red: true });
conteoTiposRed++; conteoTiposRed++;
break; break;
} }
serviciosActivos.push( serviciosActivosFinal.push(serv);
queryRunner.manager.create(ServActivos, servData),
);
} }
// 🔹 4. Guardar en batch (orden correcto)
await queryRunner.manager.save([...mapGenero.values()]);
await queryRunner.manager.save([...mapCarreraClave.values()]);
await queryRunner.manager.save([...mapTipo.values()]);
// 1️⃣ Guardar usuarios primero — asigna IDs
await queryRunner.manager.save(usuarios);
// 2️⃣ Reconstruir relaciones con usuarios ya guardados
// CarreraUsuario
const carrerasUsuarioFinal: CarreraUsuario[] = [];
for (const cu of carrerasUsuario) {
const usuarioConId = usuarios.find(
(u) => u.num_cuenta === cu.usuario.num_cuenta,
);
if (usuarioConId && cu.carrera) {
carrerasUsuarioFinal.push(
queryRunner.manager.create(CarreraUsuario, {
usuario: usuarioConId,
carrera: cu.carrera,
}),
);
}
}
// UsuarioTipoUsuario
const usuariosTiposFinal: UsuarioTipoUsuario[] = [];
for (const ut of usuariosTipos) {
const usuarioConId = usuarios.find(
(u) => u.num_cuenta === ut.usuario.num_cuenta,
);
if (usuarioConId && ut.tipoUsuario) {
usuariosTiposFinal.push(
queryRunner.manager.create(UsuarioTipoUsuario, {
usuario: usuarioConId,
tipoUsuario: ut.tipoUsuario,
}),
);
}
}
// ServActivos
const serviciosActivosFinal: ServActivos[] = [];
for (const sa of serviciosActivos) {
const usuarioConId = usuarios.find(
(u) => u.num_cuenta === sa.usuario.num_cuenta,
);
if (usuarioConId) {
serviciosActivosFinal.push(
queryRunner.manager.create(ServActivos, {
...sa,
usuario: usuarioConId,
}),
);
}
}
// 3️⃣ Guardar relaciones dependientes en orden
await queryRunner.manager.save(carrerasUsuarioFinal);
await queryRunner.manager.save(usuariosTiposFinal);
await queryRunner.manager.save(serviciosActivosFinal); await queryRunner.manager.save(serviciosActivosFinal);
await queryRunner.commitTransaction();
return { return {
inserted: rows.length - contador, inserted: rows.length - contador,
id_movimiento: movimiento.id_mov, id_movimiento: movimiento.id_mov,
@@ -507,9 +477,6 @@ export class ExcelService {
const errs = status.errors; const errs = status.errors;
const rows = status.rowsGood; const rows = status.rowsGood;
if (rows.length === 0) { if (rows.length === 0) {
throw new BadRequestException( throw new BadRequestException(
'No se encontraron filas válidas para cargar. ' + errs, 'No se encontraron filas válidas para cargar. ' + errs,
@@ -524,7 +491,7 @@ export class ExcelService {
const queryRunner = this.dataSource.createQueryRunner(); const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
await queryRunner.startTransaction(); await queryRunner.startTransaction();
let idsUsuarios: number[] =[] let idsUsuarios: number[] = [];
try { try {
const movimiento = await this.movimientoService.logger( const movimiento = await this.movimientoService.logger(
queryRunner, queryRunner,
@@ -587,12 +554,13 @@ export class ExcelService {
const serviciosActivos: ServActivos[] = []; const serviciosActivos: ServActivos[] = [];
let contador = 0; let contador = 0;
for (const r of rows) { for (const r of rows) {
if (setCuentas.has(r.cuenta) || (r.rfc && setRfcs.has(r.rfc))) { if (setCuentas.has(r.cuenta) || (r.rfc && setRfcs.has(r.rfc))) {
const use= existentes.find( u => u.num_cuenta === r.cuenta || u.rfc === r.rfc) const use = existentes.find(
if(use?.id_usuario) (u) => u.num_cuenta === r.cuenta || u.rfc === r.rfc,
idsUsuarios.push(use?.id_usuario) );
if (use?.id_usuario) idsUsuarios.push(use?.id_usuario);
contador++; contador++;
continue; continue;
} }
@@ -651,7 +619,7 @@ export class ExcelService {
}); });
usuarios.push(usuario); usuarios.push(usuario);
if (carrera) { if (carrera) {
const carreraUsuario = queryRunner.manager.create(CarreraUsuario, { const carreraUsuario = queryRunner.manager.create(CarreraUsuario, {
usuario, usuario,
@@ -734,10 +702,8 @@ export class ExcelService {
// 1️⃣ Guardar usuarios primero — asigna IDs // 1️⃣ Guardar usuarios primero — asigna IDs
await queryRunner.manager.save(usuarios); await queryRunner.manager.save(usuarios);
idsUsuarios = usuarios.map(u => u.id_usuario); idsUsuarios = usuarios.map((u) => u.id_usuario);
idsUsuarios.push( idsUsuarios.push(...existentes.map((e) => e.id_usuario));
...existentes.map(e => e.id_usuario)
);
// 2️⃣ Reconstruir relaciones con usuarios ya guardados // 2️⃣ Reconstruir relaciones con usuarios ya guardados
// CarreraUsuario // CarreraUsuario
@@ -793,11 +759,6 @@ export class ExcelService {
await queryRunner.manager.save(usuariosTiposFinal); await queryRunner.manager.save(usuariosTiposFinal);
await queryRunner.manager.save(serviciosActivosFinal); await queryRunner.manager.save(serviciosActivosFinal);
return { return {
inserted: rows.length - contador, inserted: rows.length - contador,
id_movimiento: movimiento.id_mov, id_movimiento: movimiento.id_mov,
@@ -812,26 +773,22 @@ export class ExcelService {
throw err; throw err;
} finally { } finally {
await queryRunner.release(); await queryRunner.release();
await this.servActivosRepo await this.servActivosRepo
.createQueryBuilder() .createQueryBuilder()
.update() .update()
.set({ .set({
Red: false, Red: false,
Prestamos: false, Prestamos: false,
AT: false, AT: false,
Correo: false, Correo: false,
RedStatus: 'Inactivo', RedStatus: 'Inactivo',
PrestamosStatus: 'Inactivo', PrestamosStatus: 'Inactivo',
ATStatus: 'Inactivo', ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo', CorreoStatus: 'Inactivo',
}) })
.where('id_usuario NOT IN (:...ids)', { ids: idsUsuarios }) .where('id_usuario NOT IN (:...ids)', { ids: idsUsuarios })
.execute(); .execute();
} }
} }
@@ -1210,7 +1167,6 @@ export class ExcelService {
'Carga de Usuarios', 'Carga de Usuarios',
`Se ha realizado una carga de usuarios en el sistema. Nuevos: ${data?.nuevos ?? 0}, Actualizados: ${data?.actualizados ?? 0}`, `Se ha realizado una carga de usuarios en el sistema. Nuevos: ${data?.nuevos ?? 0}, Actualizados: ${data?.actualizados ?? 0}`,
); );
} }
async enviarInforme( async enviarInforme(
@@ -1238,18 +1194,14 @@ export class ExcelService {
} }
} }
async buscaAct() { async buscaAct() {
return await this.servActivosRepo.find({ return await this.servActivosRepo.find({
where: [ where: [
{ AT: true }, { AT: true },
{ Correo: true }, { Correo: true },
{ Prestamos: true }, { Prestamos: true },
{ Red: true }, { Red: true },
], ],
}); });
} }
} }
+37 -37
View File
@@ -13,7 +13,7 @@ export class MovimientoService {
private readonly origenRepo: Repository<Origen>, private readonly origenRepo: Repository<Origen>,
@InjectRepository(Usuario) @InjectRepository(Usuario)
private readonly usuarioRepo: Repository<Usuario>, private readonly usuarioRepo: Repository<Usuario>,
) { } ) {}
/** Crea un registro de movimiento */ /** Crea un registro de movimiento */
async log( async log(
@@ -54,7 +54,7 @@ export class MovimientoService {
origenNombre: string, origenNombre: string,
status: string, status: string,
observaciones?: string, observaciones?: string,
reporte?: string reporte?: string,
): Promise<Movimiento> { ): Promise<Movimiento> {
const origenEntidad = await queryRunner.manager.findOne(Origen, { const origenEntidad = await queryRunner.manager.findOne(Origen, {
where: { origen: origenNombre }, where: { origen: origenNombre },
@@ -76,17 +76,21 @@ export class MovimientoService {
return await queryRunner.manager.save(nuevoMov); return await queryRunner.manager.save(nuevoMov);
} }
/** Actualiza el status de un movimiento existente */ /** Actualiza el status de un movimiento existente */
async updateStatus(id_movimiento: number, nuevoStatus: string, observaciones?: string): Promise<void> { async updateStatus(
const movimiento = await this.movRepo.findOne({ where: { id_mov: id_movimiento } }); id_movimiento: number,
nuevoStatus: string,
observaciones?: string,
): Promise<void> {
const movimiento = await this.movRepo.findOne({
where: { id_mov: id_movimiento },
});
if (!movimiento) { if (!movimiento) {
throw new Error(`Movimiento con ID ${id_movimiento} no encontrado`); throw new Error(`Movimiento con ID ${id_movimiento} no encontrado`);
} }
console.log('movimiento' + movimiento);
movimiento.status = nuevoStatus; movimiento.status = nuevoStatus;
movimiento.observaciones = observaciones || movimiento.observaciones; // opcional: actualizar observaciones movimiento.observaciones = observaciones || movimiento.observaciones; // opcional: actualizar observaciones
movimiento.fecha_mov = new Date(); // opcional: actualizar fecha movimiento.fecha_mov = new Date(); // opcional: actualizar fecha
@@ -98,8 +102,12 @@ export class MovimientoService {
origen: string, origen: string,
page: number = 1, page: number = 1,
limit: number = 10, limit: number = 10,
): Promise<{ move: any[]; button: boolean; total?: number; lastPage?: number }> { ): Promise<{
move: any[];
button: boolean;
total?: number;
lastPage?: number;
}> {
if (origen === 'LOAD') { if (origen === 'LOAD') {
const [movimientos, total] = await this.movRepo.findAndCount({ const [movimientos, total] = await this.movRepo.findAndCount({
where: { where: {
@@ -136,8 +144,6 @@ export class MovimientoService {
SOLICITA: 'Prestamos', SOLICITA: 'Prestamos',
} as const; } as const;
const field = statusFieldMap[origen as keyof typeof statusFieldMap]; const field = statusFieldMap[origen as keyof typeof statusFieldMap];
const origenField = FieldMap[origen as keyof typeof FieldMap]; const origenField = FieldMap[origen as keyof typeof FieldMap];
@@ -147,7 +153,6 @@ export class MovimientoService {
origen: { origen: 'LOAD' }, origen: { origen: 'LOAD' },
status: 'SUCCESS', status: 'SUCCESS',
reporte: 'CARGA MASIVA DE USUARIOS', reporte: 'CARGA MASIVA DE USUARIOS',
}, },
}); });
@@ -156,23 +161,16 @@ export class MovimientoService {
origen: { origen: 'SISTEMA' }, origen: { origen: 'SISTEMA' },
status: 'SUCCESS', status: 'SUCCESS',
reporte: 'CARGA MASIVA WEB SERVICE', reporte: 'CARGA MASIVA WEB SERVICE',
}, },
}); });
const mov2 = await this.movRepo.find({ const mov2 = await this.movRepo.find({
where: { where: {
reporte: 'CARGA INDIVIDUAL DE USUARIOS', reporte: 'CARGA INDIVIDUAL DE USUARIOS',
status: 'SUCCESS', status: 'SUCCESS',
}, },
}); });
const todosLosMovimientos = [...movimientos, ...mov, ...mov2]; const todosLosMovimientos = [...movimientos, ...mov, ...mov2];
return { move: todosLosMovimientos, button: false }; return { move: todosLosMovimientos, button: false };
} }
@@ -186,7 +184,7 @@ export class MovimientoService {
servActivo: { servActivo: {
[origenField]: true, [origenField]: true,
[field]: 'Inactivo' [field]: 'Inactivo',
}, },
}, },
}, },
@@ -199,20 +197,19 @@ export class MovimientoService {
usuario: { usuario: {
servActivo: { servActivo: {
[origenField]: true, [origenField]: true,
[field]: 'Inactivo' [field]: 'Inactivo',
}, },
}, },
}, },
}); });
const mov2 = await this.movRepo.find({ const mov2 = await this.movRepo.find({
where: { where: {
reporte: 'CARGA INDIVIDUAL DE USUARIOS', reporte: 'CARGA INDIVIDUAL DE USUARIOS',
status: 'SUCCESS', status: 'SUCCESS',
usuario: { usuario: {
servActivo: { servActivo: {
[origenField]: true, [origenField]: true,
[field]: 'Inactivo' [field]: 'Inactivo',
}, },
}, },
}, },
@@ -224,7 +221,6 @@ export class MovimientoService {
} }
async findAllCargaIndv(origen): Promise<Usuario[]> { async findAllCargaIndv(origen): Promise<Usuario[]> {
const statusFieldMap = { const statusFieldMap = {
AT: 'ATStatus', AT: 'ATStatus',
RED: 'RedStatus', RED: 'RedStatus',
@@ -239,10 +235,6 @@ export class MovimientoService {
SOLICITA: 'Prestamos', SOLICITA: 'Prestamos',
} as const; } as const;
const field = statusFieldMap[origen as keyof typeof statusFieldMap]; const field = statusFieldMap[origen as keyof typeof statusFieldMap];
const origenField = FieldMap[origen as keyof typeof FieldMap]; const origenField = FieldMap[origen as keyof typeof FieldMap];
@@ -254,7 +246,6 @@ export class MovimientoService {
const usuarios = await this.usuarioRepo.find({ const usuarios = await this.usuarioRepo.find({
where: { where: {
movimiento: { movimiento: {
reporte: 'CARGA INDIVIDUAL DE USUARIOS', reporte: 'CARGA INDIVIDUAL DE USUARIOS',
}, },
@@ -262,18 +253,27 @@ export class MovimientoService {
[field]: 'Inactivo', [field]: 'Inactivo',
[origenField]: true, [origenField]: true,
}, },
}, },
}); });
return usuarios; return usuarios;
} }
async findAllWithRelations(id: number): Promise<Movimiento[]> {
return await this.movRepo.find({
where: { id_mov: id },
relations: [
'usuario',
'origen',
'usuario.servActivo',
'usuario.carreraUsuarios',
'usuario.carreraUsuarios.carrera',
'usuario.usuarioTipos',
'usuario.usuarioTipos.tipoUsuario',
],
order: {
fecha_mov: 'DESC',
},
});
}
} }