622 lines
18 KiB
TypeScript
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();
|
|
}
|
|
}
|
|
}
|