21 documentos en cuatro secciones, escritos sobre el comportamiento real del sistema —incluidos los casos que costaron diagnosticar esta semana. Manual de usuario (visible para todos): primeros pasos, recepción, toma de muestras, portal del enfermero y administración. Orientado a tareas concretas, no a describir pantallas. Documentación técnica: índice de módulos, turnero, formularios y firma digital, WhatsApp y bot, domicilios, webhook (migrado de WEBHOOK_ENDPOINTS.md) e inventario de endpoints. Arquitectura: visión general, enrutamiento y registro de módulos, roles y permisos, modelo de datos, integración con WhatsApp, y decisiones tomadas con su deuda técnica asociada. Operación: runbook de incidentes ordenado por síntoma, configuraciones críticas —incluido qué vive en Meta y no en la base— y despliegue. Se documentan explícitamente las trampas conocidas: role/role_id que hay que mantener sincronizados, las columnas can_* que el control de acceso no lee, las URL de plantilla que no se cambian desde el código, y las columnas históricas que quedaron en NULL sin forma de recuperarlas. README_DOCS.md apunta al módulo y explica cómo agregar páginas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
105 lines
4.6 KiB
Markdown
105 lines
4.6 KiB
Markdown
# Decisiones y deuda técnica
|
|
|
|
Por qué el sistema es como es, y qué cosas conviene saber antes de tocarlo.
|
|
|
|
## Decisiones tomadas a propósito
|
|
|
|
### Migración gradual, sin corte
|
|
|
|
Conviven el sistema original (archivos en la raíz) y el nuevo (módulos). No hubo una reescritura de golpe.
|
|
|
|
**Por qué:** el laboratorio opera todos los días. Una reescritura completa implicaba congelar el desarrollo o mantener dos sistemas en paralelo.
|
|
|
|
**Costo:** hay que saber en cuál de los dos está el código de cada pantalla. Los `lab_*` suelen estar en la raíz; el turnero está en el módulo.
|
|
|
|
### Sin framework de frontend
|
|
|
|
Las vistas son PHP que emiten HTML, con JavaScript embebido en la misma vista.
|
|
|
|
**Por qué:** despliegue por `git pull`, sin build ni compilación. Un archivo se edita y ya está en producción.
|
|
|
|
**Costo:** hay código repetido entre vistas, y las vistas grandes (el turnero) pasan de las 2.000 líneas.
|
|
|
|
### Esquemas de formulario en JSON
|
|
|
|
Los formularios se definen en JSON dentro de `lab_formularios.esquema`, no en tablas normalizadas.
|
|
|
|
**Por qué:** las fichas clínicas cambian seguido y cada una tiene campos distintos. Normalizarlas obligaba a migrar el esquema con cada formulario nuevo.
|
|
|
|
**Costo:** no se puede consultar por SQL «todos los pacientes con fiebre». Las respuestas viven dentro de un JSON.
|
|
|
|
### La identidad de quien firma se resuelve en el servidor
|
|
|
|
Nunca se acepta del navegador quién firmó algo.
|
|
|
|
**Por qué:** es un dato con valor legal. Un cliente puede mentir; la sesión no.
|
|
|
|
### El turno original nunca se modifica
|
|
|
|
Cuando una muestra pendiente se completa en una visita posterior, el turno original **queda como estaba**. Solo se registra el vínculo.
|
|
|
|
**Por qué:** el turno cerrado es un registro histórico. Alterarlo retroactivamente falsea los tiempos de atención y la facturación de aquel día.
|
|
|
|
### Inventarios generados, no escritos
|
|
|
|
Las tablas de módulos, endpoints, tablas y roles de esta documentación se leen del código y la base en cada carga.
|
|
|
|
**Por qué:** una lista escrita a mano envejece sin que nadie se entere. Una generada no puede mentir.
|
|
|
|
## Deuda técnica conocida
|
|
|
|
### Columnas `can_*` que no hacen nada
|
|
|
|
`role_modules` tiene `can_view`, `can_create`, `can_edit`, `can_delete`, `can_export` — y **el control de acceso no las lee**. Solo usa `permission` (`read`/`write`).
|
|
|
|
**Riesgo:** poner `can_edit = 0` da falsa sensación de haber restringido algo. Ya causó confusión.
|
|
|
|
**Arreglo:** o se usan de verdad, o se eliminan. Mientras tanto, conviene mantenerlas coherentes con `permission`.
|
|
|
|
### `role` y `role_id` duplicados
|
|
|
|
Un usuario tiene el rol en dos columnas. La interfaz lee una, los permisos salen de la otra.
|
|
|
|
**Riesgo:** cambiar solo `role` deja al usuario con permisos que no corresponden.
|
|
|
|
**Arreglo:** derivar `role` de `role_id` en lugar de almacenarlo.
|
|
|
|
### Dos vías para el mismo formulario
|
|
|
|
`turnero_consentimientos` y `lab_form_envios` guardan lo mismo con estructuras distintas y tokens de formato distinto. `ver_formulario_enviado.php` tiene que manejar ambos, y `form_cliente.php` existe solo para redirigir entre ellos.
|
|
|
|
**Por qué sigue así:** unificarlas obliga a cambiar la plantilla aprobada en Meta y migrar los registros históricos.
|
|
|
|
### Convenciones de nombre mezcladas
|
|
|
|
Conviven `creado_at` y `created_at`, `creado_por` y `enviado_por`, español e inglés. Depende de la época de cada tabla.
|
|
|
|
### Vistas muy grandes
|
|
|
|
`ver_formulario_enviado.php` supera las 3.000 líneas y mezcla render, lógica de tomas prolongadas y JavaScript. Es el archivo más delicado de tocar del sistema.
|
|
|
|
### Datos históricos incompletos
|
|
|
|
Algunas columnas se agregaron después y las filas viejas quedaron en `NULL`, sin forma de recuperarlas:
|
|
|
|
| Columna | Desde | Antes |
|
|
|---|---|---|
|
|
| `turnero_consentimientos.creado_por` | 3 ago 2026 | `NULL` |
|
|
| Identidad por toma en F-LAB-28 | 3 ago 2026 | No se guardaba |
|
|
| `admin_users.cedula` | 3 ago 2026 | Solo enfermeros la tenían |
|
|
|
|
No hay traza de auditoría que permita reconstruirlos.
|
|
|
|
### El dominio se deduce de cada petición
|
|
|
|
`APP_URL` sale del `HTTP_HOST`. Si alguien entra por una IP o un dominio alterno, los enlaces que se generen llevarán esa dirección — y quedan guardados así en el WhatsApp del paciente.
|
|
|
|
**Arreglo:** fijar `APP_URL` explícitamente.
|
|
|
|
## Al hacer cambios
|
|
|
|
- **Cambio de esquema** → dejá la migración en `migrations/`, idempotente.
|
|
- **Endpoint nuevo** → verificá permisos ahí adentro, no confíes en la vista.
|
|
- **Tocar el turnero** → es lo que más gente usa a diario; probá con un turno real.
|
|
- **Tocar formularios firmados** → tienen valor legal. Un render roto es un documento inválido.
|