Files
cargaMasiva_api/src/usuarios/usuarios.service.ts
T

622 lines
18 KiB
TypeScript

import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { CreateUsuarioDto } from './dto/create-usuario.dto';
import { UpdateUsuarioDto } from './dto/update-usuario.dto';
import { InjectRepository } from '@nestjs/typeorm';
import {
Carrera,
CarreraUsuario,
Genero,
TipoUsuario,
Usuario,
UsuarioTipoUsuario,
} from 'src/entities/entities';
import { Repository } from 'typeorm';
import { ServActivos } from './entities/servActivos.entitie';
import { MovimientoService } from 'src/movimiento/movimiento.service';
import { MailService } from 'src/mail/mail.service';
import { error } from 'console';
import { Cron } from '@nestjs/schedule';
import { ExcelService } from 'src/excel/excel.service';
@Injectable()
export class UsuariosService {
private readonly logger = new Logger(UsuariosService.name);
constructor(
@InjectRepository(Usuario)
private readonly usuarioRepository: Repository<Usuario>,
@InjectRepository(Carrera)
private readonly carreraRepository: Repository<Carrera>,
@InjectRepository(ServActivos)
private readonly servActivosRepository: Repository<ServActivos>,
@InjectRepository(TipoUsuario)
private readonly tipoUsuarioRepository: Repository<TipoUsuario>,
@InjectRepository(Genero)
private readonly generoRepository: Repository<Genero>,
@InjectRepository(CarreraUsuario)
private readonly carreraUsuario: Repository<CarreraUsuario>,
@InjectRepository(UsuarioTipoUsuario)
private readonly usuarioTipoUsuario: Repository<UsuarioTipoUsuario>,
private readonly movimientoService: MovimientoService,
private readonly mailService: MailService,
private readonly excelService: ExcelService, // Asegúrate de importar el servicio de Excel
) { }
altaIndividual(createUsuarioDto: CreateUsuarioDto) {
return 'This action adds a new usuario';
}
async findByMov(id: number) {
const usuarios = await this.usuarioRepository.find({
where: {
//movimiento:{id_mov:id},
servActivo: {
PrestamosStatus: 'Inactivo', // solo los que no tienen servicio activo
Prestamos: true, // solo los que tienen el servicio de préstamos activo
},
},
relations: ['usuarioTipos', 'usuarioTipos.tipoUsuario', 'servActivo'],
});
if (!usuarios)
throw new Error('No existe suauarios relacionados a ese movimiento');
return usuarios;
}
async findOneStatus(noCuenta: string) {
const usuario = await this.usuarioRepository.findOne({
where: { num_cuenta: noCuenta },
});
if (!usuario) {
throw new NotFoundException('Usuario no encontrado');
}
const servActivo = await this.servActivosRepository.findOne({
where: { usuario: { id_usuario: usuario.id_usuario } },
});
if (!servActivo) {
throw new NotFoundException('Servicios no encontrados para el usuario');
}
const resultado: {
servicio: string;
status: string;
fecha_activacion: string;
}[] = [];
const mapServicio = (nombre: string, estado: string | undefined) => {
if (!estado) return;
if (estado.startsWith('Activo')) {
const fechaCompleta = estado.substring(7); // "2025-06-25T14:26:21.427Z"
const fechaSolo = fechaCompleta.substring(0, 10); // "2025-06-25"
resultado.push({
servicio: nombre,
status: 'Activo',
fecha_activacion: fechaSolo,
});
} else {
resultado.push({
servicio: nombre,
status: 'Inactivo',
fecha_activacion: '',
});
}
};
await mapServicio('Red', servActivo.RedStatus);
await mapServicio('Correo', servActivo.CorreoStatus);
await mapServicio('Préstamo de equipo PC Puma', servActivo.PrestamosStatus);
await mapServicio('Préstamo de equipo en CEDETEC', servActivo.ATStatus);
if (resultado.length === 0) {
return [
{
servicio: 'Ninguno',
status: 'No hay servicios activos para este usuario',
fecha_activacion: null,
},
];
}
return { resultado, usuario: usuario.nombre };
}
update(id: number, updateUsuarioDto: UpdateUsuarioDto) {
return `This action updates a #${id} usuario`;
}
@Cron('0 0 0 10,25 * *')
async tareaMensual() {
this.logger.log('Ejecutando consulta mensual de profesores');
await this.enviarSolicitud(); // tu función de importación
}
async enviarSolicitud() {
const mov = await this.movimientoService.log(
'SISTEMA',
'LOADING',
'Enviando solicitud de consulta masiva de profesores al WebService',
'CARGA MASIVA WEB SERVICE',
);
interface DatosEntrada {
Nombre: string;
ApellidoPaterno: string;
ApellidoMaterno: string;
NumeroTrabajador: string;
RFC: string;
}
interface DatosRespuesta {
numeroTrabajador: string;
nombre: string;
apellidoPaterno: string;
apellidoMaterno: string;
nombreCarrera: string;
fechaNacimiento: string;
rfc: string;
genero: string;
}
const apiUrl = process.env.API_URL;
if (!apiUrl) return;
const entrada: DatosEntrada = {
Nombre: '',
ApellidoPaterno: '',
ApellidoMaterno: '',
NumeroTrabajador: '',
RFC: '',
};
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(entrada),
});
if (!response.ok) return;
const profesores: DatosRespuesta[] = await response.json();
let nuevos = 0;
let actualizados = 0;
/* ==========================
TIPO USUARIO PROFESOR
========================== */
let tipoProfesor = await this.tipoUsuarioRepository.findOne({
where: { tipo_usuario: 'Profesor' },
});
if (!tipoProfesor) {
tipoProfesor = await this.tipoUsuarioRepository.save(
this.tipoUsuarioRepository.create({ tipo_usuario: 'Profesor' }),
);
}
/* ==========================
CACHE DE CARRERAS
========================== */
const carreraCache = new Map<string, any>();
for (const prof of profesores) {
if (!prof.rfc || !prof.nombre) continue;
const usuario = await this.usuarioRepository.findOne({
where: { rfc: prof.rfc },
relations: ['genero'],
});
/* ==========================
NORMALIZAR CARRERA
========================== */
const nombreCarrera = prof.nombreCarrera?.trim().toUpperCase();
let carrera = carreraCache.get(nombreCarrera);
if (!carrera && nombreCarrera) {
carrera = await this.carreraRepository.findOne({
where: { carrera: nombreCarrera },
});
if (!carrera) {
carrera = await this.carreraRepository.save(
this.carreraRepository.create({
carrera: nombreCarrera,
clave: '',
}),
);
}
carreraCache.set(nombreCarrera, carrera);
}
/* ==========================
USUARIO NUEVO
========================== */
if (!usuario) {
let genero;
if (prof.genero === 'M' || prof.genero === 'F') {
const generoTexto = prof.genero === 'M' ? 'Masculino' : 'Femenino';
genero =
(await this.generoRepository.findOne({
where: { genero: generoTexto },
})) ??
(await this.generoRepository.save(
this.generoRepository.create({ genero: generoTexto }),
));
}
const nuevoUsuario = await this.usuarioRepository.save(
this.usuarioRepository.create({
num_cuenta: prof.numeroTrabajador || undefined,
nombre: prof.nombre,
a_paterno: prof.apellidoPaterno,
a_materno: prof.apellidoMaterno,
rfc: prof.rfc,
fecha_nacimiento: prof.fechaNacimiento,
genero,
movimiento: mov,
}),
);
await this.servActivosRepository.save(
this.servActivosRepository.create({
usuario: nuevoUsuario,
AT: !!prof.numeroTrabajador,
Red: !!prof.numeroTrabajador,
Prestamos: !!prof.numeroTrabajador,
Correo: true,
ATStatus: 'Inactivo',
RedStatus: 'Inactivo',
PrestamosStatus: 'Inactivo',
CorreoStatus: 'Inactivo',
}),
);
await this.carreraUsuario.save(
this.carreraUsuario.create({
usuario: nuevoUsuario,
carrera,
}),
);
await this.usuarioTipoUsuario.save(
this.usuarioTipoUsuario.create({
usuario: nuevoUsuario,
tipoUsuario: tipoProfesor,
}),
);
nuevos++;
continue;
}
/* ==========================
USUARIO EXISTENTE
========================== */
let cambios = false;
const servActivo = await this.servActivosRepository.findOne({
where: { usuario: { id_usuario: usuario.id_usuario } },
});
const activarServicios = () => {
if (!servActivo) return;
servActivo.AT = true;
servActivo.Red = true;
servActivo.Prestamos = true;
servActivo.Correo = true;
servActivo.ATStatus = 'Inactivo';
servActivo.RedStatus = 'Inactivo';
servActivo.PrestamosStatus = 'Inactivo';
servActivo.CorreoStatus = 'Inactivo';
};
if (usuario.nombre !== prof.nombre) {
usuario.nombre = prof.nombre;
activarServicios();
cambios = true;
}
if (usuario.a_paterno !== prof.apellidoPaterno) {
usuario.a_paterno = prof.apellidoPaterno;
activarServicios();
cambios = true;
}
if (usuario.a_materno !== prof.apellidoMaterno) {
usuario.a_materno = prof.apellidoMaterno;
activarServicios();
cambios = true;
}
if (usuario.fecha_nacimiento !== prof.fechaNacimiento) {
usuario.fecha_nacimiento = prof.fechaNacimiento;
activarServicios();
cambios = true;
}
if (
prof.numeroTrabajador &&
usuario.num_cuenta !== prof.numeroTrabajador
) {
usuario.num_cuenta = prof.numeroTrabajador;
activarServicios();
cambios = true;
}
if (cambios) {
usuario.movimiento = mov;
await this.usuarioRepository.save(usuario);
if (servActivo) await this.servActivosRepository.save(servActivo);
actualizados++;
}
}
await this.movimientoService.updateStatus(
mov.id_mov,
'SUCCESS',
`Carga masiva finalizada. Nuevos: ${nuevos}, Actualizados: ${actualizados}`,
);
return `Importación finalizada. Nuevos: ${nuevos}, Actualizados: ${actualizados}`;
} catch (error) {
this.logger.error('Error en carga masiva de profesores', error);
throw error;
}
}
async cargaIndividual(
usuario: CreateUsuarioDto,
origen: string,
user: string,
) {
const queryRunner =
this.usuarioRepository.manager.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const existente = await queryRunner.manager.findOne(Usuario, {
where: { num_cuenta: usuario.num_cuenta ?? usuario.usuario },
relations: ['genero'],
});
if (existente) {
throw new Error('Ya existe este usuario');
}
const mov = await this.movimientoService.logger(
queryRunner,
origen,
'LOADING',
'la carga se hizo por: ' + user,
'CARGA INDIVIDUAL DE USUARIOS',
);
let genero: Genero | null = null;
if (usuario.genero === 'M' || usuario.genero === 'F') {
const generoTexto = usuario.genero === 'M' ? 'Masculino' : 'Femenino';
genero = await queryRunner.manager.findOne(Genero, {
where: { genero: generoTexto },
});
if (!genero) {
genero = queryRunner.manager.create(Genero, { genero: generoTexto });
await queryRunner.manager.save(genero);
}
}
let carrera;
if (usuario.carrera != undefined) {
carrera = await queryRunner.manager.findOne(Carrera, {
where: { carrera: usuario.carrera },
});
if (!carrera) {
carrera = await queryRunner.manager.findOne(Carrera, {
where: { carrera: '' },
});
}
} else {
carrera = await queryRunner.manager.findOne(Carrera, {
where: { carrera: '' },
});
if (!carrera) {
const nuevaCarrera = queryRunner.manager.create(Carrera, {
carrera: '',
clave: '',
});
carrera = await queryRunner.manager.save(nuevaCarrera);
}
}
const nuevo = queryRunner.manager.create(Usuario, {
num_cuenta: usuario.num_cuenta ?? usuario.usuario,
nombre: usuario.nombre,
a_paterno: usuario.a_paterno,
a_materno: usuario.a_materno,
rfc: usuario.rfc ?? null,
fecha_nacimiento: usuario.fecha_nacimiento,
generacion: usuario.generacion ?? null,
genero,
movimiento: mov,
contraseña: usuario.contraseña ?? null, // Asegúrate de manejar la contraseña adecuadamente
});
const savedUser = await queryRunner.manager.save(nuevo);
const userCarrera = queryRunner.manager.create(CarreraUsuario, {
carrera,
usuario: savedUser,
});
await queryRunner.manager.save(userCarrera);
const FieldMap = [
'Diplomado',
'Extra Largo',
'Servicio Social',
'Idiomas R (UNAM)',
'Idiomas Sabatino',
'Reinscrito',
'Posgrado',
'Intercambio UNAM',
'Movilidad',
'Ampliación de Conocimiento',
'Licenciatura',
'Profesor',
'Trabajadores',
'Caso especial',
];
if (!FieldMap.includes(usuario.tipo_usuario)) {
throw new Error(
`Tipo de usuario no permitido: ${usuario.tipo_usuario}`,
);
}
// Verifica si el tipo de usuario ya existe
let tipoUsuario = await queryRunner.manager.findOne(TipoUsuario, {
where: { tipo_usuario: usuario.tipo_usuario },
});
// Si no existe, lo crea y guarda
if (!tipoUsuario) {
tipoUsuario = queryRunner.manager.create(TipoUsuario, {
tipo_usuario: usuario.tipo_usuario,
});
tipoUsuario = await queryRunner.manager.save(tipoUsuario);
}
// Luego crea la relación con el usuario ya guardado
const usuarioTipo = queryRunner.manager.create(UsuarioTipoUsuario, {
tipoUsuario,
usuario: savedUser,
});
await queryRunner.manager.save(usuarioTipo);
let at: boolean = false;
let correo: boolean = false;
let red: boolean = false;
let solicita: boolean = false;
switch (usuario.tipo_usuario.trim()) {
case 'Diplomado':
const servActivosDiplomado = this.servActivosRepository.create({
Correo: true,
usuario: savedUser,
RedStatus: 'Inactivo',
ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo',
PrestamosStatus: 'Inactivo',
});
correo = true;
await queryRunner.manager.save(servActivosDiplomado);
break;
case 'Extra Largo':
const servActivosExtraLargo = this.servActivosRepository.create({
Prestamos: true,
Correo: true,
usuario: savedUser,
RedStatus: 'Inactivo',
ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo',
PrestamosStatus: 'Inactivo',
});
solicita = true;
correo = true;
await queryRunner.manager.save(servActivosExtraLargo);
break;
case 'Servicio Social':
const servActivosServicio = this.servActivosRepository.create({
Red: true,
AT: true,
Correo: true,
usuario: savedUser,
RedStatus: 'Inactivo',
ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo',
PrestamosStatus: 'Inactivo',
});
at = true;
red = true;
correo = true;
await queryRunner.manager.save(servActivosServicio);
break;
case 'Idiomas R (UNAM)':
case 'Idiomas Sabatino':
const servActivosIdiomas = this.servActivosRepository.create({
Red: true,
Correo: true,
usuario: savedUser,
RedStatus: 'Inactivo',
ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo',
PrestamosStatus: 'Inactivo',
});
red = true;
correo = true;
await queryRunner.manager.save(servActivosIdiomas);
break;
case 'Reinscrito':
case 'Posgrado':
case 'Intercambio UNAM':
case 'Movilidad':
case 'Ampliación de Conocimiento':
case 'Licenciatura':
case 'Profesor':
const servActivos = this.servActivosRepository.create({
Red: true,
AT: true,
Correo: true,
Prestamos: true,
usuario: savedUser,
RedStatus: 'Inactivo',
ATStatus: 'Inactivo',
CorreoStatus: 'Inactivo',
PrestamosStatus: 'Inactivo',
});
at = true;
red = true;
correo = true;
solicita = true;
await queryRunner.manager.save(servActivos);
break;
case 'Caso especial':
case 'Trabajadores':
const servActivosTrabajadores = this.servActivosRepository.create({
Red: true,
usuario: savedUser,
RedStatus: 'Inactivo',
});
red = true;
await queryRunner.manager.save(servActivosTrabajadores);
break;
}
await queryRunner.commitTransaction();
return { saved: savedUser, movId: mov.id_mov, at, correo, red, solicita };
} catch (error) {
await queryRunner.rollbackTransaction();
throw new Error('Error en la carga individual: ' + error.message);
} finally {
await queryRunner.release();
}
}
}