-- ===================================================================== -- Portal Interno INSTA — esquema -- Instituto Santiago Tapia · Morelia, Michoacán -- MySQL 8.0 · utf8mb4 -- ===================================================================== -- El portal es una base de conocimiento: oferta educativa, requisitos, -- becas y fechas, links de clases, preguntas frecuentes y contacto. -- El catálogo lo edita dirección; los links de clases, dirección y -- administración. Toda edición queda en la bitácora. -- -- El esquema se reconstruye completo en cada `npm run db:reset`. SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS bitacora; DROP TABLE IF EXISTS sesiones; DROP TABLE IF EXISTS magic_tokens; DROP TABLE IF EXISTS clases; DROP TABLE IF EXISTS programas_modalidades; DROP TABLE IF EXISTS requisitos; DROP TABLE IF EXISTS programas; DROP TABLE IF EXISTS modalidades; DROP TABLE IF EXISTS niveles; DROP TABLE IF EXISTS promociones; DROP TABLE IF EXISTS guiones; DROP TABLE IF EXISTS kb_articulos; DROP TABLE IF EXISTS titulacion_opciones; DROP TABLE IF EXISTS institucional; DROP TABLE IF EXISTS discrepancias; DROP TABLE IF EXISTS roles_permisos; DROP TABLE IF EXISTS permisos; DROP TABLE IF EXISTS usuarios; DROP TABLE IF EXISTS roles; -- Tablas de la versión anterior del portal, ya retiradas. DROP TABLE IF EXISTS prospectos_etiquetas; DROP TABLE IF EXISTS prospectos; DROP TABLE IF EXISTS pendientes; DROP TABLE IF EXISTS cotizaciones; DROP TABLE IF EXISTS metricas_crm; DROP TABLE IF EXISTS etiquetas; SET FOREIGN_KEY_CHECKS = 1; -- --------------------------------------------------------------------- -- 1. Identidad, roles y permisos -- --------------------------------------------------------------------- CREATE TABLE roles ( id INT AUTO_INCREMENT PRIMARY KEY, clave VARCHAR(32) NOT NULL UNIQUE, nombre VARCHAR(64) NOT NULL, nivel TINYINT NOT NULL COMMENT '3 dirección · 2 administración · 1 empleado', color CHAR(7) NOT NULL DEFAULT '#4275B7', descripcion VARCHAR(255) NOT NULL DEFAULT '' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE permisos ( id INT AUTO_INCREMENT PRIMARY KEY, clave VARCHAR(48) NOT NULL UNIQUE COMMENT 'seccion.accion', seccion VARCHAR(32) NOT NULL, descripcion VARCHAR(255) NOT NULL DEFAULT '' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE roles_permisos ( rol_id INT NOT NULL, permiso_id INT NOT NULL, PRIMARY KEY (rol_id, permiso_id), CONSTRAINT fk_rp_rol FOREIGN KEY (rol_id) REFERENCES roles(id) ON DELETE CASCADE, CONSTRAINT fk_rp_permiso FOREIGN KEY (permiso_id) REFERENCES permisos(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE usuarios ( id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(96) NOT NULL, email VARCHAR(160) NOT NULL UNIQUE, puesto VARCHAR(96) NOT NULL DEFAULT '', rol_id INT NOT NULL, iniciales CHAR(2) NOT NULL DEFAULT '??', extension VARCHAR(16) NOT NULL DEFAULT '', activo TINYINT(1) NOT NULL DEFAULT 1, es_demo TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'visible en el acceso rápido de la demo', ultimo_acceso DATETIME NULL, creado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_usuario_rol FOREIGN KEY (rol_id) REFERENCES roles(id), INDEX idx_usuarios_rol (rol_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- Magic Login: el token nunca se guarda en claro, solo su SHA-256. CREATE TABLE magic_tokens ( id INT AUTO_INCREMENT PRIMARY KEY, usuario_id INT NOT NULL, token_hash CHAR(64) NOT NULL UNIQUE, proposito VARCHAR(32) NOT NULL DEFAULT 'login', creado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, expira_en DATETIME NOT NULL, usado_en DATETIME NULL, ip_origen VARCHAR(64) NOT NULL DEFAULT '', CONSTRAINT fk_token_usuario FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE CASCADE, INDEX idx_tokens_usuario (usuario_id), INDEX idx_tokens_expira (expira_en) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE sesiones ( id CHAR(64) PRIMARY KEY COMMENT 'SHA-256 del id que viaja en la cookie', usuario_id INT NOT NULL, creada_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, expira_en DATETIME NOT NULL, user_agent VARCHAR(255) NOT NULL DEFAULT '', ip_origen VARCHAR(64) NOT NULL DEFAULT '', CONSTRAINT fk_sesion_usuario FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE CASCADE, INDEX idx_sesiones_usuario (usuario_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE bitacora ( id BIGINT AUTO_INCREMENT PRIMARY KEY, usuario_id INT NULL, actor VARCHAR(96) NOT NULL DEFAULT 'sistema', rol VARCHAR(32) NOT NULL DEFAULT '', accion VARCHAR(64) NOT NULL, entidad VARCHAR(48) NOT NULL DEFAULT '', entidad_id VARCHAR(48) NOT NULL DEFAULT '', resultado VARCHAR(16) NOT NULL DEFAULT 'ok' COMMENT 'ok · denegado · error', detalle VARCHAR(500) NOT NULL DEFAULT '', ip_origen VARCHAR(64) NOT NULL DEFAULT '', creado_en DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), CONSTRAINT fk_bitacora_usuario FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE SET NULL, INDEX idx_bitacora_creado (creado_en), INDEX idx_bitacora_accion (accion) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- --------------------------------------------------------------------- -- 2. Oferta educativa -- --------------------------------------------------------------------- CREATE TABLE niveles ( id INT AUTO_INCREMENT PRIMARY KEY, clave VARCHAR(32) NOT NULL UNIQUE, nombre VARCHAR(64) NOT NULL, orden TINYINT NOT NULL DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE modalidades ( id INT AUTO_INCREMENT PRIMARY KEY, clave VARCHAR(32) NOT NULL UNIQUE, nombre VARCHAR(64) NOT NULL, color CHAR(7) NOT NULL DEFAULT '#5E35B1', detalle VARCHAR(200) NOT NULL DEFAULT '' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE programas ( id INT AUTO_INCREMENT PRIMARY KEY, nivel_id INT NOT NULL, clave VARCHAR(48) NOT NULL UNIQUE, nombre VARCHAR(120) NOT NULL, nombre_corto VARCHAR(48) NOT NULL, duracion VARCHAR(48) NOT NULL, fecha_inicio VARCHAR(32) NOT NULL, inscripcion_lista DECIMAL(10,2) NOT NULL, inscripcion_beca DECIMAL(10,2) NOT NULL, mensualidad_lista DECIMAL(10,2) NOT NULL, mensualidad_beca DECIMAL(10,2) NOT NULL, ciclo_semanas SMALLINT NULL, rvoe_acuerdo VARCHAR(48) NOT NULL DEFAULT '', rvoe_fecha DATE NULL, rvoe_autoridad VARCHAR(120) NOT NULL DEFAULT '', rvoe_estado VARCHAR(24) NOT NULL DEFAULT 'confirmado' COMMENT 'confirmado · revisar · por-confirmar', rvoe_nota VARCHAR(500) NOT NULL DEFAULT '', beneficios VARCHAR(500) NOT NULL DEFAULT '', color CHAR(7) NOT NULL DEFAULT '#17A171', orden TINYINT NOT NULL DEFAULT 0, activo TINYINT(1) NOT NULL DEFAULT 1, actualizado_por INT NULL, actualizado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT fk_programa_nivel FOREIGN KEY (nivel_id) REFERENCES niveles(id), CONSTRAINT fk_programa_usuario FOREIGN KEY (actualizado_por) REFERENCES usuarios(id) ON DELETE SET NULL, INDEX idx_programas_nivel (nivel_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE programas_modalidades ( id INT AUTO_INCREMENT PRIMARY KEY, programa_id INT NOT NULL, modalidad_id INT NOT NULL, dias VARCHAR(64) NOT NULL DEFAULT '', hora_inicio VARCHAR(8) NOT NULL DEFAULT '', hora_fin VARCHAR(8) NOT NULL DEFAULT '', nota VARCHAR(160) NOT NULL DEFAULT '', CONSTRAINT fk_pm_programa FOREIGN KEY (programa_id) REFERENCES programas(id) ON DELETE CASCADE, CONSTRAINT fk_pm_modalidad FOREIGN KEY (modalidad_id) REFERENCES modalidades(id) ON DELETE CASCADE, INDEX idx_pm_programa (programa_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE requisitos ( id INT AUTO_INCREMENT PRIMARY KEY, nivel_id INT NOT NULL, texto VARCHAR(160) NOT NULL, nota VARCHAR(200) NOT NULL DEFAULT '', orden TINYINT NOT NULL DEFAULT 0, CONSTRAINT fk_requisito_nivel FOREIGN KEY (nivel_id) REFERENCES niveles(id) ON DELETE CASCADE, INDEX idx_requisitos_nivel (nivel_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE titulacion_opciones ( id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(64) NOT NULL, descripcion VARCHAR(255) NOT NULL DEFAULT '', orden TINYINT NOT NULL DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- --------------------------------------------------------------------- -- 3. Becas, promociones y fechas de inscripción -- --------------------------------------------------------------------- CREATE TABLE promociones ( id INT AUTO_INCREMENT PRIMARY KEY, clave VARCHAR(48) NOT NULL UNIQUE, nombre VARCHAR(120) NOT NULL, resumen VARCHAR(200) NOT NULL DEFAULT '' COMMENT 'la frase que se le dice al interesado', aplica_a VARCHAR(24) NOT NULL COMMENT 'inscripcion · mensualidad · ambos', vigencia VARCHAR(120) NOT NULL DEFAULT '', acumulable TINYINT(1) NOT NULL DEFAULT 0, condiciones VARCHAR(900) NOT NULL DEFAULT '', activo TINYINT(1) NOT NULL DEFAULT 1, orden TINYINT NOT NULL DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- --------------------------------------------------------------------- -- 4. Links de clases (Google Meet) -- --------------------------------------------------------------------- CREATE TABLE clases ( id INT AUTO_INCREMENT PRIMARY KEY, programa_id INT NOT NULL, materia VARCHAR(120) NOT NULL, docente VARCHAR(96) NOT NULL DEFAULT '', grupo VARCHAR(48) NOT NULL DEFAULT '' COMMENT 'generación o grupo', dias VARCHAR(64) NOT NULL DEFAULT '', hora_inicio VARCHAR(8) NOT NULL DEFAULT '', hora_fin VARCHAR(8) NOT NULL DEFAULT '', enlace VARCHAR(500) NOT NULL DEFAULT '', notas VARCHAR(300) NOT NULL DEFAULT '', activo TINYINT(1) NOT NULL DEFAULT 1, orden SMALLINT NOT NULL DEFAULT 0, actualizado_por INT NULL, actualizado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, creado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_clase_programa FOREIGN KEY (programa_id) REFERENCES programas(id) ON DELETE CASCADE, CONSTRAINT fk_clase_usuario FOREIGN KEY (actualizado_por) REFERENCES usuarios(id) ON DELETE SET NULL, INDEX idx_clases_programa (programa_id), INDEX idx_clases_materia (materia) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- --------------------------------------------------------------------- -- 5. Conocimiento, contacto y datos por confirmar -- --------------------------------------------------------------------- CREATE TABLE guiones ( id INT AUTO_INCREMENT PRIMARY KEY, categoria VARCHAR(48) NOT NULL, titulo VARCHAR(160) NOT NULL, cuerpo TEXT NOT NULL, canal VARCHAR(24) NOT NULL DEFAULT 'whatsapp', orden SMALLINT NOT NULL DEFAULT 0, INDEX idx_guiones_categoria (categoria) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE kb_articulos ( id INT AUTO_INCREMENT PRIMARY KEY, seccion VARCHAR(48) NOT NULL, pregunta VARCHAR(255) NOT NULL, respuesta TEXT NOT NULL, palabras_clave VARCHAR(255) NOT NULL DEFAULT '', fuente VARCHAR(120) NOT NULL DEFAULT 'Base de conocimiento INSTA', orden SMALLINT NOT NULL DEFAULT 0, INDEX idx_kb_seccion (seccion) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE institucional ( id INT AUTO_INCREMENT PRIMARY KEY, grupo VARCHAR(32) NOT NULL, clave VARCHAR(48) NOT NULL UNIQUE, etiqueta VARCHAR(96) NOT NULL, valor TEXT NOT NULL, orden SMALLINT NOT NULL DEFAULT 0, INDEX idx_institucional_grupo (grupo) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE discrepancias ( id INT AUTO_INCREMENT PRIMARY KEY, titulo VARCHAR(180) NOT NULL, detalle VARCHAR(900) NOT NULL DEFAULT '', ambito VARCHAR(48) NOT NULL DEFAULT 'rvoe', prioridad VARCHAR(16) NOT NULL DEFAULT 'media', estado VARCHAR(24) NOT NULL DEFAULT 'abierto' COMMENT 'abierto · en-proceso · aclarado', responsable VARCHAR(96) NOT NULL DEFAULT 'Dirección', orden SMALLINT NOT NULL DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;