import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import * as csv from 'csvtojson'; import * as fs from 'fs'; import * as path from 'path'; import * as moment from 'moment'; import { Programa } from './entities/programa.entity'; import { Usuario } from 'src/usuario/entities/usuario.entity'; import { ValidacionService } from 'src/helpers.services/validacion.service'; import { AuthService } from 'src/auth/auth.service'; import { gmail } from 'src/helpers.services/gmail.service'; import { SendMailDto } from 'src/helpers.services/dto/send-email.dto'; @Injectable() export class ProgramaService { constructor( @InjectRepository(Programa) private programaRepo: Repository, @InjectRepository(Usuario) private usuarioRepo: Repository, private validacionService: ValidacionService, private authService: AuthService, private gmail: gmail, ) {} async cargaMasiva(nombreArchivo: string): Promise<{ message: string }> { const filePath = path.join('server/uploads', nombreArchivo); const today = moment(); const programas = await csv().fromFile(filePath); let mensaje = ''; for (let i = 0; i < programas.length; i++) { const prog = programas[i]; mensaje += `Línea ${i + 2}\n`; if ( !prog.correo || !prog.nombre || !prog.institucion || !prog.dependencia || !prog.programa || !prog.clave ) { mensaje += 'Faltan campos requeridos. Línea omitida.\n\n'; continue; } try { this.validacionService.validarCorreo(prog.correo); } catch { mensaje += 'Correo inválido. Línea omitida.\n\n'; continue; } const acatlan = prog.clave.substr(4, 7) === '-12/20-'; const activo = Number(prog.clave.substr(0, 4)) === today.year(); let responsable = await this.usuarioRepo.findOne({ where: { usuario: prog.correo, tipoUsuario: { idTipoUsuario: 2, }, }, }); if (!responsable) { const password = await this.authService.encriptar( this.authService.generarPassword(), ); const correoInfo = enviarSec(password, prog.correo, prog.nombre); responsable = await this.usuarioRepo.create({ usuario: prog.correo, password: password, nombre: prog.nombre, activo: true, tipoUsuario: { idTipoUsuario: 2, }, }); const sendCorreoDto: SendMailDto = { to: prog.correo, subject: correoInfo.subject, text: correoInfo.msj, fecha_recibido: new Date(), }; if (!process.env.TOKEN_GMAIL) { throw new Error('No existe el token'); } try { responsable = await this.usuarioRepo.save(responsable); await this.gmail.enviarCorreo(sendCorreoDto); mensaje += `Responsable creado con ID ${responsable.idUsuario} y correo ${responsable.usuario}\n`; } catch (err) { mensaje += `Error creando responsable: ${err.message}\n`; continue; } } if (!acatlan) { const existente = await this.programaRepo.findOne({ where: { clavePrograma: prog.clave }, relations: ['usuario'], }); if (!existente) { try { const nuevoPrograma = this.programaRepo.create({ institucion: prog.institucion, dependencia: prog.dependencia, programa: prog.programa, clavePrograma: prog.clave, activo, usuario: { idUsuario: responsable.idUsuario, }, }); const creado = await this.programaRepo.save(nuevoPrograma); mensaje += `Programa ${creado.clavePrograma} asignado al usuario ${responsable.usuario}\n`; } catch (err) { mensaje += `Error creando programa: ${err.message}\n`; } } else { mensaje += `Programa ya existe con clave ${existente.clavePrograma}. `; if (existente.usuario?.usuario === prog.correo) { mensaje += 'Ya pertenece a este responsable.\n'; } else { mensaje += `Asignado a otro responsable: ${existente.usuario.usuario}\n`; } } } else { const existente = await this.programaRepo.findOne({ where: { clavePrograma: prog.clave, usuario: { idUsuario: responsable.idUsuario, }, }, }); if (!existente) { try { const nuevoPrograma = this.programaRepo.create({ institucion: 'UNAM', dependencia: 'FES ACATLAN', programa: prog.programa, clavePrograma: prog.clave, activo, acatlan, usuario: { idUsuario: responsable.idUsuario, }, }); const creado = await this.programaRepo.save(nuevoPrograma); mensaje += `Programa ACATLÁN ${creado.clavePrograma} asignado a ${responsable.usuario}\n`; } catch (err) { mensaje += `Error creando programa: ${err.message}\n`; } } else { mensaje += `Programa ACATLÁN ya pertenece a ${responsable.usuario}\n`; } } mensaje += '\n'; } fs.unlinkSync(filePath); return { message: 'Se subió correctamente el archivo CSV para la carga masiva.', }; } async programasAdmin(idUser: number) { const idUsuario = this.validacionService.validarNumeroEntero( idUser, 'id usuario', ); const usuario = await this.usuarioRepo.findOne({ where: { idUsuario }, }); if (!usuario) { throw new Error('No existe este usuario.'); } if (usuario.tipoUsuario.idTipoUsuario !== 2) { throw new Error('No es un usuario de tipo responsable'); } return this.programaRepo.find({ where: { usuario: { idUsuario } }, }); } async programasResponsable(idUser: number) { const idUsuario = this.validacionService.validarNumeroEntero( idUser, 'id usuario', ); const usuario = await this.usuarioRepo.findOne({ where: { idUsuario }, }); if (!usuario) { throw new Error('No existe este usuario.'); } if (usuario.tipoUsuario.idTipoUsuario !== 2) { throw new Error('No es un usuario de tipo responsable'); } return this.programaRepo.find({ where: { usuario: { idUsuario }, activo: true, }, }); } async reasignarProgramas(idUsuario: number, correoOtroResponsable: string) { const idusuario = this.validacionService.validarNumeroEntero( idUsuario, 'id usuario', ); const otroResponsable = this.validacionService.validarCorreo( correoOtroResponsable, ); let usuarioNuevo = await this.usuarioRepo.findOne({ where: { idUsuario: idusuario }, }); if (!usuarioNuevo) throw new Error('No existe este usuario.'); if (usuarioNuevo.tipoUsuario.idTipoUsuario != 2) throw new Error('No es un usuario de tipo responsable'); if (usuarioNuevo.usuario === correoOtroResponsable) throw new Error('Son el mismo usuario.'); let viejoResponsable = await this.usuarioRepo.findOne({ where: { usuario: otroResponsable }, }); if (!viejoResponsable) throw new Error('No existe este usuario.'); await this.programaRepo.update( { usuario: viejoResponsable }, { usuario: usuarioNuevo }, ); // Eliminar usuario antiguo await this.usuarioRepo.delete({ idUsuario: viejoResponsable.idUsuario }); return { message: `Se eliminó correctamente al usuario ${correoOtroResponsable} y se reasignaron sus programas.`, }; } }