bloque 5: tablero de direccion (pagina /direccion con permiso propio: resumen con comparativos, cohortes de retencion, valor por cliente, clientes en riesgo, ocupacion por medico/sucursal/recurso, ingresos por servicio y sucursal, membresias y paquetes, pasivo de lealtad, metas por sucursal con proyeccion y exportacion) con cifras cruzadas contra los reportes existentes y consultas agrupadas (menos de 2 s)

This commit is contained in:
2026-10-12 03:34:00 +00:00
parent a6d6df4ebd
commit 6139df6327
15 changed files with 2256 additions and 3 deletions

View File

@@ -615,6 +615,80 @@ todo respeta el **modo prueba** y queda en la bitácora con su campaña o encues
de origen.
## 14 quater. Tablero de dirección (indicadores del dueño)
Pantalla **Dirección** (menú, ruta `/direccion`) con los indicadores del
negocio en una sola vista. Es de **solo lectura** y **no depende de ningún
interruptor**: se ve quien tenga el permiso.
- **Permisos**: `direccion.ver` — por defecto **admin, gerencia y marketing**.
El rol **médico no lo ve** (ni la sección de menú ni la API: el endpoint
responde 403). Se administra en **Configuración → Roles → Permisos**.
- **Filtros**: rango de fechas con atajos (hoy, esta semana, este mes, mes
pasado, este año, personalizado), **sucursal** y un **comparativo**
(periodo anterior equivalente, mismo periodo del año pasado o ninguno).
Todo el tablero se **exporta a Excel**.
- **Secciones**:
1. **Resumen del periodo**: ingresos cobrados, ventas, ticket promedio,
visitas atendidas, pacientes nuevos y recurrentes, tasa de no presentados
y de cancelación, con la variación contra el comparativo elegido.
2. **Clientes**: pacientes activos, nuevos por mes, **retención por
cohortes** (de quienes vinieron por primera vez en un mes, cuántos
volvieron en 1, 3, 6 y 12 meses), **frecuencia promedio** de visita,
**valor por cliente** (ingreso histórico promedio y mediana) y **clientes
en riesgo** (los que solían venir con regularidad y llevan más de X días
sin aparecer), con un botón directo para **armar una campaña** con ellos.
3. **Ocupación y agenda**: horas vendidas contra disponibles por médico, por
sucursal y por recurso, porcentaje de ocupación, franjas horarias más y
menos ocupadas y no-show por médico.
4. **Ingresos por concepto**: por servicio, categoría, sucursal y método de
pago, **propinas**, membresías (activas, ingreso recurrente mensual
estimado, renovaciones y cancelaciones), paquetes (vendidos y sesiones
pendientes de usar, que son un compromiso del negocio) y el **pasivo de
lealtad** en pesos.
5. **Metas y proyección**: metas por sucursal y por empleado, avance del mes
y **proyección de cierre** con el ritmo actual.
- **Indicadores no disponibles**: los que no se pueden calcular con los datos
del sistema (p. ej. entregas de productos o resultados de WhatsApp) se
muestran como **no disponible** con su motivo; nunca se estiman.
- **Criterios de cálculo** (coinciden con los reportes existentes):
- *Ingresos cobrados*: pagos con estado **completado** del periodo (igual que
**Reportes → Cortes/Caja** y el *Concentrado*).
- *Ventas*: ventas **no canceladas** del periodo (las devoluciones se
reportan aparte); *ventas cobradas* = suma de lo pagado en esas ventas.
- *Pacientes nuevos*: citas del periodo cuya fecha es la **primera cita
histórica** no cancelada del paciente (igual que **Reportes → KPIs**).
- *No-show y ocupación por médico*: mismas reglas que **KPIs**; *franjas
horarias* igual que **Horas agenda**; *recursos* igual que **Recursos**.
- *Pasivo de lealtad* y *propinas*: mismos criterios que sus reportes.
### 14 quater.1 Bloque de ajustes `tablero`
**Configuración → Dirección**. Guarda los parámetros del tablero; con los
valores por defecto el tablero funciona igual y solo deja de mostrar el avance
de metas. Claves (defaults):
- `metas_sucursal`: lista `[{sucursal: <código>, meta_mensual: <monto>}]`
(default: **vacía**). Es la **meta mensual de venta de cada sucursal**.
- `meta_mensual_global`: meta de venta mensual de toda la clínica; **0** usa la
suma de las metas por sucursal (default: **0**).
- `dias_inactividad`: días sin venir para considerar a un cliente **en riesgo**
(default: **90**).
- `visitas_minimas_riesgo`: visitas históricas mínimas para entrar a *en
riesgo*; un paciente de una sola visita no se marca (default: **3**).
- `comparativo_default`: `anterior` | `anio` | `ninguno` (default:
**anterior**).
La clave se llama **`tablero`** y no `direccion` para no chocar con el campo
homónimo de ajustes que guarda la **dirección postal** de la clínica. Se guarda
dentro del JSON de `skeen.clinic.settings` (`GET`/`PUT
/skeen/frontend/v1/clinic-settings`), con **merge anidado**: un PUT parcial no
borra el resto.
El endpoint de datos es **`GET /skeen/frontend/v1/direccion`** (parámetros
`start`, `end`, `sucursal`, `comparar`), de solo lectura y con las cifras ya
agrupadas en el servidor.
## 15. Tickets y documentos
**Configuración → Tickets**: ancho (58/80 mm), fuente, logo y qué secciones se