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 { SendCorreoDto } 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: SendCorreoDto = { to: prog.correo, subject: correoInfo.subject, fecha_recibido: new Date(), text: correoInfo.msj, html: '', adjuntos: undefined }; if (!process.env.TOKEN_GMAIL) { throw new Error('No existe el token'); } try { responsable = await this.usuarioRepo.save(responsable); await this.gmail.send(sendCorreoDto, process.env.TOKEN_GMAIL); 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(body: { idUsuario: number }) { const idUsuario = this.validacionService.validarNumeroEntero(body.idUsuario, '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(body: { idUsuario: number }) { const idUsuario = this.validacionService.validarNumeroEntero(body.idUsuario, '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.`, } } }