From 58368a6929e331bf2ee1e9a62956d4c7b11dfdd8 Mon Sep 17 00:00:00 2001 From: santiago Date: Mon, 28 Jul 2025 15:33:09 -0600 Subject: [PATCH 1/2] Cambios en el back de inscripciones --- package-lock.json | 15 ++++ package.json | 1 + server/app.js | 15 ++++ server/config/config.js | 2 + server/config/mariadb.conf.js | 37 ++++++++- server/controller/Profesor/buscarProfesor.js | 38 ++++++++++ .../Profesor/confirmarInscripcion.js | 23 ++++++ server/controller/Profesor/enviarCorreo.js | 33 ++++++++ .../Profesor/inscripcionProfesor.js | 66 ++++++++++++++++ server/db/install.js | 29 +++++++ server/db/tablas/Profesor.js | 39 ++++++++++ server/db/tablas/ProfesorInscrito.js | 42 ++++++++++ server/db/tablas/Usuario.js | 14 ++-- server/helper/encriptar.js | 18 ++++- server/middleware/autentificacion.js | 4 + server/routes/Profesor.js | 76 +++++++++++++++++++ 16 files changed, 442 insertions(+), 10 deletions(-) create mode 100644 server/controller/Profesor/buscarProfesor.js create mode 100644 server/controller/Profesor/confirmarInscripcion.js create mode 100644 server/controller/Profesor/enviarCorreo.js create mode 100644 server/controller/Profesor/inscripcionProfesor.js create mode 100644 server/db/tablas/Profesor.js create mode 100644 server/db/tablas/ProfesorInscrito.js create mode 100644 server/routes/Profesor.js diff --git a/package-lock.json b/package-lock.json index 4ab75d6..63104c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "mariadb": "^2.5.3", "moment": "^2.29.1", "multer": "^1.4.4", + "nodemailer": "^7.0.5", "sequelize": "^6.6.2", "validator": "^13.6.0" }, @@ -1757,6 +1758,15 @@ "node": "4.x || >=6.0.0" } }, + "node_modules/nodemailer": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.5.tgz", + "integrity": "sha512-nsrh2lO3j4GkLLXoeEksAMgAOqxOv6QumNRVQTJwKH4nuiww6iC2y7GyANs9kRAxCexg3+lTWM3PZ91iLlVjfg==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -4092,6 +4102,11 @@ "whatwg-url": "^5.0.0" } }, + "nodemailer": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.5.tgz", + "integrity": "sha512-nsrh2lO3j4GkLLXoeEksAMgAOqxOv6QumNRVQTJwKH4nuiww6iC2y7GyANs9kRAxCexg3+lTWM3PZ91iLlVjfg==" + }, "nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", diff --git a/package.json b/package.json index 0499c97..9c505bd 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "mariadb": "^2.5.3", "moment": "^2.29.1", "multer": "^1.4.4", + "nodemailer": "^7.0.5", "sequelize": "^6.6.2", "validator": "^13.6.0" }, diff --git a/server/app.js b/server/app.js index 8640a9d..3f1d904 100644 --- a/server/app.js +++ b/server/app.js @@ -13,6 +13,21 @@ app.use( }) ); +/* +const alumnoRoutes = require('./routes/alumno'); +app.use('/alumnos', alumnoRoutes); +*/ + +//agregue esto +app.use(bodyParser.json()); // esto debe ir antes de app.use('/api', rutaProfesor) +app.use(express.json()); + + +//const rutaProfesor = require('./routes/Profesor'); +//app.use('/api', rutaProfesor); +app.use('/api/profesores', require('./routes/Profesor')); + + app.use(bodyParser.json()); app.get('/', (req, res) => res.send('API de Inscripciones a CEDETEC')); diff --git a/server/config/config.js b/server/config/config.js index b7736ee..3ec5225 100644 --- a/server/config/config.js +++ b/server/config/config.js @@ -9,3 +9,5 @@ try { } catch (err) { console.log('El archivo .env no se cargo.'.underline.bold.red); } + + diff --git a/server/config/mariadb.conf.js b/server/config/mariadb.conf.js index c92bc77..396f112 100644 --- a/server/config/mariadb.conf.js +++ b/server/config/mariadb.conf.js @@ -70,4 +70,39 @@ const usuarioInscrito = async (numeroCuenta) => { }); }; -module.exports = { obtenerIdCarrera, obtenerCarrera, usuarioInscrito }; +// Agregue para profesores +const buscarProfesorPorNumero = async (numeroTrabajador) => { + const conn = await pool2.getConnection().catch((err) => { + throw new Error('No se pudo conectar con la base de datos. ' + err); + }); + + return conn + .query( + `SELECT nombre, idUsuario, numeroCuenta FROM usuario WHERE numeroCuenta = ?`, + [numeroTrabajador] // NUmero de cuenta + ) + .then((rows) => { + conn.end(); + if (rows.length === 0) return null; + return rows[0]; // { nombre: 'Juan', rfc: 'JUAP123' } + }) + .catch((err) => { + conn.end(); + throw new Error('Error al buscar el profesor: ' + err); + }); +}; + +// Para envios de correos +const nodemailer = require('nodemailer'); + +const enviarCorreoInscripcion = async (destinatario, nombreProfesor) => { + const transporter = nodemailer.createTransport({ + service: 'gmail', // o smtp host como 'smtp.mailtrap.io' + auth: { + user: process.env.CORREO_ORIGEN, // tu correo + pass: process.env.CORREO_PASSWORD, // tu contraseña o app password + }, + }); +}; + +module.exports = { obtenerIdCarrera, obtenerCarrera, usuarioInscrito, buscarProfesorPorNumero }; diff --git a/server/controller/Profesor/buscarProfesor.js b/server/controller/Profesor/buscarProfesor.js new file mode 100644 index 0000000..2a38aea --- /dev/null +++ b/server/controller/Profesor/buscarProfesor.js @@ -0,0 +1,38 @@ +const { buscarProfesorPorNumero } = require('../../config/mariadb.conf'); +const Inscripcion = require('../../db/tablas/Inscripcion'); + +async function buscarProfesor(req, res) { + const { numeroTrabajador } = req.params; + + try { + // Borrar esta linea de codigo + //console.log('Buscando profesor con RFC:', numeroTrabajador); + + const profesor = await buscarProfesorPorNumero(numeroTrabajador); + + if (!profesor) { + return res.status(404).json({ message: 'Profesor no encontrado' }); + } + + // Verificar si existe ya en la tabla de incripcion + const existeIncripcion = await Inscripcion.findOne({ + where: { + idUsuario: profesor.idUsuario + } + }); + + if (existeIncripcion) { + return res.status(409).json({ + //yaInscrito: true, + message: 'El usuario ya está inscrito.', + }); + } + + + res.status(200).json(profesor); // { nombre, correo } + } catch (error) { + res.status(500).json({ message: error.message }); + } +} + +module.exports = buscarProfesor; diff --git a/server/controller/Profesor/confirmarInscripcion.js b/server/controller/Profesor/confirmarInscripcion.js new file mode 100644 index 0000000..63c37f3 --- /dev/null +++ b/server/controller/Profesor/confirmarInscripcion.js @@ -0,0 +1,23 @@ + +/*const { inscripcion } = require('../../db/tablas/Inscripcion') + +const confirmacionInscripcion = async (req, res) => { + try { + const { idUsuario } = req.body; + + const [update] = await inscripcion.update( + { confirmacion: true}, + { where: { idUsuario } } + ); + + if (update > 0) { + return res.status(200).json({ message: 'Inscripción confirmada con éxito.'}); + } else { + return res.status(404).json({ message: 'No se encontro la inscripcion para confirmar'}); + } + } catch (error) { + console.error('Error al confirmar inscripcion: ', error); + return res.status(500).json({ message: 'Error al confirmar inscripcion.'}); + } +} +*/ \ No newline at end of file diff --git a/server/controller/Profesor/enviarCorreo.js b/server/controller/Profesor/enviarCorreo.js new file mode 100644 index 0000000..d8f7697 --- /dev/null +++ b/server/controller/Profesor/enviarCorreo.js @@ -0,0 +1,33 @@ +const nodemailer = require('nodemailer'); + +async function enviarCorreoInscripcion(correo, nombre) { + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.CORREO_ORIGEN, + pass: process.env.CORREO_PASSWORD + } + }); + + const mailOptions = { + from: '"CEDETEC"', + to: 'smtrabajos5@gmail.com', + subject: 'Confirmación de inscripción CEDETEC', + html: ` +
    +

    Estimado profesor(a) ${nombre}

    +

    Informo que su inscripción fue realizad con éxito.

    +
+ ¿Cómo puede hacer uso de los servicios? +

Es necesario revise los siguientes + videos + para solicitar equipo en el área de profesores.

+

Nota: Es importante revisar los + lineamientos de uso para hacer uso de los servicios que ofrece el CEDETEC.

+ ` + }; + + await transporter.sendMail(mailOptions); +} + +module.exports = enviarCorreoInscripcion; diff --git a/server/controller/Profesor/inscripcionProfesor.js b/server/controller/Profesor/inscripcionProfesor.js new file mode 100644 index 0000000..e4a80e2 --- /dev/null +++ b/server/controller/Profesor/inscripcionProfesor.js @@ -0,0 +1,66 @@ +const Usuario = require('../../db/tablas/Usuario'); // Asegúrate de importar correctamente +const inscripcion = require('../../db/tablas/Inscripcion'); +const enviarCorreoInscripcion = require('../../controller/Profesor/enviarCorreo'); // Ajusta si está en otra ruta +const { where } = require('sequelize'); + +async function realizarInscripcion(req, res) { + const { idUsuario, nombre, numeroCuenta, correo } = req.body; + + try { + if (!nombre || !numeroCuenta || !idUsuario) { + return res.status(400).json({ message: 'Faltan datos requeridos.' }); + } + + // 1. Buscar si el usuario existe + const usuario = await Usuario.findOne({ where: { numeroCuenta } }); + + if (!usuario) { + return res.status(404).json({ message: 'Usuario no encontrado en la base de datos.' }); + } + + // 2. Verificar si ya tiene inscripción + const inscripcionExistente = await inscripcion.findOne({ + where: { idUsuario: usuario.idUsuario } + }); + + if (inscripcionExistente) { + return res.status(200).json({ + yaInscrito: true, + message: 'El usuario ya está inscrito.', + }); + } + + // 3. Crear inscripción + await inscripcion.create({ + idUsuario: usuario.idUsuario, + idArea: 1, // Cambiar si se requiere otro valor + validacion: 2, + confirmacion: false, + folio: null, + monto: null, + hizoPago: null, + rutaTicket: null, + extension: null, + fechaInscripcion: null, // fechaInscripcion: new Date() + fechaTicket: null + }); + + // 4. Realizar confirmacion + await inscripcion.update( + { confirmacion: true }, + { where: { idUsuario: usuario.idUsuario } } + ); + + // 5. Enviar correo + await enviarCorreoInscripcion(correo, nombre); + + // 6. Respuesta final + res.status(200).json({ message: 'Inscripción creada y correo enviado correctamente.' }); + + } catch (error) { + console.error('Error en realizarInscripcion:', error); + res.status(500).json({ message: 'Error al procesar la inscripción o enviar el correo.' }); + } +} + +module.exports = { realizarInscripcion }; diff --git a/server/db/install.js b/server/db/install.js index aeb300e..925b512 100644 --- a/server/db/install.js +++ b/server/db/install.js @@ -7,6 +7,8 @@ const Area = require('./tablas/Area'); const FechaInscripcion = require('./tablas/FechaInscripcion'); const Inscripcion = require('./tablas/Inscripcion'); const Admin = require('./tablas/Admin'); +const ProfesorInscrito = require('./tablas/ProfesorInscrito'); +const Profesor = require('./tablas/Profesor'); const drop = async () => { console.log('\nPaso 1) Desinstalando la db.'.bold.blue); @@ -28,6 +30,15 @@ const drop = async () => { await Carrera.drop(); console.log('La tabla Carrera se desinstalo correctamente.'.magenta); + /* + await ProfesorInscrito.drop(); + console.log('La tabla ProfesorInscrito se desinstalo correctamente.'.magenta); + + await Profesor.drop(); + console.log('La tabla Profesor se desinstalo correctamente.'.magenta); + */ + //await ProfesorInscrito.drop().catch(console.error); // Tiene FK hacia Profesor + //await Profesor.drop().catch(console.error); }; const sync = async () => { @@ -50,6 +61,14 @@ const sync = async () => { await Inscripcion.sync(); console.log('La tabla Inscripcion se instalo correctamente.'.magenta); + + /* + await Profesor.sync(); + console.log('La tabla Profesor se instalo correctamente.'.magenta); + + await ProfesorInscrito.sync(); + console.log('La tabla ProfesorInscrito se instalo correctamente.'.magenta); + */ }; const dataArea = async () => { @@ -61,6 +80,16 @@ const dataArea = async () => { const dataAdmin = async () => { console.log('\nPaso 4) Insertando admin.'.bold.blue); + + /* + //Borrar esta linea de codigo + console.log('Admin password:', process.env.ADMIN_PASSWORD); + + //Eliminar esta linea de codigo + const pwdHasheada = encriptar.encriptar(process.env.ADMIN_PASSWORD); + console.log('Password hasheada:', pwdHasheada); + */ + await Admin.create({ idTipoUsuario: 1, usuario: 'Araceli', diff --git a/server/db/tablas/Profesor.js b/server/db/tablas/Profesor.js new file mode 100644 index 0000000..e05e2b5 --- /dev/null +++ b/server/db/tablas/Profesor.js @@ -0,0 +1,39 @@ +const { unique } = require("next/dist/build/utils"); +const { DataTypes, Model } = require("sequelize"); +const sequelize = require('../../config/sequelize.conf'); + +class Profesor extends Model{} +Profesor.init( + { + idProfesor: { + type: DataTypes.INTEGER, + primaryKey: true, + allowNull: false, + unique: true, + autoIncrement: true, + }, + nombre: { + type: DataTypes.STRING(100), + allowNull: true, + defaultValue: null, + }, + rfc: { + type: DataTypes.STRING(10), + allowNull: false, + unique: true, + }, + homo: { + type: DataTypes.STRING(3), + allowNull: false, + unique: true, + }, + }, + { + sequelize, + modelName: 'Profesor', + tableName: 'profesor', + timestamps: false, + }, +) + +module.exports = Profesor; \ No newline at end of file diff --git a/server/db/tablas/ProfesorInscrito.js b/server/db/tablas/ProfesorInscrito.js new file mode 100644 index 0000000..862131f --- /dev/null +++ b/server/db/tablas/ProfesorInscrito.js @@ -0,0 +1,42 @@ +const { Model, DataTypes } = require("sequelize"); +const Profesor = require("./Profesor"); +const sequelize = require('../../config/sequelize.conf'); + +class ProfesorInscrito extends Model {} + +ProfesorInscrito.init( + { + idProfesorInscrito: { + type: DataTypes.INTEGER, + primaryKey: true, + unique: true, + allowNull: false, + autoIncrement: true, + }, + fechaRegistro: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + }, + { + sequelize, + modelName: 'ProfesorInscrito', + tableName: 'profesorInscrito', + timestamps: false, + } +); + +// Relación (Sequelize crea automáticamente idProfesor con FK) +ProfesorInscrito.belongsTo(Profesor, { + foreignKey: { + name: 'idProfesor', + type: DataTypes.INTEGER, + allowNull: false, + }, +}); + + +module.exports = ProfesorInscrito; + + diff --git a/server/db/tablas/Usuario.js b/server/db/tablas/Usuario.js index abb094a..70c0ac0 100644 --- a/server/db/tablas/Usuario.js +++ b/server/db/tablas/Usuario.js @@ -43,12 +43,12 @@ Usuario.init( } ); -// Usuario.belongsTo(Carrera, { -// foreignKey: { -// name: 'idCarrera', -// type: DataTypes.INTEGER, -// allowNull: false, -// }, -// }); +Usuario.belongsTo(Carrera, { + foreignKey: { + name: 'idCarrera', + type: DataTypes.INTEGER, + allowNull: false, + }, +}); module.exports = Usuario; diff --git a/server/helper/encriptar.js b/server/helper/encriptar.js index 423c929..a853b33 100644 --- a/server/helper/encriptar.js +++ b/server/helper/encriptar.js @@ -6,8 +6,22 @@ const comparar = (password, dbPassword) => { return true; }; -const encriptar = (password) => - bcrypt.hashSync(password, Number(process.env.SALT_ROUNDS)); +const encriptar = (password) => { + /* + bcrypt.hashSync(password, Number(process.env.SALT_ROUNDS)); + + const rounds = Number(process.env.SALT_ROUNDS) || 10; + console.log('Rounds para hashSync:', rounds); + return bcrypt.hashSync(password, rounds); + + const rounds = Number(process.env.SALT_ROUNDS) || 10; + console.log('Rounds para hashSync:', rounds); + console.log('Password recibido en encriptar:', password); // <-- agrega esto + return bcrypt.hashSync(password, rounds); + */ + const rounds = Number(process.env.SALT_ROUNDS) || 10; + return bcrypt.hashSync(password, rounds); +} const generarPassword = () => { const length = 8; diff --git a/server/middleware/autentificacion.js b/server/middleware/autentificacion.js index b336d8d..346a58f 100644 --- a/server/middleware/autentificacion.js +++ b/server/middleware/autentificacion.js @@ -43,4 +43,8 @@ const crearTokenOperador = (data) => { }); }; + + + + module.exports = { verificaToken, crearToken, crearTokenAdmin }; diff --git a/server/routes/Profesor.js b/server/routes/Profesor.js new file mode 100644 index 0000000..643247b --- /dev/null +++ b/server/routes/Profesor.js @@ -0,0 +1,76 @@ +const express = require('express'); +const router = express.Router(); +const buscarProfesor = require('../controller/Profesor/buscarProfesor'); +const { realizarInscripcion } = require('../controller/Profesor/inscripcionProfesor'); + +//const Usuario = require('../controller/Profesor/Usuario'); + + +router.get('/:numeroTrabajador', buscarProfesor); + +// POST: inscribir profesor y enviar correo +router.post('/inscripcion', realizarInscripcion); + + +/* +// Ruta POST para inscribir profesor y enviar correo +router.post('/inscripcion', async (req, res) => { + // Buscar al usuario por correo o nombre, dependiendo de qué campo sea único o útil + const usuario = await Usuario.findOne({ + where: { correo } // o por nombre si es único, pero mejor por correo + }); + + if (!usuario) { + return res.status(404).json({ message: 'Usuario no encontrado en la base de datos.' }); + } + + // Verificar si ya tiene una inscripción + const inscripcionExistente = await Inscripcion.findOne({ + where: { idUsuario: usuario.idUsuario } + }); + + if (inscripcionExistente) { + return res.status(200).json({ message: 'El usuario ya está inscrito.' }); + } + + // Crear inscripción con campos opcionales como null + await Inscripcion.create({ + idUsuario: usuario.idUsuario, + idArea: 1, // puedes cambiar esto si lo tienes dinámico + validacion: 2, + confirmacion: false, + folio: null, + monto: null, + hizoPago: null, + rutaTicket: null, + extension: null, + fechaInscripcion: null, + fechaTicket: null, + }); + + try { + const { correo, nombre } = req.body; + + //Borrar esta linea de codigo + //console.log('Datos recibidos:', correo, nombre); // ← Agrega esto + //console.log('Datos recibidos:', req.body); // Agrega esto + + if (!correo || !nombre) { + return res.status(400).json({ message: 'Faltan datos requeridos.' }); + } + + //aqui tengo que aplicar la logica para crear al prodesor inscrito + + + await enviarCorreoInscripcion(correo, nombre); + res.status(200).json({ message: 'Correo enviado correctamente.' }); + } catch (error) { + console.error(error); + res.status(500).json({ message: 'Error al enviar el correo.' }); + } + +}); +*/ + + +module.exports = router; From 31f2add1c090aa364dd0f3c195a19a6b05788302 Mon Sep 17 00:00:00 2001 From: santiago Date: Sat, 9 Aug 2025 09:03:32 -0600 Subject: [PATCH 2/2] Modificacion del controller de enviar correo --- server/controller/Profesor/enviarCorreo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/controller/Profesor/enviarCorreo.js b/server/controller/Profesor/enviarCorreo.js index d8f7697..024e704 100644 --- a/server/controller/Profesor/enviarCorreo.js +++ b/server/controller/Profesor/enviarCorreo.js @@ -11,7 +11,7 @@ async function enviarCorreoInscripcion(correo, nombre) { const mailOptions = { from: '"CEDETEC"', - to: 'smtrabajos5@gmail.com', + to: correo, subject: 'Confirmación de inscripción CEDETEC', html: `