# Clínica — Análisis de paridad vs MQN y pendientes

> Estado tras cerrar los 4 gaps de paridad (Laboratorio/Recepcionista/Ingresos/Reprogramar).
> Entorno verificado: LOCAL, tenant de prueba `mqn_efp` en `jena.enterfarmaplus.test`. NO deployado a prod.
> Última pasada de análisis con Playwright: 2026-06-30.

## ✅ Lo que funciona (verificado en vivo)

- Las 8 pantallas de clínica cargan: Panel, Citas, Laboratorio, Pacientes, Reportes, Especialidades, Procedimientos, Config.
- **Citas**: lista/Día/Calendario, nueva cita (wizard), Vitales, Pagar→POS, Sin cobro, Ticket, FUA, **Reprogramar** (modal calendario + slots 12h).
- **Atención (doctor)**: tabs Atención Médica (EVA, vitales con IMC auto, CIE) / Ayuda Dx (adjuntos) / Procedimientos y Tratamientos / **Ventas** (carrito→POS) / Historial (Citas + Laboratorio con "Ver detalle"). Header sticky, badges, panel resumen.
- **Laboratorio**: "Solicitar examen" (paciente/doctor/prioridad/fecha/notas/búsqueda+seleccionados) y "Resultados" (#/Examen/Resultado/Acciones); marca la orden Atendido al completar.
- **Reportes**: Resumen + **Ingresos** (S/ por rango, por doctor/especialidad/día).
- **Configuración**: Personal (CRUD doctor/recepcionista), Signos vitales, Servicio de cita.
- **Recepcionista** (rol): aterriza en su dashboard, menú reducido (Dashboard/Citas/Pacientes), bloqueado de atención/settings/reportes/laboratorio, permitido en citas/pacientes; botón "Atender" oculto.

## ✅ Resueltos desde la primera pasada (ver sección de perfiles + memoria del proyecto)

1. ~~El recepcionista NO puede cobrar~~ → **RESUELTO**: RBAC centralizado da `pos`+`charge` al rol 2; recep cobra
   consulta y productos (verificado e2e). Ya no depende del admin.
2. ~~Recepcionista ve FUA/Cotizaciones~~ → **RESUELTO**: FUA es intencional para recepción (`can.fua=true`);
   el botón **"Cotizaciones" se eliminó** para todos (decisión: carrito).
3. ~~Roles faltantes vs MQN~~ → **RESUELTO**: los **5 perfiles** (Doctor/Recep/Admin/Farmacia/Laboratorio) están
   implementados vía `User::clinicProfile()`. (Prod aún no tiene usuario Laboratorio → asignar uno al cutover.)

## 🟡 Pendientes menores (no bloqueantes)

- **Error de consola del layout** (`configurations/visual/get_menu`, `/persons/tables` en **https**): gotcha del 301
  cacheado; son calls del *layout*, no de clínica. Benigno en local; resuelve en prod (force_https ON).
- **Login**: el botón "Iniciar Sesión" no submitea por click simple (handler JS); en pruebas Playwright hubo que
  forzar el submit nativo. Confirmar que el flujo real de usuario funciona.

## 👤 Cómo funciona cada perfil (estado actual — 2026-06-30)

**NO hay tabla de roles.** El "perfil" es el entero **`users.clinic_role_id`**. Todo el comportamiento
sale de un mapa central **`User::clinicProfile(roleId)`** → `{landing, modules, prefixes, pos, clinic_scoped, can}`,
consumido por `LoginController@authenticated` (landing), `RedirectModule` + `ClinicRoleGate` (rutas),
`sidebar.blade.php` (menú) y `Configuration::getCollectionData` (expone `clinic_role`/`clinic_can` al JS).
**Defensa en 3 capas**: menú oculto + ruta bloqueada + backend `abort(403)` vía `User::clinicCan(acción)`.

| Perfil (rol) | Aterriza en | Atiende | Crea cita | Cobra | FUA | POS | En el clon (mqn_efp) |
|---|---|:--:|:--:|:--:|:--:|:--:|---|
| **Doctor** (1) | `/clinica/dashboard-doctor` | ✅ | ❌ | ❌ | ❌ | ❌ | quezada@gmail.com, hector@gmail.com |
| **Recepcionista** (2) | `/clinica/dashboard-recepcionist` | ❌ | ✅ | ✅ | ✅ | ✅ | cita@gmail.com |
| **Administrador** (3) | `/dashboard` | ✅ | ✅ | ✅ | ✅ | ✅ | mqn@gmail.com |
| **Farmacia** (4) | `/pos` | ❌ | ❌ | POS normal | ❌ | ✅ | erav1598@gmail.com |
| **Laboratorio** (5) | `/clinica/laboratory` | ❌ | ❌ | ❌ | ❌ | ❌ | yas@gmail.com |

**👨‍⚕️ Doctor** — Panel doctor, Mis Citas, Citas, Consultas, Pacientes, Especialidades, Procedimientos.
Atiende (ficha: vitales+IMC, CIE-10, procedimientos, EVA), **arma el carrito "Ventas"**, solicita laboratorio,
ve historial, reprograma, finaliza (→AT). **No cobra** (ni consulta ni productos → 403, sin botones); arma el
carrito y lo cobra recepción.

**🧑‍💼 Recepcionista** — *centro del cobro*. Panel recepción, Citas, Pacientes, POS. Crea/agenda citas, reprograma,
toma vitales, **cobra la consulta** ("Pagar"→POS) y **los productos** del carrito ("Cobrar prod."→POS), "Sin cobro"
(gratuita), Ticket, **FUA**. No atiende (ficha), no Config/Reportes/Lab.

**🛡️ Administrador** — acceso pleno (conserva todos sus módulos). Atiende, crea, cobra, FUA, Config, Reportes, Lab, POS.

**💊 Farmacia** — vendedor POS normal de EFP (POS/Documentos/Inventario/Ítems/Personas). **No entra a `/clinica`**.

**🔬 Laboratorio** — solo el módulo Laboratorio: ve órdenes y **registra resultados**. Nada más.

**Cobro (estado actual)**: consulta al inicio + productos después = dos comprobantes (la consulta se cobra antes de
que existan los productos; fusionar la doble-cobraría). Ambos **vinculan de vuelta a la cita** (`linkSale` /
`linkProductsSale`) y **no se doble-cobran** (`products_charged` oculta el botón → "Prod. cobrados"). El botón
**"Cotizaciones" fue eliminado** (decisión: carrito, no módulo Quotation).

## Pendientes futuros (no bloqueantes)

- **Procedimientos sin precio**: `procedures`/`medical_consultation_procedures` no tienen `item_id`/monto → no se
  cobran. Para cobrarlos habría que mapearlos a ítems de catálogo. (En MQN sí iban en la cotización con precio.)
- **Cutover a prod**: correr la migración de columnas de cobro (idempotente) en el tenant real + limpieza de
  duplicados `module_user`/`module_level_user` (ver memoria del proyecto).
- **Error de consola del layout** (`get_menu`/`persons/tables` en https): gotcha del 301 cacheado, benigno; resuelve
  en prod con force_https. Ver si falta cache-buster en el layout.
