se modifico endpoint de cargar
This commit is contained in:
Generated
+439
-506
File diff suppressed because it is too large
Load Diff
@@ -110,7 +110,7 @@ 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) {
|
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') {
|
||||||
@@ -122,10 +122,20 @@ export class ExcelController {
|
|||||||
throw new Error('Origen no permitido para carga.');
|
throw new Error('Origen no permitido para carga.');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const result = await this.excelService.loadFile(
|
let result;
|
||||||
|
if(funcion==2){
|
||||||
|
result = await this.excelService.loadFile2(
|
||||||
file.buffer,
|
file.buffer,
|
||||||
req.user.email,
|
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({
|
||||||
|
|||||||
@@ -500,6 +500,332 @@ export class ExcelService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async loadFile2(buffer: Buffer, user: string) {
|
||||||
|
const file = await this.parseFile(buffer);
|
||||||
|
const status = this.validateRows(file);
|
||||||
|
const errs = status.errors;
|
||||||
|
const rows = status.rowsGood;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (rows.length === 0) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'No se encontraron filas válidas para cargar. ' + errs,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let conteoTiposRed: number = 0;
|
||||||
|
let conteoTiposAt: number = 0;
|
||||||
|
let conteoTiposSolicita: number = 0;
|
||||||
|
let conteoTiposCorreo: number = 0;
|
||||||
|
|
||||||
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const movimiento = await this.movimientoService.logger(
|
||||||
|
queryRunner,
|
||||||
|
'LOAD',
|
||||||
|
'LOADING',
|
||||||
|
'Caraga masiva de usuarios hecha por: ' + user,
|
||||||
|
`CARGA MASIVA DE USUARIOS`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 🔹 1. Pre-cargar cuentas/rfc ya existentes
|
||||||
|
const cuentas = rows.map((r) => r.cuenta).filter(Boolean);
|
||||||
|
const rfcs = rows.map((r) => r.rfc).filter(Boolean);
|
||||||
|
|
||||||
|
const existentes = await queryRunner.manager.find(Usuario, {
|
||||||
|
where: [{ num_cuenta: In(cuentas) }, { rfc: In(rfcs) }],
|
||||||
|
select: ['num_cuenta', 'rfc', 'id_usuario'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const setCuentas = new Set(existentes.map((u) => u.num_cuenta));
|
||||||
|
const setRfcs = new Set(existentes.map((u) => u.rfc));
|
||||||
|
|
||||||
|
// 🔹 2. Pre-cargar catálogos
|
||||||
|
const generosUnicos = [
|
||||||
|
...new Set(rows.map((r) => r.sexo).filter(Boolean)),
|
||||||
|
];
|
||||||
|
const carrerasUnicasClave = [
|
||||||
|
...new Set(rows.map((r) => r.clave).filter(Boolean)),
|
||||||
|
];
|
||||||
|
const carrerasUnicasNombre = [
|
||||||
|
...new Set(rows.map((r) => r.nomCarr).filter(Boolean)),
|
||||||
|
];
|
||||||
|
const tiposUnicos = [
|
||||||
|
...new Set(rows.map((r) => r.tipo?.trim()).filter(Boolean)),
|
||||||
|
];
|
||||||
|
|
||||||
|
const [generosExist, carrerasExist, tiposExist] = await Promise.all([
|
||||||
|
queryRunner.manager.find(Genero, {
|
||||||
|
where: { genero: In(generosUnicos) },
|
||||||
|
}),
|
||||||
|
queryRunner.manager.find(Carrera, {
|
||||||
|
where: [
|
||||||
|
{ clave: In(carrerasUnicasClave) },
|
||||||
|
{ carrera: In(carrerasUnicasNombre) },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
queryRunner.manager.find(TipoUsuario, {
|
||||||
|
where: { tipo_usuario: In(tiposUnicos) },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const mapGenero = new Map(generosExist.map((g) => [g.genero, g]));
|
||||||
|
const mapCarreraClave = new Map(carrerasExist.map((c) => [c.clave, c]));
|
||||||
|
const mapCarreraNom = new Map(carrerasExist.map((c) => [c.carrera, c]));
|
||||||
|
const mapTipo = new Map(tiposExist.map((t) => [t.tipo_usuario, t]));
|
||||||
|
|
||||||
|
// 🔹 3. Arreglos para inserciones masivas
|
||||||
|
const usuarios: Usuario[] = [];
|
||||||
|
const carrerasUsuario: CarreraUsuario[] = [];
|
||||||
|
const usuariosTipos: UsuarioTipoUsuario[] = [];
|
||||||
|
const serviciosActivos: ServActivos[] = [];
|
||||||
|
|
||||||
|
let contador = 0;
|
||||||
|
let idsUsuarios: number[] =[]
|
||||||
|
for (const r of rows) {
|
||||||
|
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)
|
||||||
|
if(use?.id_usuario)
|
||||||
|
idsUsuarios.push(use?.id_usuario)
|
||||||
|
contador++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r.tipo || !r.nombres || !r.apellidopa || !r.apellidoma) {
|
||||||
|
errs.push(`Fila con cuenta ${r.cuenta} tiene campos faltantes.`);
|
||||||
|
contador++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Genero
|
||||||
|
let genero = mapGenero.get(r.sexo);
|
||||||
|
if (!genero) {
|
||||||
|
genero = queryRunner.manager.create(Genero, { genero: r.sexo });
|
||||||
|
mapGenero.set(r.sexo, genero);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Carrera
|
||||||
|
let carrera: Carrera | undefined;
|
||||||
|
if (r.clave && mapCarreraClave.has(r.clave)) {
|
||||||
|
carrera = mapCarreraClave.get(r.clave);
|
||||||
|
} else if (r.nomCarr && mapCarreraNom.has(r.nomCarr)) {
|
||||||
|
carrera = mapCarreraNom.get(r.nomCarr);
|
||||||
|
} else if (r.clave || r.nomCarr) {
|
||||||
|
carrera = queryRunner.manager.create(Carrera, {
|
||||||
|
clave: r.clave ?? '',
|
||||||
|
carrera: r.nomCarr?.slice(0, 100) ?? '',
|
||||||
|
});
|
||||||
|
mapCarreraClave.set(carrera.clave, carrera);
|
||||||
|
mapCarreraNom.set(carrera.carrera, carrera);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tipo
|
||||||
|
let tipo = mapTipo.get(r.tipo.trim());
|
||||||
|
if (!tipo) {
|
||||||
|
tipo = queryRunner.manager.create(TipoUsuario, {
|
||||||
|
tipo_usuario: r.tipo.trim(),
|
||||||
|
});
|
||||||
|
mapTipo.set(r.tipo.trim(), 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,
|
||||||
|
a_paterno: r.apellidopa,
|
||||||
|
a_materno: r.apellidoma,
|
||||||
|
rfc: r.rfc,
|
||||||
|
fecha_nacimiento: r.fechnac,
|
||||||
|
generacion,
|
||||||
|
genero,
|
||||||
|
movimiento,
|
||||||
|
});
|
||||||
|
|
||||||
|
usuarios.push(usuario);
|
||||||
|
idsUsuarios.push(usuario.id_usuario)
|
||||||
|
|
||||||
|
if (carrera) {
|
||||||
|
const carreraUsuario = queryRunner.manager.create(CarreraUsuario, {
|
||||||
|
usuario,
|
||||||
|
carrera,
|
||||||
|
});
|
||||||
|
carrerasUsuario.push(carreraUsuario);
|
||||||
|
}
|
||||||
|
|
||||||
|
usuariosTipos.push(
|
||||||
|
queryRunner.manager.create(UsuarioTipoUsuario, {
|
||||||
|
usuario,
|
||||||
|
tipoUsuario: tipo,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Servicios activos
|
||||||
|
const servData: Partial<ServActivos> = {
|
||||||
|
usuario,
|
||||||
|
RedStatus: 'Inactivo',
|
||||||
|
ATStatus: 'Inactivo',
|
||||||
|
CorreoStatus: 'Inactivo',
|
||||||
|
PrestamosStatus: 'Inactivo',
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (r.tipo.trim()) {
|
||||||
|
case 'Diplomado':
|
||||||
|
Object.assign(servData, { Correo: true });
|
||||||
|
conteoTiposCorreo++;
|
||||||
|
break;
|
||||||
|
case 'Extra Largo':
|
||||||
|
Object.assign(servData, { Correo: true, Prestamos: true });
|
||||||
|
conteoTiposCorreo++;
|
||||||
|
conteoTiposSolicita++;
|
||||||
|
break;
|
||||||
|
case 'Servicio Social':
|
||||||
|
Object.assign(servData, { Correo: true, AT: true, Red: true });
|
||||||
|
conteoTiposCorreo++;
|
||||||
|
conteoTiposAt++;
|
||||||
|
conteoTiposRed++;
|
||||||
|
break;
|
||||||
|
case 'Idiomas R (UNAM)':
|
||||||
|
case 'Idiomas Sabatino':
|
||||||
|
Object.assign(servData, { Correo: true, Red: true });
|
||||||
|
conteoTiposCorreo++;
|
||||||
|
conteoTiposRed++;
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
conteoTiposCorreo++;
|
||||||
|
conteoTiposRed++;
|
||||||
|
conteoTiposAt++;
|
||||||
|
conteoTiposSolicita++;
|
||||||
|
break;
|
||||||
|
case 'Trabajadores':
|
||||||
|
Object.assign(servData, { Red: true });
|
||||||
|
conteoTiposRed++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviciosActivos.push(
|
||||||
|
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 this.servActivosRepo
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update()
|
||||||
|
.set({
|
||||||
|
Red: false,
|
||||||
|
Prestamos: false,
|
||||||
|
AT: false,
|
||||||
|
Correo: false,
|
||||||
|
RedStatus: 'Inactivo',
|
||||||
|
PrestamosStatus: 'Inactivo',
|
||||||
|
ATStatus: 'Inactivo',
|
||||||
|
CorreoStatus: 'Inactivo',
|
||||||
|
})
|
||||||
|
.where('id_usuario NOT IN (:...ids)', { ids: idsUsuarios })
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
inserted: rows.length - contador,
|
||||||
|
id_movimiento: movimiento.id_mov,
|
||||||
|
errors: errs,
|
||||||
|
conteoTiposAt,
|
||||||
|
conteoTiposCorreo,
|
||||||
|
conteoTiposRed,
|
||||||
|
conteoTiposSolicita,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// async generateCsv(): Promise<string> {
|
// async generateCsv(): Promise<string> {
|
||||||
// const users = await this.usuarioRepo.find({
|
// const users = await this.usuarioRepo.find({
|
||||||
// relations: ['genero', 'carreraUsuarios'], // si quieres más info
|
// relations: ['genero', 'carreraUsuarios'], // si quieres más info
|
||||||
|
|||||||
Reference in New Issue
Block a user