Explora Cursos

Catálogo siempre actualizado

img
  • 169 Students
  • 12 Lessons

">

(09 Reviews)
$674.00
  • 3 hr 40 min
¡Exacto! Separar los videos y los cuestionarios por temario es una excelente decisión tanto por rendimiento como por estructura lógica. Te explico por qué y cómo podrías modelarlo: 📦 Estructura recomendada (continuando con la normalización): Tabla: temario temario_id (PK) curso_id (FK a cursos) titulo descripcion orden (para definir el orden del temario dentro del curso) duracion_estimada (opcional, por ejemplo: 10 min) Tabla: videos video_id (PK) temario_id (FK a temario) titulo url_video o archivo_ruta duracion descripcion (opcional) Tabla: cuestionarios cuestionario_id (PK) temario_id (FK a temario) titulo descripcion tiempo_limite intentos_maximos Tabla: preguntas pregunta_id (PK) cuestionario_id (FK a cuestionarios) texto_pregunta tipo (por ejemplo: opción múltiple, verdadero/falso, etc.) Tabla: respuestas respuesta_id (PK) pregunta_id (FK a preguntas) texto_respuesta es_correcta (boolean) CREATE TABLE cursos ( curso_id INT AUTO_INCREMENT PRIMARY KEY, curso_titulo VARCHAR(255) NOT NULL, descripcion TEXT, categoria_id INT NOT NULL, detalle_id INT, empresa_id INT NOT NULL, fecha_inicio DATE, fecha_fin DATE, imagen VARCHAR(255), precio DECIMAL(10, 2) DEFAULT 0.00, estado ENUM('activo', 'inactivo') DEFAULT 'activo', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_curso_titulo (curso_titulo), INDEX idx_categoria_id (categoria_id), INDEX idx_empresa_id (empresa_id), FOREIGN KEY (categoria_id) REFERENCES categorias(categoria_id), FOREIGN KEY (detalle_id) REFERENCES detalles_curso(detalle_id), FOREIGN KEY (empresa_id) REFERENCES empresas(empresa_id) ); CREATE TABLE categorias ( categoria_id INT AUTO_INCREMENT PRIMARY KEY, nombre_categoria VARCHAR(100) NOT NULL UNIQUE, descripcion TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE detalles_curso ( detalle_id INT AUTO_INCREMENT PRIMARY KEY, objetivos TEXT, temario TEXT, requisitos TEXT, beneficios TEXT, duracion VARCHAR(50), recursos TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE empresas ( empresa_id INT AUTO_INCREMENT PRIMARY KEY, nombre_empresa VARCHAR(255) NOT NULL UNIQUE, rfc VARCHAR(20), direccion TEXT, contacto VARCHAR(255) NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE promotorias ( promotoria_id INT AUTO_INCREMENT PRIMARY KEY, nombre_promotoria VARCHAR(255) NOT NULL UNIQUE, empresa_id INT, contacto VARCHAR(255) NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE puestos ( puesto_id INT AUTO_INCREMENT PRIMARY KEY, nombre_puesto VARCHAR(255) NOT NULL UNIQUE, ); CREATE TABLE roles ( rol_id INT AUTO_INCREMENT PRIMARY KEY, nombre_rol VARCHAR(255) NOT NULL UNIQUE, ); CREATE TABLE usuarios ( usuario_id INT AUTO_INCREMENT PRIMARY KEY, nombre_completo VARCHAR(255), rfc VARCHAR(25) UNIQUE, promotoria_id INT, curp VARCHAR(25) UNIQUE, puesto_id INT, estado_lugar VARCHAR(250), status ENUM('ACTIVO', 'INACTIVO') DEFAULT 'ACTIVO', email VARCHAR(150) UNIQUE, password VARCHAR(250), rol_id INT, fecha_ingreso DATE NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (promotoria_id) REFERENCES promotorias(promotoria_id), FOREIGN KEY (puesto_id) REFERENCES puestos(puesto_id), FOREIGN KEY (rol_id) REFERENCES roles(rol_id), ); CREATE TABLE cursos_usuario ( curso_usuario_ id INT AUTO_INCREMENT PRIMARY KEY, curso_id INT, usuario_id INT, fecha_inscripcion DATETIME DEFAULT CURRENT_TIMESTAMP, fecha_finalizacion DATETIME, estatus ENUM('inscrito', 'en_progreso', 'finalizado', 'cancelado') DEFAULT 'inscrito', calificacion DECIMAL(4,2), FOREIGN KEY (curso_id) REFERENCES cursos(curso_id), FOREIGN KEY (usuario_id) REFERENCES usuarios(usuario_id), INDEX idx_usuario_id (usuario_id), INDEX idx_curso_id (curso_id) ); CREATE TABLE calificaciones ( calificacion_id INT AUTO_INCREMENT PRIMARY KEY, curso_id INT, usuario_id INT, puntuacion INT CHECK (puntuacion BETWEEN 1 AND 5), comentario TEXT, fecha DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (curso_id) REFERENCES cursos(curso_id), FOREIGN KEY (usuario_id) REFERENCES usuarios(usuario_id) ); ----------------------------------------------------------- CREATE TABLE cuestionarios ( cuestionario_id INT AUTO_INCREMENT PRIMARY KEY, curso_id INT, titulo VARCHAR(255) NOT NULL, descripcion TEXT, fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (curso_id) REFERENCES cursos(curso_id) ); CREATE TABLE preguntas ( pregunta_id INT AUTO_INCREMENT PRIMARY KEY, cuestionario_id INT, texto_pregunta TEXT NOT NULL, tipo ENUM('opcion_multiple', 'verdadero_falso', 'respuesta_abierta') NOT NULL, FOREIGN KEY (cuestionario_id) REFERENCES cuestionarios(cuestionario_id) ); CREATE TABLE respuestas ( respuesta_id INT AUTO_INCREMENT PRIMARY KEY, pregunta_id INT, texto_respuesta TEXT NOT NULL, es_correcta BOOLEAN DEFAULT FALSE, FOREIGN KEY (pregunta_id) REFERENCES preguntas(pregunta_id) ); CREATE TABLE respuestas_usuario ( respuesta_usuario_id INT AUTO_INCREMENT PRIMARY KEY, usuario_id INT, pregunta_id INT, respuesta_id INT NULL, -- si es opción múltiple / verdadero-falso respuesta_texto TEXT NULL, -- si es abierta fecha_respuesta DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (usuario_id) REFERENCES usuarios(usuario_id), FOREIGN KEY (pregunta_id) REFERENCES preguntas(pregunta_id), FOREIGN KEY (respuesta_id) REFERENCES respuestas(respuesta_id) ); --------------------------------------------- contraseña Promotoria2025 ---------------------------------------------TBL_DETALLESCURSO----------------------------- Desglose de la Tabla detalles_curso detalle_id (INT, AUTO_INCREMENT, PRIMARY KEY): Identificador único para cada conjunto de detalles del curso. AUTO_INCREMENT genera automáticamente valores únicos. PRIMARY KEY asegura que no haya detalles duplicados. curso_id (INT, UNIQUE, NOT NULL, FOREIGN KEY): Clave externa que conecta esta tabla con la tabla cursos. UNIQUE es crucial para la relación 1:1: cada curso tiene solo un conjunto de detalles. NOT NULL garantiza que cada detalle esté asociado a un curso. FOREIGN KEY (curso_id) REFERENCES cursos(curso_id) establece la relación con la clave primaria curso_id en la tabla cursos. objetivos_aprendizaje (TEXT): Descripción detallada de lo que los estudiantes podrán hacer después del curso. audiencia_objetivo (VARCHAR(255)): Grupo de empleados o personas a quienes está dirigido el curso. requisitos_previos (TEXT): Conocimientos, habilidades o cursos necesarios antes de tomar este curso. duracion (VARCHAR(100)): Tiempo que dura el curso (por ejemplo, "5 días", "40 horas"). modalidad (VARCHAR(50)): Formato del curso (por ejemplo, "En línea", "Presencial", "Híbrido"). materiales_curso (TEXT): Lista o descripción de los materiales proporcionados a los estudiantes. evaluacion (VARCHAR(255)): Métodos utilizados para evaluar el aprendizaje de los estudiantes. instructor (VARCHAR(255)): Nombre del instructor o facilitador del curso. ubicacion (VARCHAR(255)): Lugar donde se imparte el curso (si es presencial) o plataforma (si es en línea). horario_sesiones (VARCHAR(255)): Días y horas de las sesiones del curso. created_at (DATETIME, DEFAULT CURRENT_TIMESTAMP): Fecha y hora en que se creó el registro. DEFAULT CURRENT_TIMESTAMP establece la fecha y hora actual por defecto. updated_at (DATETIME, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP): Fecha y hora en que se actualizó el registro por última vez. ON UPDATE CURRENT_TIMESTAMP actualiza automáticamente la fecha y hora cuando se modifica el registro. --------------------------------------------TABLAS YA APROBADAS --------------------------------------------- SQL: SELECT c.* FROM cursos c JOIN cursos_promotorias cp ON c.curso_id = cp.curso_id WHERE cp.promotoria_id = [promotoria_id_deseada]; CREATE TABLE empresas ( empresa_id INT AUTO_INCREMENT PRIMARY KEY, nombre_empresa VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); CREATE TABLE promotorias ( promotoria_id INT AUTO_INCREMENT PRIMARY KEY, empresa_id INT NOT NULL, nombre_promotoria VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (empresa_id) REFERENCES empresas(empresa_id) ); CREATE TABLE cursos_promotorias ( curso_promotoria_id INT AUTO_INCREMENT PRIMARY KEY, curso_id INT NOT NULL, promotoria_id INT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (curso_id) REFERENCES cursos(curso_id), FOREIGN KEY (promotoria_id) REFERENCES promotorias(promotoria_id), UNIQUE KEY unique_curso_promotoria (curso_id, promotoria_id) -- Asegura que no haya duplicados en la relación ); CREATE TABLE cuestionarios ( cuestionario_id INT AUTO_INCREMENT PRIMARY KEY, curso_id INT NOT NULL, titulo VARCHAR(255) NOT NULL, descripcion TEXT, fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP, fecha_actualizacion DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (curso_id) REFERENCES cursos(curso_id) ); CREATE TABLE preguntas ( pregunta_id INT AUTO_INCREMENT PRIMARY KEY, cuestionario_id INT NOT NULL, texto_pregunta TEXT NOT NULL, puntaje DECIMAL(5, 2) NOT NULL, fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP, fecha_actualizacion DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (cuestionario_id) REFERENCES cuestionarios(cuestionario_id) ); CREATE TABLE opciones_pregunta ( opcion_id INT AUTO_INCREMENT PRIMARY KEY, pregunta_id INT NOT NULL, texto_opcion VARCHAR(255) NOT NULL, es_correcta BOOLEAN DEFAULT FALSE, FOREIGN KEY (pregunta_id) REFERENCES preguntas(pregunta_id) ); CREATE TABLE usuarios_cursos ( usuario_curso_id INT AUTO_INCREMENT PRIMARY KEY, usuario_id INT NOT NULL, curso_id INT NOT NULL, fecha_inscripcion DATETIME DEFAULT CURRENT_TIMESTAMP, progreso DECIMAL(5,2) DEFAULT 0.00, -- Porcentaje de progreso en el curso estado_curso ENUM('En curso', 'Completado', 'Abandonado') DEFAULT 'En curso', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, calificacion_final DECIMAL(5,2) NULL, FOREIGN KEY (usuario_id) REFERENCES usuarios(usuario_id), FOREIGN KEY (curso_id) REFERENCES cursos(curso_id), UNIQUE KEY unique_usuario_curso (usuario_id, curso_id) -- Evita duplicados ); CREATE TABLE respuestas_usuario ( respuesta_id INT AUTO_INCREMENT PRIMARY KEY, usuario_curso_id INT NOT NULL, pregunta_id INT NOT NULL, opcion_seleccionada_id INT NOT NULL, es_correcta BOOLEAN, -- Redundante pero útil para consultas puntaje_obtenido DECIMAL(5, 2), fecha_respuesta DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (usuario_curso_id) REFERENCES usuarios_cursos(usuario_curso_id), FOREIGN KEY (pregunta_id) REFERENCES preguntas(pregunta_id), FOREIGN KEY (opcion_seleccionada_id) REFERENCES opciones_pregunta(opcion_id) ); ------------------------------------------------------------------------------------------------ FUNCION PARA CONVERTR LA FECHA EN FORMATO 2025-04-10 EN 10 DE ABRIL 2025 function formatearFecha(fechaString) { /** * Convierte una cadena de fecha en formato 'YYYY-MM-DD' a 'DD de Mes de AAAA'. * * @param {string} fechaString La cadena de fecha a convertir (ej: '2025-05-12'). * @returns {string} La cadena de fecha formateada (ej: '12 de Mayo de 2025') o un mensaje de error. */ try { const fechaObj = new Date(fechaString.replace(/-/g, '/')); // Replace - with / for better parsing if (isNaN(fechaObj.getTime())) { // Check for invalid date return "Formato de fecha inválido. Por favor, use AAAA-MM-DD."; } const meses = [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" ]; const dia = fechaObj.getDate(); const mes = meses[fechaObj.getMonth()]; const anio = fechaObj.getFullYear(); return `${dia} de ${mes} de ${anio}`; } catch (error) { return "Error al formatear la fecha: " + error.message; } } // Ejemplos de uso: let fecha = "2025-05-12"; let fechaFormateada = formatearFecha(fecha); console.log(`Fecha original: ${fecha}`); console.log(`Fecha formateada: ${fechaFormateada}`); fecha = "2025-10-01"; fechaFormateada = formatearFecha(fecha); console.log(`Fecha original: ${fecha}`); console.log(`Fecha formateada: ${fechaFormateada}`); fecha = "2025/10/01"; // Formato inválido - pero parseado con el replace fechaFormateada = formatearFecha(fecha); console.log(`Fecha original: ${"2025/10/01"}`); console.log(`Fecha formateada: ${fechaFormateada}`); fecha = "invalid-date"; // Realmente inválido fechaFormateada = formatearFecha(fecha); console.log(`Fecha original: ${"invalid-date"}`); console.log(`Fecha formateada: ${fechaFormateada}`); //////////////////////////////////////////////////////////////////////////////////////////ASIGANACION DE promotorias










2. PHP (Backend - Obtener Cursos y Promotorias para el Formulario) 3. JavaScript (Frontend - Enviar y Manejar la Solicitud) async function asignarCurso() { let cursoId = document.getElementById('curso_id').value; let promotoriasSeleccionadas = []; let checkboxes = document.querySelectorAll('input[name="promotorias[]"]:checked'); checkboxes.forEach(checkbox => { promotoriasSeleccionadas.push(checkbox.value); }); let fechaInicio = document.getElementById('fecha_inicio').value; let fechaFin = document.getElementById('fecha_fin').value; let precioPromotoria = document.getElementById('precio_promotoria').value; let mensajeDiv = document.getElementById('mensaje'); mensajeDiv.textContent = 'Enviando...'; const datos = { curso_id: cursoId, promotorias: promotoriasSeleccionadas, fecha_inicio: fechaInicio, fecha_fin: fechaFin, precio_promotoria: precioPromotoria }; try { const respuesta = await fetch('/api/asignar-curso.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(datos) }); const resultado = await respuesta.json(); if (respuesta.ok) { mensajeDiv.textContent = resultado.mensaje; mensajeDiv.style.color = 'green'; } else { mensajeDiv.textContent = resultado.mensaje; mensajeDiv.style.color = 'red'; } } catch (error) { mensajeDiv.textContent = 'Error de conexión: ' + error.message; mensajeDiv.style.color = 'red'; } } 4. PHP (Backend - Recibir y Procesar la Solicitud) false, 'mensaje' => 'Datos inválidos.']); exit; } $errores = []; // Validar si el curso existe $sql_curso_existe = "SELECT 1 FROM Cursos WHERE ID_Curso = ?"; $stmt_curso_existe = mysqli_prepare($conexion, $sql_curso_existe); mysqli_stmt_bind_param($stmt_curso_existe, "i", $cursoId); mysqli_stmt_execute($stmt_curso_existe); mysqli_stmt_store_result($stmt_curso_existe); if (mysqli_stmt_num_rows($stmt_curso_existe) == 0) { $errores[] = "El curso seleccionado no existe."; } // Validar si las promotorias existen foreach ($promotorias as $promotoriaId) { if (!is_numeric($promotoriaId)) { $errores[] = "ID de promotoria inválido: $promotoriaId"; continue; } $sql_promotoria_existe = "SELECT 1 FROM Promotoria WHERE ID_Promotoria = ?"; $stmt_promotoria_existe = mysqli_prepare($conexion, $sql_promotoria_existe); mysqli_stmt_bind_param($stmt_promotoria_existe, "i", $promotoriaId); mysqli_stmt_execute($stmt_promotoria_existe); mysqli_stmt_store_result($stmt_promotoria_existe); if (mysqli_stmt_num_rows($stmt_promotoria_existe) == 0) { $errores[] = "La promotoria con ID $promotoriaId no existe."; } mysqli_stmt_free_result($stmt_promotoria_existe); mysqli_stmt_close($stmt_promotoria_existe); // Cierra este statement despues de ejecutar } if (!empty($errores)) { echo json_encode(['exito' => false, 'mensaje' => implode("
", $errores)]); // Une los errores en un string exit; } // Si la validacion pasa, aqui insertamos mysqli_begin_transaction($conexion); // Iniciar transacción para asegurar atomicidad $insertado = true; // Iniciar flag en verdadero; foreach ($promotorias as $promotoriaId) { $sql = "INSERT INTO Curso_Promotoria (ID_Curso, ID_Promotoria, Fecha_Inicio_Oferta, Fecha_Fin_Oferta, Precio_Promotoria) VALUES (?, ?, ?, ?, ?)"; $stmt = mysqli_prepare($conexion, $sql); mysqli_stmt_bind_param($stmt, "iisss", $cursoId, $promotoriaId, $fechaInicio, $fechaFin, $precioPromotoria); if(!mysqli_stmt_execute($stmt)){ $insertado = false; break; // Sale del bucle ante el primer fallo } mysqli_stmt_free_result($stmt); mysqli_stmt_close($stmt); } if ($insertado) { mysqli_commit_transaction($conexion); echo json_encode(['exito' => true, 'mensaje' => 'Curso asignado a promotorias correctamente.']); } else { mysqli_rollback_transaction($conexion); echo json_encode(['exito' => false, 'mensaje' => 'Error al asignar curso a promotorias.']); } mysqli_close($stmt); } else { echo json_encode(['exito' => false, 'mensaje' => 'Solicitud inválida.']); } ?>