40 KiB
Configuración de una clínica / spa nuevo
Guía de puesta en marcha de una instancia del sistema (producto multi-giro). Todo lo que sigue se configura desde la interfaz, sin tocar código.
Para crear la instancia (base de datos, puerto, servicio, dominio, secretos y
primer usuario admin) usa el script de provisioning: ver
nueva-instancia.md. Esta guía empieza cuando la
instancia ya está levantada y con sesión de administrador.
La configuración vive en Configuración (panel con pestañas). El administrador
ve todas; gerencia ve un subconjunto (no ve la pestaña Clínica con los datos de
la instancia, ni Catálogos, API o Auditoría; en Licencia solo consulta el
estado). Salvo donde se diga lo contrario, cada bloque tiene un interruptor de
encendido y apagado por defecto: mientras no se active, la instancia se
comporta como una instalación base.
1. Identidad de la clínica
Configuración → Clínica (sección de identidad)
| Qué | Efecto |
|---|---|
| Nombre comercial | Login, títulos, tickets, documentos y mensajes |
| Logo claro / oscuro | Sidebar, login y tema claro |
| Pie de página | Login y documentos impresos |
| Color primario / acento | Se aplican en vivo sobre los 3 temas; vacío = tema original |
| URL pública | Base para enlaces de pago, correos y el enlace de reservas |
La marca es por instancia y no vive en el código: sale del parámetro
skeen.clinic.brand (API /skeen/frontend/v1/brand). Por eso una misma build del frontend sirve a
varias clínicas white-label sin recompilar.
2. Terminología (giro del negocio)
Configuración → Terminología
Elige el pack según el negocio y ajusta cualquier término a mano. El glosario tiene 24 términos configurables (singular y plural de paciente, cita, visita, expediente, médico, personal, sucursal, cabina/sala, servicio, paquete, receta y tratamiento).
| Término | Clínica (default) | Spa / Wellness | Estética | Dental |
|---|---|---|---|---|
| Paciente | Paciente | Cliente | Cliente | Paciente |
| Cita | Cita | Reserva | Cita | Cita |
| Visita | Visita | Sesión | Sesión | Consulta |
| Expediente | Expediente | Ficha | Ficha | Expediente |
| Médico | Médico | Terapeuta | Especialista | Odontólogo |
| Cabina / sala | Cabina | Sala | Cabina | Consultorio |
| Servicio | Servicio | Servicio | Servicio | Tratamiento |
| Receta | Receta | Recomendación | Receta | Receta |
| Tratamiento | Tratamiento | Tratamiento | Tratamiento | Procedimiento |
El pack cambia menús, títulos, botones, estados y también los mensajes de
notificación y el portal público de reservas. El pack custom parte de Clínica
y aplica solo los ajustes manuales.
3. Idioma de la interfaz
Menú de usuario → idioma o Configuración → Clínica (selector ES/EN).
- El selector cambia el idioma de toda la interfaz a Español o English.
- El idioma es por navegador (se guarda en el navegador del equipo), no por clínica ni por usuario; dos equipos pueden ver idiomas distintos.
- La i18n y el glosario conviven: el glosario define el vocabulario del negocio (paciente↔cliente, cita↔reserva) y solo existe en español; en inglés se usa un mapa base equivalente. El idioma traduce el resto del texto. En español manda el término del pack configurado.
4. Operación
Configuración → Clínica (datos y horarios)
- Teléfono, email, dirección, sitio web, RFC, nota de ticket.
- Horario de apertura y cierre: define la rejilla de la agenda (default 08:00–19:00).
- Zona horaria (default
America/Tijuana) y moneda base (defaultMXN).
Configuración → Sucursales: alta de sedes (nombre, código, dirección, teléfono) y cuál es la predeterminada. Cada cita pertenece a una sucursal. Las sucursales con histórico no se borran: se desactivan (quedan archivadas). Vienen dos de ejemplo (Rosarito predeterminada y Tijuana).
Configuración → Categorías: las 4 categorías base (Consulta, Tratamiento, Procedimiento, Paquete) se pueden renombrar y se pueden crear más (p. ej. "Depilación", "Faciales"). Las de sistema no se borran.
5. Catálogo y precios
- Servicios: nombre, categoría, precio, duración (define el tamaño del bloque en la agenda), paquete y tasa de impuesto.
- Inventario: artículos, consumibles (con caducidad, que bloquea la venta al vencer) y su tasa de impuesto.
- Los precios se editan en Servicios / Inventario; el POS y la agenda los toman de ahí.
6. Impuestos
Configuración → Clínica → Impuestos (apagado por defecto)
- Activar impuestos, nombre (default
IVA), tasa por defecto (default0) y catálogo de tasas (default0, 8, 16). Precios incluyen impuesto: si el precio capturado ya trae impuesto, el sistema lo desglosa automáticamente.- Con impuestos activos: desglose en POS, tickets, estado de cuenta y reporte Reportes → Impuestos (por mes, servicio y sucursal, exportable).
7. Reservas en línea (portal del cliente)
Configuración → Reservas en línea (apagado por defecto)
- Activar el portal y compartir el enlace
/reservarde la clínica (el propio panel muestra el enlace listo para copiar). - Opciones (con sus valores por defecto entre paréntesis): título y descripción
visibles al cliente, confirmación manual o automática (
requiere_confirmacion= sí), permitir elegir especialista (sí), permitir elegir sucursal (no), máximo de días a futuro (60), anticipación mínima en horas (2), teléfono de contacto, mensaje de confirmación y política de cancelación (permitir cancelar = sí, hasta 24 h antes). - El cliente recibe un enlace propio para consultar o cancelar su cita. Las reservas que llegan por el portal se distinguen en la agenda.
7.1 Anticipo (depósito) al reservar — apagado por defecto
Dentro del mismo bloque, la llave reservas_online.anticipo. Con activo = true:
- Opciones (defaults entre paréntesis):
tipo(porcentaje|monto_fijo),valor(0; el % sobre el precio del servicio o el monto fijo),moneda(MXN),horas_para_pagar(24),reembolsable(sí),texto_aviso(''), ypermitir_simulado(no, ver más abajo). - Al reservar, la cita queda retenida sin confirmar (badge "Esperando anticipo" en la agenda y en el detalle) y el portal muestra el monto y el botón para pagar. Al pagarse, la cita pasa a confirmada y se avisa por el motor de notificaciones.
- Si no se paga dentro de
horas_para_pagar, un proceso automático cancela la cita y libera el horario. - El anticipo se registra como pago real (
skeen.pago) ligado a la cita y a la venta, por lo que aparece en cortes de caja y reportes; no se duplica con el resto que el cliente pague después en caja. - Reembolso: con
reembolsable = true, al cancelar una cita con anticipo pagado, el pago se marca como reembolsado y la cita como "Anticipo reembolsado". Confalse, el anticipo se retiene.
7 bis. Cuenta del cliente (portal de autoservicio)
Configuración → Portal del cliente (apagado por defecto)
Hoy el cliente final solo llega por enlaces con token (reserva, pago,
formulario). Con este bloque se enciende una cuenta propia en /mi-cuenta
donde entra con su teléfono o correo, sin contraseña, y ve su información.
Apagado, nada cambia: el portal responde como deshabilitado y no aparece ninguna
ruta ni enlace nuevo (ni para el cliente ni para el personal).
- Acceso sin contraseña: el cliente escribe su teléfono (o correo) y recibe
por el motor de notificaciones un código de 6 dígitos por WhatsApp o un
enlace de acceso por correo, según
metodo(otp_whatsapp|enlace_correo|ambos). El código se guarda con hash, caduca en 10 minutos, admite como máximo 5 intentos y tiene límite de peticiones por IP y por teléfono/correo (nadie puede probar códigos ni molestar a un cliente). El enlace de correo es de un solo uso y caduca en 30 minutos. - Sesión propia del cliente, separada de la del personal: token firmado con alcance limitado al paciente identificado y revocable (cerrar sesión lo invalida de inmediato; el personal puede cerrar las sesiones de un paciente). Un token de cliente no funciona en los endpoints del personal, y uno del personal no funciona en el portal. El portal nunca confía en un identificador enviado por el navegador: el paciente siempre sale de la sesión.
- Opciones (defaults entre paréntesis):
activo(no),metodo(otp_whatsapp),requerir_correo_verificado(no),permitir_contrasena(no; permite fijar contraseña tras entrar),sesion_horas(24),permitir_reagendar(sí),horas_minimas_cancelar(24),mostrar_precios(sí),mostrar_recetas(sí),permitir_descargar_estado_cuenta(sí) ypermitir_actualizar_datos(sí). - Qué ve el cliente: Mis citas (próximas/pasadas; cancelar respetando
horas_minimas_cancelary reagendar reutilizando la disponibilidad real), Mis pagos (historial, saldo pendiente y estado de cuenta imprimible), Mi monedero (puntos y su equivalente en pesos y dólares), Mis paquetes (sesiones incluidas/usadas/restantes y vigencia), Mis membresías (plan, vigencia, próximo cobro, sesiones y adeudo, con botón para pagar el periodo pendiente por el enlace de cobro existente), Mis formularios (pendientes y respondidos con su firma), Mis documentos (recetas y estado de cuenta) y Mi perfil (datos de contacto y fotografías; edición solo sipermitir_actualizar_datos, y nunca datos clínicos). - Para el personal: en la ficha del paciente (expediente) hay un bloque para
invitar al portal, ver si ya entró (última entrada y sesiones abiertas)
y cerrar sus sesiones; en la pestaña de configuración hay un listado de
quién tiene acceso activo. Requiere los permisos nuevos
portal.invitaryportal.sesiones(por defecto: administración, gerencia y recepción). - Notificaciones: usa dos plantillas nuevas del bloque de notificaciones,
plantilla_codigo_accesoyplantilla_enlace_acceso(con advertencia de no compartir el código/enlace). En modo prueba del motor, la pantalla de acceso muestra el código o el enlace en pantalla para poder probar sin enviar nada real; con el modo prueba apagado nunca se expone. - Enlaces cruzados: el portal de reservas (
/reservar) enlaza a la cuenta y la pantalla de acceso del personal muestra un aviso para clientes que llegan ahí por error.
8. Recursos (cabinas, salas y equipos)
Configuración → Recursos (apagado por defecto)
Sirve para agendar recursos físicos además del médico: cabinas, salas, consultorios o equipos. Con el módulo apagado la agenda se ve igual que siempre y no se valida nada.
- Catálogo (
skeen.recurso): nombre, código, tipo (Cabina / Sala / Consultorio / Equipo / Otro), activo, secuencia, sucursales donde aplica (vacío = todas), capacidad, costo por hora, color y notas. Vienen dos recursos semilla (Cabina y Consultoría). - Opciones del bloque (defaults): activo (no),
validar_solape(sí),obligatorio_al_agendar(no),permitir_multiples(sí),mostrar_en_agenda(sí),filtrar_como_doctores(sí). - Asignación: en el modal de la cita se eligen uno o varios recursos.
- Validación de solape: con
validar_solapeencendido el sistema impide dos citas en el mismo recurso a la misma hora e informa con qué cita choca. También respeta los bloqueos del recurso. - Bloqueos por recurso: un bloqueo de agenda puede ser de un médico, de un
recurso o de ambos (
skeen.cita.bloqueo): fecha, todo el día o rango horario, motivo y serie (grupo). - Vista por recurso: la agenda puede mostrar el recurso en la tarjeta y ofrecer el filtro por recurso junto al de doctores. El reporte Reportes → Recursos muestra ocupación e ingresos estimados por recurso.
9. Usuarios, roles y permisos
Configuración → Usuarios: alta de usuarios, rol, menús visibles y, para agenda, las acciones específicas (consultar, agendar, editar, mover, eliminar, generar visitas, ver todas, bloquear).
Configuración → Roles: tres pestañas:
- Roles: crear roles propios del negocio (p. ej. Terapeuta, Recepción de fin de semana), renombrar, ajustar jerarquía y activar/desactivar. Vienen 10 roles base (admin, médico, recepción, enfermería, cosmetología, psicóloga, farmacia, gerencia, marketing, lectura).
- Permisos: 75 permisos por acción agrupados en 17 grupos (Agenda, Recursos, Pacientes, Visitas, Ventas, Inventario, Servicios, Reportes, WhatsApp, Notificaciones, Formularios, Membresías, Compras, Comisiones, Cobros y enlaces de pago, Configuración, Plataforma), con botones todo/ninguno. El backend los hace cumplir aunque el usuario manipule la interfaz.
- Menús: qué sección ve cada rol.
Los permisos de Cobros (defaults): cobros.ver (todos), cobros.administrar
(admin/gerencia), cobros.forzar (admin/recepción/gerencia) y cobros.cancelar
(admin/gerencia).
Recomendación: partir del rol más parecido, ajustar y guardar.
10. Notificaciones
Configuración → Notificaciones (apagado por defecto, con modo prueba)
- Recordatorios automáticos antes de la cita (ventanas configurables de hasta 168 h; default 24 h y 2 h), confirmación al reservar en línea, felicitación de cumpleaños, seguimiento post-visita (horas configurable) y recuperación de pacientes que no se presentaron.
- Canales: WhatsApp, correo o ambos (default WhatsApp). Plantillas editables con
vista previa y variables (
{nombre},{cita},{servicio},{fecha},{hora},{doctor},{sucursal},{telefono},{enlace},{formulario}y las de membresía{plan},{membresia},{monto},{sesiones},{periodo}). - Modo prueba (default): registra lo que se habría enviado sin contactar a nadie — úsalo para revisar textos antes de encenderlo.
- Configuración → Notificaciones enviadas: historial por paciente y por cita, con reintento.
11. Membresías
Configuración → Membresías (apagado por defecto) y Membresías (menú).
Una membresía no es un paquete: es un plan recurrente con vigencia, sesiones incluidas, cobro periódico, congelamiento y renovación.
- Planes (
skeen.membresia.plan): precio y moneda, periodicidad (semanal, mensual, trimestral, semestral, anual), sesiones incluidas por periodo (0 = ilimitadas), servicios y categorías incluidos, descuento en servicios no incluidos, cargo de inscripción, meses mínimos, permite congelamiento, sucursales y servicio con el que se cobra. - Opciones del bloque (defaults): activo (no),
dias_aviso_renovacion([7, 1]),permitir_congelamiento(sí),dias_max_congelamiento_anio(30),renovacion_automatica_default(no),descuento_porcentaje_default(0),permitir_pausa_pago(no),generar_cargo_al_renovar(sí),dias_gracia(5). - Alta: la membresía recibe folio
MEM-y calcula su periodo actual, próximo cobro y fin de compromiso. - Cobro: genera una venta y un pago normales (aparece en cortes de caja como cualquier venta). También cobra la inscripción la primera vez.
- Consumo desde POS/expediente: el consumo de sesiones no se descuenta en silencio; el POS o la cita llaman explícitamente a "usar sesión de membresía". Al cancelar una cita que usó una sesión, la sesión se libera.
- Congelamiento: se congela con rango y motivo, respetando el tope anual; al descongelar se corre el fin de periodo y el próximo cobro.
- Renovación: manual (avanza el periodo y genera el cargo si aplica) o automática por cron.
- Vencimientos y avisos: un cron diario marca vencidas (con días de gracia), envía avisos de renovación en cada ventana y descongela al terminar la ventana.
- Reporte: Membresías → reporte con ingreso recurrente por periodo.
11.1 Cobro automático de membresías — apagado por defecto
Dentro del bloque, la llave membresias.cobro_automatico. Con activo = true:
- Opciones (defaults entre paréntesis):
dias_antes(3),metodo(enlace|tarjeta_guardada),reintentos_dias([1, 3, 7]),cancelar_si_no_paga(no),dias_gracia(5) ypermitir_simulado(no). - Método
enlace: al acercarse el vencimiento el cron genera el enlace de pago del periodo y lo envía al paciente por el motor de notificaciones (plantillaplantilla_cobro_membresia, variable{enlace}). El periodo queda pendiente hasta que se pague; al pagarse pasa a pagado y la membresía se renueva sola. Reintentos: se vuelve a avisar en los días indicados respecto al vencimiento. Al agotarse los reintentos y los días de gracia, concancelar_si_no_pagala membresía pasa a vencida; apagado, solo se marca el periodo y es el proceso normal de vencimiento el que la vence. - Método
tarjeta_guardada: cargo sin presencia del cliente. Requiere credenciales reales de Stripe y tarjetas guardadas (que hoy no se persisten); sin ellas queda inerte (no cobra ni marca nada como pagado).
11 bis. Cobros en línea y pasarelas de pago
Los anticipos de reservas y el cobro automático de membresías usan un mismo
objeto, el enlace de cobro (skeen.cobro.enlace): origen (reserva,
membresía o venta), monto y moneda, token firmado con caducidad, estado
(pendiente/pagado/expirado/cancelado), proveedor (Stripe, MercadoPago o
simulado) y bitácora. Al pagarse se registra un skeen.pago real ligado a
la cita y a la venta.
- Página pública de pago:
/pagar/<token>(sin sesión). Muestra concepto, monto, estado y el botón de pago; tras pagar muestra el comprobante. Respeta marca, glosario e idioma y funciona en celular. - Proveedor
simulado: cuando no hay credenciales de pasarela, el enlace nacesimulado. Para poder probar el flujo completo sin dinero real hay que encenderreservas_online.anticipo.permitir_simuladoy/omembresias.cobro_automatico.permitir_simulado. En producción déjalos apagados: nunca se simula un pago sin permiso explícito. - Configurar Stripe (Odoo → Ajustes técnicos → Parámetros del sistema):
skeen.stripe_secret_key: llave secreta (sk_live_…/sk_test_…).skeen.stripe_webhook_secret: secreto del endpoint de webhook (whsec_…).- Webhook a
https://<url-pública>/skeen/frontend/v1/public/cobro/webhook/stripecon los eventoscheckout.session.completedypayment_intent.succeeded. La firma (Stripe-Signature) se verifica; sin secreto el webhook responde 400.
- Configurar MercadoPago (mismos parámetros):
skeen.mercadopago_access_token: access token de producción/prueba.skeen.mercadopago_webhook_secret(opcional): si se define, se verifica la firmax-signature; si no, se confirma consultando el pago con el token.- Webhook a
https://<url-pública>/skeen/frontend/v1/public/cobro/webhook/mercadopago.
- Sin credenciales: ambos webhooks existen pero rechazan la notificación (400) y el checkout real no se crea; el flujo queda inerte salvo el modo simulado explicado arriba.
- Reporte: Reportes → Cobros lista enlaces pendientes y expirados (anticipos y membresías), con totales, exportable a Excel, y permite forzar el cobro o cancelar la retención según los permisos de Cobros.
12. Compras y proveedores
Configuración → Compras (apagado por defecto) y Compras (menú).
- Proveedores: sobre el contacto (
res.partner) con marca propia de proveedor, días de crédito, contacto de compras, banco, cuenta/CLABE y notas. Un proveedor con historial no se borra: se desactiva. - Órdenes de compra (
skeen.compra): folioOC-, proveedor, líneas de artículo, moneda (MXN/USD), descuento e impuesto por línea. Estados: Borrador → Enviada → Recibida parcial / Recibida → Cancelada. Cancelar solo se permite si no hubo recepciones (si ya entró mercancía se usa una baja/ajuste). - Recepción total o parcial: cada recepción es acumulativa; al recibir se carga inventario (movimiento tipo compra) y se puede capturar lote y caducidad.
- Costo promedio: al recibir se recalcula el costo promedio ponderado del
artículo y se guarda el último costo (si
actualizar_costo_promedioestá encendido). - Pagos a proveedor: egresos separados de los cobros a pacientes (no aparecen en corte de caja ni en estado de cuenta del paciente).
- Cuentas por pagar: saldo por proveedor y reporte con antigüedad.
- Reportes: Reportes → Compras y margen por artículo (contra costo promedio y precio de venta sin impuesto).
- Opciones del bloque (defaults): activo (no),
actualizar_costo_promedio(sí),permitir_recepcion_parcial(sí),requiere_autorizacion(no),dias_credito_default(0),margen_minimo_alerta(0),permitir_compras_sin_orden(no).
13. Comisiones
Configuración → Comisiones (apagado por defecto), Reportes → Comisiones y Liquidaciones (menú).
Con el módulo apagado se conserva el reporte de comisiones de siempre (porcentaje plano por empleado). Al encenderlo se usa el motor de reglas.
- Reglas (
skeen.comision.regla): alcance global, por categoría, por servicio, por artículo, por plan de membresía o por paquete; tipo porcentaje, monto fijo o escalonado por metas; prioridad; dirigidas a un empleado, a un tipo de staff (doctor/cosmetóloga) o a todos; vigencia; y base propia opcional. La regla ganadora se decide por prioridad, luego por especificidad (artículo > servicio > membresía/paquete > categoría > global) y luego por empleado > tipo de staff > genérica. Sin ninguna regla aplicable se usa el porcentaje de comisión del empleado (respaldo de compatibilidad). - Base:
cobrado(default, sobre lo efectivamente pagado) ovendido(subtotal de la línea). Opcionalmente suma impuestos y resta la parte devuelta. - Escalonados: el porcentaje se decide con la venta total del periodo del empleado y se aplica a cada línea cubierta.
- Metas y bonos (
skeen.comision.meta): por empleado y periodo (AAAA-MMomensual), monto objetivo y bono fijo o porcentaje sobre la venta. - Ajustes manuales firmados (+/−), que suman o restan a la liquidación.
- Liquidaciones: se generan por empleado y periodo; al generarlas el desglose
queda congelado (ya no cambia aunque después se editen reglas o precios).
Estados Borrador → Pagada, o Borrador → Cancelada (una pagada no se cancela:
se registra un ajuste). Folio
LIQ-. - Opciones del bloque (defaults): activo (no),
base(cobrado),incluir_impuestos(no),neto_de_devoluciones(sí),comisionar_membresias(sí),comisionar_paquetes(sí),comisionar_productos(sí),permitir_ajustes_manuales(sí),dia_corte(1),redondeo(2 decimales),pago_minimo(0).
13 bis. Lealtad (monedero, puntos y niveles VIP)
Configuración → Lealtad, la tarjeta del paciente (saldo, nivel e historial de movimientos), la cuenta del cliente y Reportes → Puntos.
El programa de puntos vive en el bloque lealtad de los ajustes de la clínica.
Trae dos modos:
- Clásico (por defecto): reproduce exactamente el comportamiento de siempre — 1 punto por cada $10 pagados, 1 punto = $1, canje máximo del 50 % y sin niveles ni multiplicadores. Con este modo ninguna cifra cambia.
- Configurable: usa los valores del bloque.
Opciones del bloque (defaults entre paréntesis):
activo(sí),modo(clasico|configurable).puntos_por_unidad(0.1 = 1 punto por cada $10),valor_punto(1.0 pesos por punto al canjear),moneda_base(MXN).canje_max_pct(50): tope de canje sobre el total de la venta.expira_meses(0 = no expiran): con un valor mayor, el proceso diario vence los puntos no usados más antiguos que ese plazo y lo registra en la bitácora. En modo clásico nunca se expira nada.acumular_sobre(pagado|vendido),aplicar_a(servicios,productos,membresias,paquetes),redondear(abajo|normal).
Multiplicadores (multiplicadores[]): reglas con alcance (servicio,
artículo, categoría de servicio, nivel, sucursal, rango de fechas o día de la
semana), valor, factor (2 = doble de puntos; < 1 reduce) y vigencia
(fecha_desde/fecha_hasta). Precedencia: gana la más específica
(servicio > artículo > categoría > nivel > sucursal > rango de fechas > día de
la semana) y, a igual especificidad, la última de la lista.
Niveles VIP (niveles[]): cada nivel define codigo, nombre,
gasto_minimo, ventana_meses (por defecto 12), descuento_pct (se aplica
automáticamente en el punto de venta), factor_puntos, vigencia_meses y
color. El nivel se recalcula al cerrar cada venta y por el proceso diario.
Un cliente no baja de inmediato: el nivel conserva su vigencia y solo al
vencer se recalcula a la baja. La asignación manual (con fecha de revisión)
no se sobreescribe sola hasta esa fecha.
Puntos a mano y auditoría (lealtad.ajustar): el endpoint
POST /patients/<id>/points/adjust exige motivo y deja el movimiento en el
historial y en la auditoría. El nivel se puede recalcular
(POST /patients/<id>/lealtad/recalcular) o asignar a mano
(PUT /patients/<id>/lealtad).
Reportes (Reportes → Puntos): puntos otorgados, canjeados y expirados del
periodo, el pasivo en pesos (puntos activos × valor del punto) y los clientes
por nivel. En modo clásico coincide con las cifras de siempre.
Permisos: lealtad.ver (todos), lealtad.ajustar, lealtad.nivel y
lealtad.configurar (admin y gerencia).
13 ter. Propinas en el punto de venta
Configuración → Propinas, el cobro del punto de venta y Reportes → Propinas (exportable a Excel).
Con el módulo apagado (por defecto) el punto de venta se ve y se comporta exactamente igual que hoy: no aparece ningún campo de propina y el total no cambia. Al encenderlo, al cobrar se puede agregar una propina por porcentaje sugerido o por monto libre.
- La propina se guarda aparte del importe de los servicios (campos
propinaypropina_monedade la venta): el total cobrado al cliente sí la incluye y se muestra desglosada en el ticket y en el corte de caja, pero las cifras de servicios no cambian y los puntos se acumulan solo por los servicios. - Reparto (
ninguno|equitativo|por_participacion): al cobrar, la propina se reparte entre el personal que atendió y quien cobró; el detalle (quién, cuánto y de qué venta) queda enskeen.propina.repartoy en el reporte por empleado. incluir_en_liquidacion_comisiones(no): al encenderlo, la propina del empleado se suma a su liquidación de comisiones sin alterar el cálculo de la comisión; apagado, no cambia ninguna liquidación.
Opciones del bloque (defaults): activo (no), sugerencias_pct
([10, 15, 20]), permitir_personalizado (sí), permitir_sin_propina (sí),
reparto (ninguno), incluir_en_liquidacion_comisiones (no) y
cuenta_propinas (etiqueta de la cuenta destino).
Permisos: propinas.ver (todos), propinas.aplicar (recepción y demás roles
de cobro) y propinas.configurar (admin y gerencia).
14. Formularios y consentimientos
Configuración → Formularios y, en el expediente del paciente, la pestaña de formularios.
- Plantillas (
skeen.formulario.plantilla): tipo consentimiento informado, nota de expediente, encuesta o autorización; con campo de texto legal, requerir firma y/o foto, duración estimada y asociación opcional a sucursales y servicios. Las plantillas se versionan: cada respuesta guarda la versión con la que se llenó. - Tipos de campo (13): texto, texto largo, número, fecha, selección, multiselección, casilla, escala, recomendación (NPS 0-10), firma, foto, archivo y consentimiento. Los campos de foto/archivo pueden marcarse como antes / después / otro, lo que arma la galería antes/después del expediente. El campo de recomendación (NPS) es un tipo propio: se puede analizar sin depender del texto (ver la sección de encuestas de salida).
- Envío: por WhatsApp, correo o enlace. El enlace es un token firmado (HMAC, vigencia 180 días) y deja de servir al llenarse.
- Llenado por el paciente: página pública
/formulario/<token>(también funciona en el celular) con firma capturada como PNG (hasta 3 MB) y fotos (hasta 5 MB cada una, máximo 10). El sistema valida campos obligatorios, firma y fotos requeridas. - Historial: respuestas por paciente con canal, fecha, firma y fotos.
14 bis. Campañas por segmentos — apagado por defecto
Configuración → Campañas (interruptor) y Campañas (menú, sección
"Comunicación"), con dos pestañas: Campañas y Segmentos. Con el bloque
apagado (campanas.activo = false, el default) no aparece ninguna pantalla ni
enlace, no corre ningún proceso automático y no se envía nada.
- Segmentos (
skeen.segmento): un segmento guarda nombre, criterios y una previsualización (cuántos pacientes y una muestra de 5) que se calcula antes de usarlo. Criterios disponibles (todos opcionales):- última visita hace más de N días, o sin visita en N meses (incluye a quien nunca ha venido);
- cumpleaños del mes en curso o en los próximos N días;
- nivel de lealtad;
- gasto acumulado (suma de ventas no canceladas) mayor o igual a X;
- sucursal (con al menos una cita ahí);
- servicio que sí ha tomado y servicio que nunca ha tomado;
- con o sin membresía activa;
- con o sin paquetes con sesiones disponibles;
- con o sin saldo pendiente;
- con o sin consentimiento de marketing. La evaluación corre en el servidor y su conteo coincide con lo que responde la base de datos.
- Campañas (
skeen.campana): nombre, segmento, canal (WhatsApp, correo o ambos), mensaje con variables ({nombre},{servicio},{sucursal},{enlace},{doctor},{fecha},{hora},{telefono}), programación (una sola vez en una fecha, mensual, semanal o según el propio segmento, p. ej. cumpleaños) y estado (borrador, programada, en ejecución, pausada, terminada, cancelada). - Envío de prueba: manda el mensaje a un número o correo propio antes de lanzar. Queda registrado en la bitácora marcado como prueba (no cuenta en la medición).
- Medición por campaña: pacientes alcanzados, enviados, errores y pendientes; citas generadas como consecuencia (atribuidas por paciente y dentro de una ventana configurable, por defecto 7 días) y su valor en dinero; y la tasa de conversión. Lo que no se puede medir con lo que hay (entrega real y respuestas del paciente) se muestra como no disponible en lugar de inventarse.
- Cuidado de WhatsApp: límite de envíos por minuto configurable, pausa automática si se acumulan errores seguidos y respeto al consentimiento (ver abajo).
- Opciones del bloque (defaults):
activo(no),envios_por_minuto(20),pausar_tras_errores(5),ventana_atribucion_dias(7),exigir_consentimiento(sí) yhora_envio(10:00, para las recurrentes).
14 bis.1 Consentimiento de marketing por canal
En el paciente (res.partner) hay un interruptor general y uno por canal:
consentimiento_marketing(general),consentimiento_whatsappyconsentimiento_email, más la fecha y el origen del consentimiento.
Un paciente sin consentimiento de marketing nunca recibe una campaña, aunque cumpla el criterio del segmento. Los avisos transaccionales (recordatorio de cita, confirmación, encuesta de salida) no dependen de esto: son parte del servicio que el paciente ya contrató. El consentimiento nace apagado.
14 bis.2 Permisos
campanas.ver: ver campañas y segmentos (por defecto: todos los roles).campanas.gestionar: crear y editar campañas y segmentos (admin, gerencia y marketing).campanas.enviar: lanzar campañas y enviar pruebas (admin, gerencia y marketing).campanas.medir: ver la medición (por defecto: todos los roles).
14 ter. Encuestas de salida y satisfacción (NPS) — apagado por defecto
Configuración → Encuestas (interruptor) y Satisfacción (menú). Con el
bloque apagado (encuestas.activo = false, el default) no se envía ninguna
encuesta tras completar una cita y la pantalla de Satisfacción no aparece.
- Envío automático: cuando una cita pasa a completada, tras N horas (default 2) se envía al paciente la encuesta configurada, por WhatsApp, correo o ambos. Hay recordatorio opcional si no responde (default 48 h) y una opción de enviarla solo a la primera visita.
- Captura: reutiliza la página pública de formularios
/formulario/<token>(no hay otro mecanismo de captura). El mensaje de agradecimiento es configurable. - Pregunta de recomendación (NPS): tipo de campo propio
nps(puntaje de 0 a 10) más un comentario abierto (texto largo). Se calcula de forma estándar: promotores 9-10, pasivos 7-8, detractores 0-6, y NPS = % promotores − % detractores (de −100 a 100). - Reporte de satisfacción: resultado del periodo, tendencia por mes, desglose por sucursal, médico y servicio, y la lista de respuestas con su comentario y un enlace a la ficha del paciente para dar seguimiento (incluida la posibilidad de responderle por WhatsApp desde ahí). Exportable a Excel.
- Opciones del bloque (defaults):
activo(no),enviar_tras_horas(2),plantilla_id(ninguna),canal(whatsapp),recordatorio_horas(48),solo_primera_visita(no) yagradecimiento(vacío). - Permisos:
encuestas.veryencuestas.medir(todos los roles);encuestas.gestionar(admin y gerencia).
Ambas piezas pasan por el motor de notificaciones: nada se envía en silencio, todo respeta el modo prueba y queda en la bitácora con su campaña o encuesta de origen.
15. Tickets y documentos
Configuración → Tickets: ancho (58/80 mm), fuente, logo y qué secciones se imprimen (incluida la de impuestos). Se aplica al ticket de venta y al de reimpresión. Los perfiles de ticket son por instancia, con defaults neutros: una instancia nueva no arrastra datos de SKEEN.
16. Licencia
Configuración → Licencia (admin; gerencia también ve el estado).
Cada instancia white-label puede llevar una licencia firmada que decide qué módulos incluye y sus límites de uso. Sin licencia aplicada el sistema se comporta con todas las funciones habilitadas.
- Planes:
basico,profesional,enterpriseycustom.- Básico: agenda, pacientes, POS, inventario y reportes.
- Profesional: Básico + WhatsApp, notificaciones, reservas en línea y recursos.
- Enterprise: todos los módulos.
- Custom: lo que diga la clave.
- Módulos gateables (controlables por licencia): WhatsApp, notificaciones, reservas en línea, recursos, membresías, compras, comisiones y formularios. Login, agenda, pacientes, POS, inventario, reportes y configuración nunca se bloquean.
- Límites: usuarios, sucursales, citas del mes y almacenamiento (MB).
0= sin límite. - Modo:
aviso(default; solo advierte y registra en el log) obloqueo(oculta menús, responde 403 en los endpoints del módulo y aplica los límites). - Cómo aplicar una clave: pegar la clave
SKN1...en Configuración → Licencia y guardar. La clave se verifica contra la firma y la vigencia; si es inválida o vencida responde 400 y no sobrescribe la licencia previa. Un campo vacío quita la licencia y vuelve a habilitar todo. El detalle del formato de la clave, la herramienta del vendedor y los endpoints está enlicencias.md.
17. API para terceros
Configuración → API (admin). Gestión de claves con alcances (scopes),
vencimiento y revocación, sobre la API pública /skeen/api/v1/* que consume
Hermes. La clave se muestra una sola vez al crearla. Alcances disponibles:
citas.read, citas.write, pacientes.read, servicios.read y
monedero.write. El detalle está en api-terceros.md.
18. Webhooks
Configuración → Webhooks (admin/gerencia). Notificación de eventos de la
clínica hacia sistemas externos, con patrón outbox + reintentos + bitácora y
firma HMAC de cada entrega. Sin webhooks activos no se emite ni se envía nada.
El catálogo de eventos, la verificación de la firma y los endpoints están en
webhooks.md.
19. PWA (instalable en tablet y celular)
El panel es una aplicación web instalable (PWA), sin tienda de aplicaciones.
- Instalar: abrir el panel en el navegador del dispositivo. En Android/Chrome aparece el aviso "Instalar aplicación"; en iPhone/Safari se usa "Compartir → Añadir a pantalla de inicio" (el aviso trae la guía de iOS).
- Comportamiento offline: un service worker precachea el app shell y los
assets con hash. La navegación es network-first (un deploy nuevo se ve al
primer refresh); si no hay red se sirve la última copia del shell o una página
offline.html. Las llamadas al API (/api/*) y cualquier petición con credenciales nunca se cachean. - Limitación: los iconos y el nombre del manifest son fijos por build ("Panel Clínico" e iconos genéricos). No cambian con la marca de la instancia; cambiarlos requiere recompilar el frontend. La marca visual (nombre, logos, colores) sí es por instancia y no requiere build.
Checklist de arranque
- Identidad: nombre, logos, colores, URL pública.
- Terminología: pack del giro + ajustes finos.
- Idioma de la interfaz (si el cliente no trabaja en español).
- Horarios, zona horaria, moneda, sucursales, categorías.
- Catálogo de servicios con precios y duraciones.
- Inventario y consumibles (caducidades y costos reales).
- Impuestos (tasa por defecto + tasas por servicio/artículo).
- Usuarios y roles/permisos.
- Recursos (si la agenda depende de cabinas/salas/equipos).
- Membresías (si vende planes recurrentes).
- Compras y proveedores (si controla abasto y margen).
- Comisiones (reglas, metas y liquidaciones).
- Formularios y consentimientos.
- Campañas por segmentos (si hará marketing): activar y registrar el consentimiento de los pacientes.
- Encuestas de salida: crear la plantilla con la pregunta NPS y activar.
- Reservas en línea (activar y difundir el enlace).
- Portal del cliente (si se ofrece cuenta): activar y difundir
/mi-cuenta. - Notificaciones en modo prueba → revisar textos → encender.
- Tickets: formato y secciones.
- Licencia: aplicar la clave del plan contratado.
- API / Webhooks si se integra con terceros.
- Confirmar que las credenciales del admin se cambiaron.
Estado del producto por fases
Todas las fases están entregadas.
| Fase | Alcance | Estado |
|---|---|---|
| 1 | Capa de configuración (terminología, sucursales, categorías, ajustes, colores, horarios, URLs de pago), defaults neutros, provisioning de instancias | Entregado |
| 2.1 | Roles y permisos editables | Entregado |
| 2.2 | Impuestos configurables | Entregado |
| 2.3 | Portal público de reservas en línea | Entregado |
| 2.4 | Recordatorios y notificaciones automáticas | Entregado |
| 2.5 | Formularios digitales y consentimientos con firma y fotos | Entregado |
| 2.6 | Membresías y suscripciones | Entregado |
| 3.1 | Recursos físicos en la agenda | Entregado |
| 3.2 | Compras y proveedores | Entregado |
| 3.3 | Comisiones por reglas y liquidación | Entregado |
| 3.4 | PWA instalable y branding por instancia | Entregado |
| 3.5 | Licenciamiento por plan, API keys gestionables y webhooks | Entregado |
| 3.6 | i18n español/inglés | Entregado |
| 3.7 | Cuenta del cliente (portal de autoservicio) | Entregado |
| 3.8 | Campañas por segmentos con medición y consentimiento de marketing | Entregado |
| 3.9 | Encuestas de salida y satisfacción (NPS) | Entregado |
| Operación | Backups automáticos verificados y panel/CLI multi-instancia | Entregado |
Los pendientes y limitaciones conocidos (los que aún no están cerrados) viven en
limitaciones-y-pendientes.md.