# Reporte de refactorización — Sistema de Reportes "La Casa de los Almuerzos"

**Origen:** `C:\Users\DEV IA\Downloads\sistema-reportes-los-almuerzos\sistema-reportes-los-almuerzos\app`
(PHP 7.2, MVC casero tipo TraversyMVC, Medoo, tema AdminBSB/Bootstrap 3, jQuery + Vue 2 + Buefy + DataTables)

**Destino:** `C:\laragon\www\almuerzos-nest`
(NestJS 10 + TypeScript 5, Handlebars, Tailwind CSS 3, mysql2, base `lacasadelosalmue_almuerzos`)

---

## 1. Arquitectura: antes y después

**Antes (2 aplicaciones PHP):**
- `app/app` — frontend MVC que llamaba por HTTP (curl) a…
- `app/rest-api-local` — API REST con otro MVC idéntico y la lógica real de BD.
- Un login requería 4+ peticiones HTTP internas encadenadas (validaUser →
  validaPass → validaLoginAdmin → registerLoginSuccess) más una llamada
  externa a ipapi.co en cada render del login.

**Después (1 aplicación NestJS):**
- Módulos de dominio con inyección de dependencias: `auth`, `reportes`,
  `sucursales`, `clientes`, `catalogo`, `eventos`, `pagos`, `usuarios`,
  `pages`, `database`.
- El login es 1 sola petición; sin dependencias externas.
- Vistas server-side (Handlebars) + JS nativo con `fetch` por página.

## 2. Reemplazo de librerías y dependencias

| Original (PHP/JS) | Reemplazo (Node/TS) | Nota |
| --- | --- | --- |
| Medoo (query builder) | **mysql2/promise** (pool + placeholders) | Elimina inyección SQL |
| PDO comentado / SQL interpolado | Consultas parametrizadas | — |
| PhpSpreadsheet | **exceljs** | Excel generado 100% en servidor |
| Html2Pdf + FPDF + TCPDF (3 librerías) | **pdfkit** (una sola) | Corte del día, ventas, concentrado |
| MD5 manual | **bcryptjs** con compatibilidad MD5 | Upgrade transparente al iniciar sesión |
| `$_SESSION` + cookies manuales | **express-session** + guard global de NestJS | Antes casi ningún endpoint validaba sesión |
| geoPlugin / ipapi.co | Eliminado (solo se guarda la IP) | Quita dependencia externa en el login |
| Bootstrap 3 + AdminBSB + SCSS/CSS del tema (83 SCSS / 210 CSS) | **Tailwind CSS 3** con paleta corporativa propia | Un solo CSS compilado (~30 KB) |
| jQuery + Vue 2 + axios + Buefy + DataTables + sweetalert + fullcalendar + Morris + Chart.js 2 (cargado 2 veces) | JS nativo (fetch, dialog, tabla ordenable/buscable propia) + **Chart.js 4** solo en Sucursales | De ~20 bundles a 2 archivos por página |
| Mike42 Escpos (impresión térmica) | **No migrado** (ver pendientes) | Depende de hardware local |

## 3. Bugs del original corregidos en la migración

1. **Inyección SQL generalizada** — `LoginModel::validaLoginAdmin`,
   `FacturasPModel`, `EventoModel`, `PagoClientesModel`, reportes: valores de
   `$_POST`/URL interpolados directo en SQL. → Todas las consultas usan `?`.
2. **Login sin contraseña** — la condición `WHERE usuario=... AND permiso='root'
   OR permiso='admin' AND password=...` (sin paréntesis) permitía entrar a
   cualquier usuario con una fila 'root' en permisos. → Verificación real de
   hash por usuario.
3. **Contraseñas fallidas guardadas en claro** en la tabla `intentos`. → Ya no
   se guarda la contraseña.
4. **Totales invertidos en monedero** — `getDataclienteM` sumaba efectivo en el
   total de tarjeta y viceversa. → Corregido en `ClientesService.movimientosMonedero`.
5. **Cobranza/propinas con fecha equivocada** — el corte de días pasados
   mostraba la cobranza y propinas de HOY (`CURDATE()`). → Se usa la fecha del
   reporte.
6. **Año ignorado en gráficas de sucursal** — `getVentasSucursal` usaba
   `date('Y-')` fijo. → El año seleccionado se respeta.
7. **División entre cero** en el promedio por comensal de `reportVentas`. → Protegida.
8. **Semántica invertida de parámetros** — `reportVentas` (tipo 2=rango,
   1=mes) vs `reportVentasConcentrado` (1=rango, 2=mes). → API uniforme:
   `?inicio&fin` o `?mes`.
9. **Sin transacciones** en alta de eventos, clientes con monedero/CPP,
   platillos con sucursales y cobranza CPC (datos a medias si algo fallaba).
   → `DatabaseService.transaction()` en todas esas operaciones.
10. **id_empleado=1 hardcodeado** al crear eventos. → Se toma de la sesión.
11. **editPlati con valores fijos** (siempre actualizaba el platillo 270). →
    Edición real parametrizada.
12. **Navbar con id equivocado** — unas pantallas armaban el menú con
    `id_usuario` y otras con `id_permiso` contra la misma columna
    `modulosusuario.id_usuarios`. → Siempre `id_usuario`.
13. **Endpoints sin autenticación** — solo 2 de ~10 controladores de la API
    validaban sesión. → Guard global; todo requiere sesión salvo `/login`.

## 4. Rendimiento (N+1 eliminados)

| Reporte | Antes | Ahora |
| --- | --- | --- |
| Dashboard sucursal (mes) | ~240 queries (4 tipos × 30 días × count+sum) | 4 queries con `GROUP BY DAY()` |
| Ventas por periodo | 1 + (5-8 queries × cada venta) — miles en un mes | 5 subconsultas agregadas en 1 query |
| Concentrado | Lo anterior × cada sucursal | 6 queries totales |
| RDV / corte del día | 8-10 queries por pago | 3 queries (LEFT JOIN agregados) |
| Ranking platillos | 2 queries × cada platillo (~300) | 1 query con `CASE` |
| Movimientos monedero | 2 queries por movimiento | 1 query |

Verificado contra la BD real: los totales coinciden (p. ej. TLAXCALA
2026-08-17: 8 ventas, $4,426.00 = suma exacta del desglose).

## 5. Interfaz (SCSS/Bootstrap → Tailwind)

- Layout corporativo: sidebar oscuro (`ink-950`) con acento naranja de marca
  (`brand-600 #c94e15`), header fijo con usuario/sucursal/permiso, responsive
  (menú colapsable en móvil).
- Componentes reutilizables definidos como `@layer components`: `btn-*`,
  `card`, `input`, `label`, `table-base`, `badge`, `tab-btn`, `nav-link`.
- Tablas con búsqueda, ordenamiento por columna y pie de totales en JS nativo
  (reemplaza DataTables/Buefy); modales con `<dialog>` nativo; toasts propios
  (reemplaza sweetalert).
- Gráficas con Chart.js 4 (barras apiladas por día + dona de formas de pago).

## 6. Pruebas realizadas (BD real `lacasadelosalmue_almuerzos`)

- Login correcto con usuario real (`desarrollo`) → sesión, navbar, redirect.
- Login incorrecto → distingue usuario/contraseña, cuenta intentos, registra
  en `intentos`; 3 fallos → bloqueo 180 s.
- Rutas protegidas: páginas → 302 a `/login`; API → 401 JSON.
- Reporte Ventas (sucursal 2, 2026-08-17): 8 ventas, totales exactos.
- Concentrado: 4 sucursales con efectivo/tarjeta/comensales correctos.
- RDV sucursal 3: desglose por pago con bauches y facturas.
- Ranking de platillos y paquetes con datos reales.
- Excel (`ventas.xlsx`, 200 OK, MIME correcto) y PDF (`corte.pdf`, 200 OK).
- Dashboard de sucursal: KPIs y gráficas del mes con agregados por día.
- Módulos clientes (55+ monederos), catálogo, facturas y usuarios responden.

## 7. Pendientes / decisiones para el equipo

- **Impresión térmica ESC/POS** (tickets): no migrada; en Node existe
  `node-thermal-printer` o `escpos`. Requiere probar con las impresoras
  físicas de las sucursales (tabla `impresoras` sigue disponible).
- **POS de mesas/ventas (Home.php, 1,104 líneas + homeJS 1,670 líneas)**: el
  sistema de punto de venta en piso (mesas, colores, comandas) es una app
  aparte del panel de reportes; se migró el panel administrativo/reportes.
  El POS puede migrarse como módulo `ventas` siguiendo el mismo patrón.
- **Encuestas** (`Encuestas.php`, tablas pregunta/respuestas): sin migrar.
- **Upgrade MD5→bcrypt**: al iniciar sesión en el sistema nuevo, la contraseña
  del usuario se rehashea a bcrypt; ese usuario ya no podrá entrar al sistema
  PHP viejo. Si van a convivir ambos sistemas, desactivar el bloque de upgrade
  en `src/auth/auth.service.ts`.
- El usuario de BD en `.env` es `root` local; en producción usar el usuario
  dedicado con permisos mínimos.
- Código muerto detectado en el original y NO migrado a propósito:
  controladores de tutorial (`Posts`, `Pages`, `Users` con tabla `users`
  inexistente en el flujo), `pruebas.php`, `reportesJS1`, vistas `users/login`
  y `users/register` rotas (apuntan a `views/inc/` inexistente), doble carga
  de Chart.js y fullcalendar.
