# 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** → deje la migración en `migrations/`, idempotente. - **Endpoint nuevo** → verifique permisos ahí adentro, no confíes en la vista. - **Tocar el turnero** → es lo que más gente usa a diario; pruebe con un turno real. - **Tocar formularios firmados** → tienen valor legal. Un render roto es un documento inválido.