se cambio la descarga de a csv y subida de archivos
This commit is contained in:
@@ -148,13 +148,13 @@ export class ExcelController {
|
||||
|
||||
origen,
|
||||
'SUCCESS',
|
||||
undefined,
|
||||
'descarga de csv',
|
||||
`size=${csv.length}`
|
||||
);
|
||||
return res
|
||||
.status(HttpStatus.OK)
|
||||
.header('Content-Type', 'text/tab-separated-values')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_solicita.tsv"')
|
||||
.header('Content-Type', 'text/csv')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_solicita.csv"')
|
||||
.send(csv);
|
||||
} catch (err) {
|
||||
await this.movimientoService.log(
|
||||
@@ -166,20 +166,20 @@ export class ExcelController {
|
||||
.status(HttpStatus.FORBIDDEN)
|
||||
.json({ statusCode: 403, message: 'Origen no permitido para descarga.' });
|
||||
}
|
||||
} else if (origen == 'CORREO') {
|
||||
} else if (origen == 'CORREO' || origen == 'LOAD') {
|
||||
try {
|
||||
const csv = await this.excelService.generateCsvCorreo();
|
||||
await this.movimientoService.log(
|
||||
|
||||
origen,
|
||||
'SUCCESS',
|
||||
undefined,
|
||||
'descarga de csv',
|
||||
`size=${csv.length}`
|
||||
);
|
||||
return res
|
||||
.status(HttpStatus.OK)
|
||||
.header('Content-Type', 'text/tab-separated-values')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios.tsv"')
|
||||
.header('Content-Type', 'text/csv')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_correo.csv"')
|
||||
.send(csv);
|
||||
} catch (err) {
|
||||
await this.movimientoService.log(
|
||||
@@ -199,13 +199,13 @@ export class ExcelController {
|
||||
|
||||
origen,
|
||||
'SUCCESS',
|
||||
undefined,
|
||||
'descarga de csv',
|
||||
`size=${csv.length}`
|
||||
);
|
||||
return res
|
||||
.status(HttpStatus.OK)
|
||||
.header('Content-Type', 'text/tab-separated-values')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_at.tsv"')
|
||||
.header('Content-Type', 'text/csv')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_AT.csv"')
|
||||
.send(csv);
|
||||
} catch (err) {
|
||||
await this.movimientoService.log(
|
||||
@@ -225,13 +225,13 @@ export class ExcelController {
|
||||
|
||||
origen,
|
||||
'SUCCESS',
|
||||
undefined,
|
||||
'descarga de csv',
|
||||
`size=${csv.length}`
|
||||
);
|
||||
return res
|
||||
.status(HttpStatus.OK)
|
||||
.header('Content-Type', 'text/tab-separated-values')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_red.tsv"')
|
||||
.header('Content-Type', 'text/csv')
|
||||
.header('Content-Disposition', 'attachment; filename="usuarios_red.csv"')
|
||||
.send(csv);
|
||||
} catch (err) {
|
||||
await this.movimientoService.log(
|
||||
|
||||
+171
-219
@@ -1,7 +1,7 @@
|
||||
// src/excel/excel.service.ts
|
||||
import { Injectable, BadRequestException, Logger } from '@nestjs/common';
|
||||
import { Workbook } from 'exceljs';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { DataSource, In, Repository } from 'typeorm';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { CarreraUsuario, TipoUsuario, Usuario, UsuariosDelSistema, UsuarioTipoUsuario } from '../entities/entities';
|
||||
import { Genero } from '../entities/entities';
|
||||
@@ -48,7 +48,8 @@ export class ExcelService {
|
||||
@InjectRepository(UsuariosDelSistema)
|
||||
private readonly usuariosDelSistemaRepo: Repository<UsuariosDelSistema>,
|
||||
private readonly movimientoService: MovimientoService,
|
||||
private readonly mailService: MailService
|
||||
private readonly mailService: MailService,
|
||||
private readonly dataSource: DataSource
|
||||
|
||||
// … inyecta otros repositorios si los usarás
|
||||
) { }
|
||||
@@ -118,7 +119,7 @@ export class ExcelService {
|
||||
const rowNum = i + 2; // por el encabezado
|
||||
|
||||
// Campos que no pueden quedar vacíos
|
||||
['cuenta', 'nombreCompleto', 'tipo'].forEach(field => {
|
||||
['cuenta', 'tipo'].forEach(field => {
|
||||
const raw = (r as any)[field];
|
||||
const str = raw != null ? raw.toString().trim() : '';
|
||||
if (!str) {
|
||||
@@ -144,7 +145,7 @@ export class ExcelService {
|
||||
seen.add(cuentaStr);
|
||||
}
|
||||
|
||||
// Numérico en cuenta y generación
|
||||
|
||||
|
||||
|
||||
const genStr = r.gen != null ? r.gen.toString().trim() : '';
|
||||
@@ -201,215 +202,166 @@ export class ExcelService {
|
||||
const status = this.validateRows(file);
|
||||
const errs = status.errors;
|
||||
const rows = status.rowsGood;
|
||||
let carga
|
||||
if (rows.length == 0) {
|
||||
|
||||
if (rows.length === 0) {
|
||||
throw new BadRequestException('No se encontraron filas válidas para cargar. ' + errs);
|
||||
}
|
||||
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
const movimiento = await this.movimientoService.log(
|
||||
try {
|
||||
const movimiento = await this.movimientoService.logger(
|
||||
queryRunner,
|
||||
'LOAD',
|
||||
'LOADING',
|
||||
undefined,
|
||||
'CARGA MASIVA DE USUARIOS'
|
||||
);
|
||||
|
||||
'LOAD',
|
||||
'LOADING',
|
||||
undefined,
|
||||
`CARGA MASIVA DE USUARIOS`,
|
||||
true, // flag para indicar que es una carga masiva
|
||||
);
|
||||
let contador = 0;
|
||||
|
||||
for (const r of rows) {
|
||||
|
||||
const whereCond: Array<{ num_cuenta?: string; rfc?: string }> = [{ num_cuenta: r.cuenta }];
|
||||
if (r.rfc) {
|
||||
whereCond.push({ rfc: r.rfc });
|
||||
}
|
||||
|
||||
let contador: number = 0;
|
||||
|
||||
for (const r of rows) {
|
||||
//0.1
|
||||
const userExists = await this.usuarioRepo.findOne({
|
||||
where: { num_cuenta: r.cuenta },
|
||||
});
|
||||
|
||||
if (userExists) {
|
||||
errs.push(`Cuenta ${r.cuenta} ya existe, se omite.`);
|
||||
contador++;
|
||||
continue; // si ya existe, no lo insertamos
|
||||
}
|
||||
|
||||
|
||||
// 1) Género (crea o reutiliza)
|
||||
let genero = await this.generoRepo.findOne({ where: { genero: r.sexo } });
|
||||
if (!genero) {
|
||||
genero = this.generoRepo.create({ genero: r.sexo });
|
||||
await this.generoRepo.save(genero);
|
||||
}
|
||||
|
||||
// 2) Carrera (por clave)
|
||||
let carrera = await this.carreraRepo.findOne({
|
||||
where: { clave: r.clave },
|
||||
});
|
||||
if (!carrera) {
|
||||
carrera = this.carreraRepo.create({
|
||||
clave: r.clave,
|
||||
carrera: r.nomCarr.slice(0, 100),
|
||||
const userExists = await queryRunner.manager.findOne(Usuario, {
|
||||
where: whereCond,
|
||||
});
|
||||
await this.carreraRepo.save(carrera);
|
||||
}
|
||||
|
||||
let tipo = await this.tipoUsuarioRepo.findOne({
|
||||
where: { tipo_usuario: r.tipo.trim() },
|
||||
});
|
||||
if (!tipo) {
|
||||
tipo = this.tipoUsuarioRepo.create({
|
||||
tipo_usuario: r.tipo.trim(),
|
||||
|
||||
|
||||
if (userExists) {
|
||||
errs.push(`Cuenta ${r.cuenta} ya existe, se omite.`);
|
||||
contador++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!r.tipo || !r.nombres || !r.apellidopa || !r.apellidoma) {
|
||||
errs.push(`Fila con cuenta ${r.cuenta} tiene campos faltantes.`);
|
||||
contador++;
|
||||
continue;
|
||||
}
|
||||
|
||||
let genero = await queryRunner.manager.findOne(Genero, { where: { genero: r.sexo } });
|
||||
if (!genero) {
|
||||
genero = queryRunner.manager.create(Genero, { genero: r.sexo });
|
||||
await queryRunner.manager.save(genero);
|
||||
}
|
||||
|
||||
let carrera
|
||||
if (r.clave || r.nomCarr) {
|
||||
carrera = await queryRunner.manager.findOne(Carrera, { where: { clave: r.clave } });
|
||||
if (!carrera) {
|
||||
carrera = queryRunner.manager.create(Carrera, {
|
||||
clave: r.clave,
|
||||
carrera: r.nomCarr.slice(0, 100),
|
||||
});
|
||||
await queryRunner.manager.save(carrera);
|
||||
}
|
||||
|
||||
} else {
|
||||
carrera = null;
|
||||
}
|
||||
|
||||
let tipo = await queryRunner.manager.findOne(TipoUsuario, {
|
||||
where: { tipo_usuario: r.tipo.trim() },
|
||||
});
|
||||
await this.tipoUsuarioRepo.save(tipo);
|
||||
if (!tipo) {
|
||||
tipo = queryRunner.manager.create(TipoUsuario, { tipo_usuario: r.tipo.trim() });
|
||||
await queryRunner.manager.save(tipo);
|
||||
}
|
||||
|
||||
const generacion = /^[0-9]{4}$/.test(r.gen?.toString().trim())
|
||||
? parseInt(r.gen.toString().trim(), 10)
|
||||
: null;
|
||||
|
||||
const usuario = queryRunner.manager.create(Usuario, {
|
||||
num_cuenta: r.cuenta,
|
||||
nombre: r.nombres.trim().split(' ')[0],
|
||||
a_paterno: r.apellidopa,
|
||||
a_materno: r.apellidoma,
|
||||
rfc: r.rfc,
|
||||
fecha_nacimiento: r.fechnac,
|
||||
generacion,
|
||||
genero,
|
||||
movimiento,
|
||||
});
|
||||
const user = await queryRunner.manager.save(usuario);
|
||||
|
||||
if (carrera) {
|
||||
const carreraUsuario = queryRunner.manager.create(CarreraUsuario, {
|
||||
usuario: user,
|
||||
carrera,
|
||||
});
|
||||
await queryRunner.manager.save(carreraUsuario);
|
||||
}
|
||||
|
||||
const usuarioTipo = queryRunner.manager.create(UsuarioTipoUsuario, {
|
||||
usuario: user,
|
||||
tipoUsuario: tipo,
|
||||
});
|
||||
await queryRunner.manager.save(usuarioTipo);
|
||||
|
||||
const servData = {
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
ATStatus: 'Inactivo',
|
||||
CorreoStatus: 'Inactivo',
|
||||
PrestamosStatus: 'Inactivo',
|
||||
};
|
||||
|
||||
switch (r.tipo.trim()) {
|
||||
case 'Diplomado':
|
||||
Object.assign(servData, { Correo: true });
|
||||
break;
|
||||
case 'Extra Largo':
|
||||
Object.assign(servData, { Correo: true, Prestamos: true });
|
||||
break;
|
||||
case 'Servicio Social':
|
||||
Object.assign(servData, { Correo: true, AT: true, Red: true });
|
||||
break;
|
||||
case 'Idiomas R (UNAM)':
|
||||
case 'Idiomas Sabatino':
|
||||
Object.assign(servData, { Correo: true, Red: true });
|
||||
break;
|
||||
case 'Reinscrito':
|
||||
case 'Posgrado':
|
||||
case 'Intercambio UNAM':
|
||||
case 'Movilidad':
|
||||
case 'Ampliación de Conocimiento':
|
||||
case 'Licenciatura':
|
||||
case 'Profesor':
|
||||
Object.assign(servData, { Correo: true, AT: true, Red: true, Prestamos: true });
|
||||
break;
|
||||
case 'Trabajadores':
|
||||
Object.assign(servData, { Red: true });
|
||||
break;
|
||||
}
|
||||
|
||||
const serv = queryRunner.manager.create(ServActivos, servData);
|
||||
await queryRunner.manager.save(serv);
|
||||
}
|
||||
|
||||
const generacion = /^[0-9]{4}$/.test(r.gen?.toString().trim())
|
||||
? parseInt(r.gen.toString().trim(), 10)
|
||||
: null;
|
||||
|
||||
|
||||
// 3) Usuario
|
||||
const usuario = this.usuarioRepo.create({
|
||||
num_cuenta: r.cuenta,
|
||||
nombre: r.nombres.trim().split(' ')[0], // ajusta si quieres
|
||||
a_paterno: r.apellidopa,
|
||||
a_materno: r.apellidoma,
|
||||
rfc: r.rfc,
|
||||
fecha_nacimiento: r.fechnac,
|
||||
generacion: generacion,
|
||||
genero,
|
||||
movimiento: { id_mov: movimiento.id_mov }, // Relación con movimiento
|
||||
|
||||
});
|
||||
const user = await this.usuarioRepo.save(usuario);
|
||||
|
||||
|
||||
|
||||
// 4) Relacion usuario–carrxera (tabla intermedia)
|
||||
const carreraUsuario = this.carreraUsuarioRepo.create({
|
||||
usuario,
|
||||
carrera,
|
||||
});
|
||||
await this.carreraUsuarioRepo.save(carreraUsuario);
|
||||
|
||||
// 5) Tipo de usuario
|
||||
|
||||
const usuarioTipo = this.usuarioTipoUsuarioRepo.create({
|
||||
usuario,
|
||||
tipoUsuario: tipo,
|
||||
});
|
||||
await this.usuarioTipoUsuarioRepo.save(usuarioTipo);
|
||||
|
||||
// 6) ServActivos (si es necesario)
|
||||
switch (r.tipo.trim()) {
|
||||
|
||||
case 'Diplomado':
|
||||
const servActivosDiplomado = this.servActivosRepo.create({
|
||||
Correo: true,
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
ATStatus: 'Inactivo',
|
||||
CorreoStatus: 'Inactivo',
|
||||
PrestamosStatus: 'Inactivo',
|
||||
});
|
||||
await this.servActivosRepo.save(servActivosDiplomado);
|
||||
|
||||
break;
|
||||
|
||||
case 'Extra Largo':
|
||||
const servActivosExtraLargo = this.servActivosRepo.create({
|
||||
Prestamos: true,
|
||||
Correo: true,
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
ATStatus: 'Inactivo',
|
||||
CorreoStatus: 'Inactivo',
|
||||
PrestamosStatus: 'Inactivo',
|
||||
});
|
||||
await this.servActivosRepo.save(servActivosExtraLargo);
|
||||
break;
|
||||
|
||||
case 'Servicio Social':
|
||||
const servActivosServicio = this.servActivosRepo.create({
|
||||
Red: true,
|
||||
AT: true,
|
||||
Correo: true,
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
ATStatus: 'Inactivo',
|
||||
CorreoStatus: 'Inactivo',
|
||||
PrestamosStatus: 'Inactivo',
|
||||
});
|
||||
await this.servActivosRepo.save(servActivosServicio);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'Idiomas R (UNAM)':
|
||||
case 'Idiomas Sabatino':
|
||||
const servActivosIdiomas = this.servActivosRepo.create({
|
||||
Red: true,
|
||||
Correo: true,
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
ATStatus: 'Inactivo',
|
||||
CorreoStatus: 'Inactivo',
|
||||
PrestamosStatus: 'Inactivo',
|
||||
});
|
||||
await this.servActivosRepo.save(servActivosIdiomas);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case 'Reinscrito':
|
||||
case 'Posgrado':
|
||||
case 'Intercambio UNAM':
|
||||
case 'Movilidad':
|
||||
case 'Ampliación de Conocimiento':
|
||||
case 'Licenciatura':
|
||||
case 'Profesor':
|
||||
const servActivos = this.servActivosRepo.create({
|
||||
|
||||
Red: true,
|
||||
AT: true,
|
||||
Correo: true,
|
||||
Prestamos: true,
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
ATStatus: 'Inactivo',
|
||||
CorreoStatus: 'Inactivo',
|
||||
PrestamosStatus: 'Inactivo',
|
||||
});
|
||||
await this.servActivosRepo.save(servActivos);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'Trabajadores':
|
||||
const servActivosTrabajadores = this.servActivosRepo.create({
|
||||
Red: true,
|
||||
usuario: user,
|
||||
RedStatus: 'Inactivo',
|
||||
|
||||
});
|
||||
await this.servActivosRepo.save(servActivosTrabajadores);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return { inserted: rows.length - contador, id_movimiento: movimiento.id_mov, errors: errs };
|
||||
} catch (err) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw err;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return { inserted: rows.length - contador, id_movimiento: movimiento.id_mov, errors: errs };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// async generateCsv(): Promise<string> {
|
||||
// const users = await this.usuarioRepo.find({
|
||||
// relations: ['genero', 'carreraUsuarios'], // si quieres más info
|
||||
@@ -483,7 +435,7 @@ export class ExcelService {
|
||||
const header = [
|
||||
'num_cuenta', 'nombre', 'a_paterno', 'a_materno',
|
||||
'carreras', 'rfc', 'fecha_nacimiento', 'generacion'
|
||||
].join('\t') + '\n';
|
||||
].join(',') + '\n';
|
||||
|
||||
const rows = usuarios.map(u => {
|
||||
const carreras = (u.carreraUsuarios ?? [])
|
||||
@@ -491,15 +443,15 @@ export class ExcelService {
|
||||
.join(', '); // une todas las carreras en un solo string
|
||||
|
||||
return [
|
||||
u.num_cuenta,
|
||||
u.nombre,
|
||||
u.a_paterno,
|
||||
u.a_materno,
|
||||
carreras,
|
||||
u.num_cuenta ?? '',
|
||||
u.nombre ?? '',
|
||||
u.a_paterno ?? '',
|
||||
u.a_materno ?? '',
|
||||
carreras ?? '',
|
||||
u.rfc ?? '',
|
||||
u.fecha_nacimiento,
|
||||
u.fecha_nacimiento ?? '',
|
||||
u.generacion?.toString() ?? ''
|
||||
].join('\t');
|
||||
].join(',');
|
||||
}).join('\n');
|
||||
|
||||
const tablaCompleta = header + rows;
|
||||
@@ -565,7 +517,7 @@ export class ExcelService {
|
||||
const header = [
|
||||
'num_cuenta', 'nombre', 'a_paterno', 'a_materno',
|
||||
'carreras', 'rfc'
|
||||
].join('\t') + '\n';
|
||||
].join(',') + '\n';
|
||||
|
||||
const rows = usuarios.map(u => {
|
||||
const carreras = (u.carreraUsuarios ?? [])
|
||||
@@ -573,13 +525,13 @@ export class ExcelService {
|
||||
.join(', '); // une todas las carreras en un solo string
|
||||
|
||||
return [
|
||||
u.num_cuenta,
|
||||
u.nombre,
|
||||
u.a_paterno,
|
||||
u.a_materno,
|
||||
carreras,
|
||||
u.num_cuenta ?? '',
|
||||
u.nombre ?? '',
|
||||
u.a_paterno ?? '',
|
||||
u.a_materno ?? '',
|
||||
carreras ?? '',
|
||||
u.rfc ?? '',
|
||||
].join('\t');
|
||||
].join(',');
|
||||
}).join('\n');
|
||||
|
||||
const tablaCompleta = header + rows;
|
||||
@@ -630,13 +582,13 @@ export class ExcelService {
|
||||
|
||||
const header = [
|
||||
'num_cuenta', 'fecha_nacimiento'
|
||||
].join('\t') + '\n';
|
||||
].join(',') + '\n';
|
||||
|
||||
const rows = usuarios.map(u => {
|
||||
return [
|
||||
u.num_cuenta,
|
||||
u.fecha_nacimiento,
|
||||
].join('\t');
|
||||
].join(',');
|
||||
}).join('\n');
|
||||
|
||||
const tablaCompleta = header + rows;
|
||||
@@ -686,22 +638,22 @@ export class ExcelService {
|
||||
const header = [
|
||||
'num_cuenta', 'nombre', 'a_paterno', 'a_materno',
|
||||
'carreras', 'fecha_nacimiento', 'generacion'
|
||||
].join('\t') + '\n';
|
||||
].join(',') + '\n';
|
||||
|
||||
const rows = usuarios.map(u => {
|
||||
const carreras = (u.carreraUsuarios ?? [])
|
||||
.map(cu => cu.carrera?.carrera ?? '') // obtenemos solo el nombre
|
||||
.join(', '); // une todas las carreras en un solo string
|
||||
.join(','); // une todas las carreras en un solo string
|
||||
|
||||
return [
|
||||
u.num_cuenta,
|
||||
u.nombre,
|
||||
u.a_paterno,
|
||||
u.a_materno,
|
||||
carreras,
|
||||
u.fecha_nacimiento,
|
||||
u.num_cuenta ?? '',
|
||||
u.nombre ?? '',
|
||||
u.a_paterno ?? '',
|
||||
u.a_materno ?? '',
|
||||
carreras ?? '',
|
||||
u.fecha_nacimiento ?? '',
|
||||
u.generacion?.toString() ?? ''
|
||||
].join('\t');
|
||||
].join(',');
|
||||
}).join('\n');
|
||||
|
||||
const tablaCompleta = header + rows;
|
||||
|
||||
Reference in New Issue
Block a user