JOSEPAN 360 · Academia Interna

Manual técnico y guía de despliegue

Documento estático Este manual es consultable directamente desde el sistema de archivos (sin servidor) y también vía web una vez desplegado. Cubre la arquitectura, la integración con el OMNI API CORE [1001] y la guía completa de despliegue y configuración.

1. Stack y arquitectura

Plataforma LAMP pura: PHP 8 nativo (sin frameworks, sin Composer, sin Docker), MySQL/MariaDB con PDO, HTML5 + CSS3 + JavaScript Vanilla. La autenticación es centralizada en el OMNI API CORE [1001]; la base de datos local solo persiste la lógica de la academia (progreso, asistencia, telemetría, puntos, certificación), usando el ID de empleado de OMNI como llave de referencia.

Todas las rutas internas son relativas y se resuelven contra una <base href> calculada dinámicamente, de modo que el proyecto funciona igual desplegado en la raíz del dominio o en una subcarpeta.

2. Guía de despliegue y configuración

2.1 Requisitos

2.2 Copia de archivos y DocumentRoot

El DocumentRoot debe apuntar a la carpeta public/. El resto de carpetas (config/, includes/, sdk_omni/, templates/, data/, lib/, downloads/) quedan fuera del webroot por diseño y llevan además un .htaccess que niega el acceso directo.

Opción A — en la raíz del dominio:

<VirtualHost *:443>
    ServerName academia.josepan360.com
    DocumentRoot /var/www/josepan-academia/public
    <Directory /var/www/josepan-academia/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Opción B — en una subcarpeta (p. ej. https://intranet.josepan360.com/academia/): basta con publicar public/ bajo ese alias. Como todas las URLs son relativas, no hay que tocar el código.

Alias /academia /var/www/josepan-academia/public
<Directory /var/www/josepan-academia/public>
    AllowOverride All
    Require all granted
</Directory>
Rutas relativas: el sistema detecta automáticamente la base (raíz o subcarpeta) a partir de SCRIPT_NAME y la publica en <base href>. Las redirecciones del servidor usan la misma base mediante el helper url(). No es necesario configurar ninguna URL absoluta.

2.3 Autoinstalador

Mientras el sistema no esté instalado, cualquier acceso se redirige a install/. Abre esa ruta en el navegador y completa el asistente:

  1. Verificación del entorno: comprueba versión de PHP, extensiones y permisos de escritura en config/ y downloads/.
  2. Parámetros: datos de la base de datos local y URL base del OMNI API CORE, además de sesión, roles y modo desarrollo.
  3. Despliegue: crea la base de datos si no existe, carga schema.sql y ejecuta los seeders (cursos, 4 sesiones, niveles y parámetros).
  4. Configuración: genera config/config.php con los valores validados.
  5. Candado: crea config/installed.lock; a partir de ahí el instalador queda bloqueado.

Como alternativa por consola: mysql -u root -p nombre_bd < schema.sql y luego configurar config/config.php manualmente a partir de config/config.example.php.

2.4 Parámetros de configuración

ConstanteDescripción
DB_HOST / DB_PORT / DB_NAME / DB_USER / DB_PASSConexión a la base de datos local de la academia.
API_CORE_BASEURL base del OMNI API CORE (sin barra final), p. ej. https://omni.josepan.es.
API_PREFIXPrefijo del API, por defecto /api/v1.
SESSION_SECUREtrue para enviar la cookie solo por HTTPS (producción).
SESSION_IDLE_MINMinutos de inactividad antes de cerrar sesión.
ADMIN_ROLES / ADMIN_PERMSRoles del perfil OMNI y permisos (academia.admin) que conceden administración.
DEV_MODE / DEV_USER / DEV_PASSAcceso de prueba si OMNI no responde. Desactivar en producción.

2.5 Documentos de la biblioteca

Sube los PDF a la carpeta downloads/ con los nombres indicados en data/documentos.php. Se sirven exclusivamente a través de descargar.php, que valida la sesión activa.

2.6 Seguridad posterior

3. Integración con el OMNI API CORE [1001]

El login no consulta la base de datos local: instancia el SDK OmniCoreClient (carpeta sdk_omni/) e invoca su método login(), que hace POST {API_CORE_BASE}{API_PREFIX}/auth/login.

POST /api/v1/auth/login
{ "usuario": "herman.torres", "password": "********" }

→ { "data": {
    "token": "JWT-HS256...",
    "user": { "id", "nombre", "rol", "tienda", "email" },
    "permissions": ["academia.admin", "inventory.read", "..."]
} }
$omni = new OmniCoreClient(API_CORE_BASE, API_PREFIX, API_TIMEOUT);
$res  = $omni->login($usuario, $password);
if ($res['ok']) {
    establish_session($res['token'], $res['user'], $res['permissions']);
}

El JWT, el perfil y los permissions[] se guardan en la sesión PHP (cookie HttpOnly, SameSite=Lax, Secure según configuración). El cliente tolera alias de campos (token/accessToken, user/profile, rol/role/cargo, tienda/sede/franquicia).

4. Modelo de datos local (MySQL)

Tablas InnoDB utf8mb4. La PK de empleados es el ID de empleado de OMNI; las tablas transaccionales referencian a empleados y a cursos con FK ON DELETE CASCADE.

5. Telemetría

Al abrir un curso, assets/js/telemetria.js hace POST api/track_open.php y recibe un id. Acumula solo el tiempo con la pestaña visible (visibilitychange) y lo envía cada 30 s con fetch; en beforeunload/pagehide usa navigator.sendBeacon. El servidor suma de forma atómica (segundos_activos = segundos_activos + :seg) con un tope defensivo de 120 s por ping. Los endpoints exigen sesión y cabecera X-CSRF-Token.

6. Gamificación y certificados

Cada sesión leída suma 25 pts; aprobar el módulo añade 50 pts (valores en la tabla parametros). El nivel global se deriva de la suma de puntos: Aprendiz → Operativo → Referente → Líder → Embajador JOSEPAN (tabla niveles). El certificado (certificado.php, PDF generado por lib/PdfBuilder.php sin FPDF/TCPDF) se emite solo con el 100% de sesiones completadas y estado_aprobacion = aprobado.

7. Mapa de archivos

config/        config.php (lo genera el instalador), database.php
sdk_omni/      OmniCoreClient.php — SDK de autenticación OMNI [1001]
includes/      base.php, bootstrap.php, auth.php, functions.php,
               gamification.php, models/ (Empleado, Curso, Parametros,
               Progreso, Telemetria, Asistencia, Certificado)
lib/           PdfBuilder.php (PDF nativo)
data/          cursos.php, documentos.php, seeders.php
templates/     header/footer + layout de manuales
downloads/     PDFs reales (servidos vía descargar.php)
schema.sql     Esquema de la base de datos local
manual-tecnico.html   Este documento (raíz, estático)
public/        DocumentRoot
  install/index.php   Autoinstaller
  index.php login.php logout.php curso.php perfil.php biblioteca.php
  descargar.php certificado.php manual-tecnico.html manual-usuario.php
  assets/  api/  admin/

8. Seguridad