ProyectoGrupal/dolibarr-bff/presentacion/index.html

289 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DoliMiddlewareApi — BFF para Dolibarr</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/theme/black.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/monokai.css">
<style>
.reveal h1,.reveal h2,.reveal h3{text-transform:none;letter-spacing:0}
.reveal section{padding:22px 46px;box-sizing:border-box}
.reveal h1{font-size:1.7em;font-weight:800;margin-bottom:.1em}
.reveal h2{font-size:1.15em;margin-bottom:.5em;color:#fff;font-weight:700}
.reveal p{font-size:.8em;line-height:1.55;margin:.35em 0}
.reveal ul{font-size:.78em;line-height:1.7;margin:.2em 0 .2em 1.3em}
.reveal pre{width:100%;margin:.5em 0;border-radius:5px}
.reveal pre code{font-size:.62em;line-height:1.25}
body,.reveal{background:#111;color:#eee}
.cols{display:flex;gap:16px;align-items:stretch}
.cols>*{flex:1}
.center{text-align:center}
.card{
background:#181818;
border:1px solid #333;
border-radius:6px;
padding:16px 20px;
margin:5px 0;
}
.callout{
background:#1c1a12;
border:1px solid #e2a84b44;
padding:14px 20px;
border-radius:6px;
margin:.7em 0;
}
.callout p{margin:0;font-size:.78em;line-height:1.5}
.badge{
display:inline-block;
background:#181818;
border:1px solid #444;
border-radius:3px;
padding:5px 12px;
font-size:.58em;
margin:2px;
color:#aaa;
font-family:'SF Mono',Consolas,monospace;
}
.flow{display:flex;align-items:center;justify-content:center;gap:16px;margin:1em 0;font-size:.85em}
.flow-box{padding:14px 26px;border-radius:6px;font-weight:700;text-align:center;font-size:.95em}
.flow-arrow{color:#e2a84b;font-size:1.5em;font-weight:800}
.img-full{width:100%;max-height:52vh;object-fit:contain;border-radius:6px;display:block;margin:0 auto}
.ep{display:grid;grid-template-columns:1fr 1fr;gap:6px 20px;margin-top:.4em}
.ep p{margin:0;line-height:1.65}
.sub{font-size:.68em;color:#888;line-height:1.5}
.glow{font-size:.95em;color:#e2a84b;font-weight:700}
.big{font-size:1.5em;font-weight:800}
</style>
</head>
<body>
<div class="reveal"><div class="slides">
<!-- PORTADA -->
<section class="center">
<p style="font-size:.65em;color:#888;margin-bottom:.5em">TFG — Javier Mengual — 2026</p>
<h1 style="color:#fff">DoliMiddlewareApi</h1>
<p style="font-size:.95em;color:#e2a84b;margin:.2em 0 1.8em">Tu frontend merece algo mejor que strings rotos</p>
</section>
<!-- EL PROBLEMA -->
<section>
<h2>El frontend no debería tener que lidiar con esto</h2>
<p>Dolibarr funciona. Pero su API devuelve un desastre que no puedes entregarle a un frontend moderno y decir "aquí tienes, apañatelas".</p>
<div class="cols" style="margin-top:.8em">
<div class="card" style="border-top:3px solid #f87171">
<p style="font-size:.8em;color:#f87171;font-weight:700;margin:0 0 8px">Lo que te da Dolibarr</p>
<div class="sub" style="line-height:1.85">
IDs como <code>"string"</code><br>
Fechas en timestamp Unix<br>
Estados que son números: <code>"1"</code><br>
snake_case inconsistente<br>
Credenciales volando por ahí
</div>
</div>
<div class="card" style="border-top:3px solid #4ade80">
<p style="font-size:.8em;color:#4ade80;font-weight:700;margin:0 0 8px">Lo que tu frontend merece</p>
<div class="sub" style="line-height:1.85">
IDs como <code>int</code><br>
Fechas ISO 8601<br>
Estados legibles: <code>"unpaid"</code><br>
camelCase<br>
Un JWT y ya está
</div>
</div>
</div>
</section>
<!-- BFF -->
<section>
<h2>Un escudo entre tu app y el caos</h2>
<p>El patrón BFF —Backend for Frontend— no es un proxy. Es una capa que traduce, protege y enriquece. Tu frontend habla con él, y él se ocupa de lo demás.</p>
<div class="flow" style="margin:1.3em 0">
<div class="flow-box" style="background:#1e1510;color:#fb923c;border:2px solid #fb923c88">Dolibarr</div>
<span class="flow-arrow"></span>
<div class="flow-box" style="background:#1a1710;color:#e2a84b;border:2px solid #e2a84b88">BFF</div>
<span class="flow-arrow"></span>
<div class="flow-box" style="background:#0f1a11;color:#4ade80;border:2px solid #4ade8088">Tu frontend</div>
</div>
<ul>
<li>El frontend nunca habla con Dolibarr directamente</li>
<li>Si el ERP cambia algo, tocas un sitio, no cincuenta</li>
<li>Y puedes meterle cosas que Dolibarr jamás va a tener</li>
</ul>
</section>
<!-- ARQUITECTURA -->
<section class="center">
<h2>Así funciona</h2>
<img src="arquitectura.png" class="img-full" alt="Arquitectura" style="max-height:54vh">
</section>
<!-- .NET 10 -->
<section data-background-image="dotnetall.jpg" data-background-size="cover" data-background-position="center" data-background-opacity="0.12">
<h2>¿Por qué .NET 10?</h2>
<p>Si voy a poner una API en producción, quiero dormir tranquilo tres años.</p>
<img src="dotnetall.jpg" style="width:100%;max-height:32vh;object-fit:cover;object-position:center;border-radius:6px;display:block;margin-bottom:10px">
<div class="cols" style="gap:10px">
<div class="card" style="border-top:3px solid #e2a84b">
<p style="font-size:.76em;color:#e2a84b;font-weight:700;margin:0 0 3px">LTS hasta 2028</p>
<p class="sub">Tres años de soporte. Me da igual lo que pase meantime.</p>
</div>
<div class="card" style="border-top:3px solid #e2a84b">
<p style="font-size:.76em;color:#e2a84b;font-weight:700;margin:0 0 3px">Rendimiento</p>
<p class="sub">Lo suficientemente rápido para que la latencia no sea un problema.</p>
</div>
<div class="card" style="border-top:3px solid #e2a84b">
<p style="font-size:.76em;color:#e2a84b;font-weight:700;margin:0 0 3px">Todo incluido</p>
<p class="sub">JWT, rate limiting, health checks, OpenAPI. Sin buscar librerías raras.</p>
</div>
</div>
</section>
<!-- ENDPOINTS -->
<section>
<h2>Lo que cubre</h2>
<div class="ep">
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Auth</span> <span class="sub">— login, JWT</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Facturas</span> <span class="sub">— CRUD, líneas, pagos, estado</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Clientes</span> <span class="sub">— con contactos incluidos</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Proveedor</span> <span class="sub">— facturas de proveedor</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Bancos</span> <span class="sub">— cuentas y movimientos</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Documentos</span> <span class="sub">— PDFs de facturas</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Setup</span> <span class="sub">— diccionarios, país, compañía</span></p>
<p><span style="color:#e2a84b;font-weight:600;font-size:.76em">Notificaciones</span> <span class="sub">— webhooks</span></p>
</div>
<div class="callout" style="margin-top:1em">
<p>Sí, gran parte es 1:1 con Dolibarr. Pero el BFF añade lo que el ERP no tiene: <strong>tipos correctos</strong>, <strong>estados legibles</strong>, enriquecimiento con nombres de cliente y notificaciones.</p>
</div>
</section>
<!-- TRANSFORMACIÓN -->
<section>
<h2>De francés y strings... a inglés y tipos</h2>
<div class="cols" style="align-items:flex-start;margin-top:.2em">
<div>
<p class="red" style="font-size:.76em;font-weight:700;margin-bottom:5px">Dolibarr</p>
<pre><code class="json" style="font-size:.62em">{
"statut": "1",
"total_ttc": "150.50",
"date": "1715673600",
"socid": "3"
}</code></pre>
</div>
<div>
<p class="green" style="font-size:.76em;font-weight:700;margin-bottom:5px">BFF</p>
<pre><code class="json" style="font-size:.62em">{
"status": "unpaid",
"total": 150.50,
"date": "2024-05-14",
"clientId": 3
}</code></pre>
</div>
</div>
<p style="font-size:.78em;margin-top:.8em;color:#ccc">Mismo dato. Otro mundo.</p>
</section>
<!-- SWAGGER -->
<section class="center">
<h2>Documentación automática</h2>
<img src="swagger.png" class="img-full" alt="Swagger UI" style="max-height:50vh">
<p class="sub" style="margin-top:.5em">OpenAPI 3.1 generado al arrancar. Cada endpoint documentado.</p>
</section>
<!-- AUTENTICACIÓN -->
<section>
<h2>La contraseña nunca sale del servidor</h2>
<p>El frontend maneja un JWT. La API key de Dolibarr queda atrapada dentro del BFF. Si alguien intercepta el token del usuario, caduca en 8 horas y no tiene acceso al ERP.</p>
<div class="cols" style="margin-top:.8em">
<div class="card" style="border-top:3px solid #e2a84b">
<p style="font-size:.78em;color:#e2a84b;font-weight:700;margin:0 0 4px">1 — Login</p>
<p class="sub">El usuario se autentica. El BFF recibe la API key de Dolibarr y la guarda en memoria.</p>
</div>
<div class="card" style="border-top:3px solid #4ade80">
<p style="font-size:.78em;color:#4ade80;font-weight:700;margin:0 0 4px">2 — JWT</p>
<p class="sub">El BFF genera un JWT para el navegador. La API key nunca sale de ahí.</p>
</div>
<div class="card" style="border-top:3px solid #fb923c">
<p style="font-size:.78em;color:#fb923c;font-weight:700;margin:0 0 4px">3 — Cada petición</p>
<p class="sub">El JWT lleva un sessionId. Con ese sessionId se busca la API key en caché y se inyecta al vuelo.</p>
</div>
</div>
<div class="callout" style="margin-top:.7em">
<p>Cada usuario tiene su propia API key aislada. Si se cachease en el HttpClient, todos compartirían la misma.</p>
</div>
</section>
<!-- NOTIFICACIONES -->
<section>
<h2>Lo que un wrapper puede hacer que el ERP no</h2>
<p>Al poner una capa por delante, puedes añadirle cosas que Dolibarr nunca va a tener. El ejemplo más claro: cuando una factura cambia de estado, el equipo se entera al momento. Sin abrir el sistema, sin mirar nada.</p>
<div class="cols" style="margin-top:.7em">
<div class="card" style="border-top:3px solid #c084fc">
<p style="font-size:.78em;color:#c084fc;font-weight:700;margin:0 0 4px">Teams, Slack, lo que sea</p>
<p class="sub">Configuras una URL y avisa donde quieras. Hoy es Teams, mañana puede ser Telegram, email, lo que haga falta.</p>
</div>
<div class="card" style="border-top:3px solid #4ade80">
<p style="font-size:.78em;color:#4ade80;font-weight:700;margin:0 0 4px">La interfaz ya está</p>
<p class="sub">Añadir un canal nuevo es implementar una interfaz. El resto del código ni se toca. Así se escala un wrapper de verdad.</p>
</div>
</div>
</section>
<!-- DESPLIEGUE -->
<section>
<h2>Un comando y funciona</h2>
<p class="sub" style="margin-bottom:.3em">docker compose up</p>
<pre><code class="yaml" style="font-size:.64em">services:
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: dolibarr
volumes: [mysql_data:/var/lib/mysql]
dolibarr:
image: dolibarr/dolibarr:latest
depends_on: [mysql]
ports: ["80:80"]
bff:
build: ./DoliMiddlewareApi
depends_on: [dolibarr]
ports: ["5001:8080"]</code></pre>
<p style="font-size:.78em;margin-top:.7em;color:#bbb">MySQL, Dolibarr, el BFF. Tres contenedores, un comando.</p>
</section>
<!-- CIERRE -->
<section class="center">
<h1 style="font-size:2.2em">Preguntas</h1>
</section>
</div></div>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.js"></script>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/highlight.js"></script>
<script>
Reveal.initialize({
hash: true,
slideNumber: 'c/t',
transition: 'fade',
transitionSpeed: 'fast',
plugins: [RevealHighlight],
width: 1100,
height: 680,
margin: 0.04,
center: false,
});
</script>
</body>
</html>