# Propuesta técnica breve: plataforma de gestión para Yola Franco Spa **Versión:** 0.1 — propuesta conceptual **Objetivo:** construir una web app de operación diaria para el spa, con una experiencia extremadamente rápida para empleadas y un dashboard de control para la dueña, conectada con GoHighLevel (GHL) mediante API y webhooks. --- ## 1. Resumen de la solución La plataforma funcionará como un sistema operativo interno del spa: - **Dueña/administradora:** visualiza ventas, citas, rendimiento, clientes, servicios, campañas y operación. - **Empleada:** gestiona su agenda, crea y modifica citas, consulta clientes y registra la atención con el mínimo número de clics. - **GoHighLevel:** conserva la relación omnicanal y automatizaciones de marketing. La app sincroniza contactos, conversaciones y eventos de cita mediante API/webhooks. - **PostgreSQL:** fuente de datos operativos de la plataforma: citas, clientes, servicios, empleadas, pagos, comisiones, auditoría y sincronizaciones. La recomendación es no intentar clonar toda la superficie de AgendaPro en la primera versión. El MVP debe resolver primero la operación diaria, la visibilidad del negocio y la integración confiable con GHL. ## 2. Alcance funcional ### 2.1 Panel de la administradora 1. **Dashboard ejecutivo** - Ventas del día, semana y mes. - Citas agendadas, atendidas, canceladas y no-show. - Ingresos por servicio, empleada y canal. - Ticket promedio. - Tasa de recompra y clientes nuevos. - Ocupación de agenda por empleada. - Top clientes por frecuencia, gasto y última visita. - Top servicios y servicios con baja demanda. - Fuente de adquisición: orgánico, Instagram, Facebook, WhatsApp, campañas GHL, referido u otro. 2. **Calendario global** - Vista diaria, semanal y mensual. - Filtros por empleada, servicio, estado y ubicación. - Crear, mover, confirmar, reprogramar y cancelar citas. - Bloqueos de horario, descansos, vacaciones y días no laborables. 3. **Clientes/CRM operativo** - Búsqueda por nombre, teléfono, correo o identificador GHL. - Historial de citas, servicios, pagos, notas y conversaciones enlazadas. - Etiquetas: nuevo, frecuente, VIP, inactivo, campaña, referido, etc. - Consentimiento de comunicaciones y preferencias. - Próxima recomendación de servicio y fecha sugerida de regreso. - Detección de posibles duplicados antes de crear un cliente. 4. **Catálogo y configuración** - Servicios, categorías, duración, precio, buffer y empleadas habilitadas. - Horarios de atención y reglas de disponibilidad. - Comisiones por servicio o por empleada. - Paquetes, promociones y tarjetas/membresías en una fase posterior. 5. **Reportes** - Exportación CSV/XLSX de clientes, citas y ventas. - Reporte por periodo, empleada, servicio y canal. - Registro de cambios y actividad administrativa. ### 2.2 Panel de la empleada Diseñado primero para móvil y tablet, con navegación reducida: - **Hoy:** próximas citas, hora, cliente, servicio y estado. - **Mi agenda:** día/semana con bloques visuales. - **Nueva cita rápida:** seleccionar fecha/hora, servicio, cliente y confirmar. - **Búsqueda de cliente:** resultados mientras se escribe; evitar duplicados. - **Alta rápida:** nombre y teléfono obligatorios; correo y notas opcionales. - **Acciones de una cita:** confirmar, iniciar, completar, reprogramar, cancelar y marcar no-show. - **Ficha resumida:** historial reciente, notas relevantes, preferencias y próxima visita. - **Rendimiento personal:** citas atendidas, ventas generadas, ticket promedio, cancelaciones y comisión estimada. La empleada no debe ver información financiera global ni clientes ajenos a sus permisos, salvo que la administradora lo configure. ## 3. Roles y permisos Usar autorización basada en roles (RBAC), no solamente ocultamiento visual: | Recurso | Administradora | Empleada | |---|---:|---:| | Dashboard global | Sí | No | | Dashboard personal | Sí | Sí | | Calendario global | Sí | Según permiso | | Mi agenda | Sí | Sí | | Crear cita | Sí | Sí | | Editar/cancelar cualquier cita | Sí | Solo propias, según regla | | Ver clientes | Todos | Necesarios para operar | | Exportar clientes/ventas | Sí | No | | Editar precios/comisiones | Sí | No | | Ver ventas globales | Sí | No | | Configurar GHL | Sí | No | | Auditoría | Sí | No | La aplicación debe estar preparada para `tenant_id`, aunque inicialmente exista un solo spa. Esto evita rediseñar la base si después se ofrecen cuentas a otros negocios. ## 4. Arquitectura propuesta ```text [Web app responsive] | v [API Python: FastAPI] | | | | | +--> [Worker: Celery/RQ + Redis] | +-----------> [GoHighLevel API] +-------------------> [PostgreSQL] | +--> métricas/reportes [GHL Webhooks] ---> [Endpoint seguro] ---> [Event inbox] ---> [Worker] ``` ### Componentes - **Frontend:** Next.js/React + TypeScript, PWA instalable, Tailwind CSS o sistema de componentes equivalente. - **Backend:** Python 3.12+ con FastAPI, Pydantic y SQLAlchemy 2.x/SQLModel. - **Base de datos:** PostgreSQL 16+, migraciones con Alembic. - **Cola y caché:** Redis; workers para webhooks, sincronizaciones y mensajes sin bloquear la interfaz. - **Autenticación:** sesiones seguras con cookies HttpOnly o JWT de corta duración con refresh rotativo. MFA para la administradora en una fase posterior. - **Despliegue inicial:** Docker Compose en staging; producción con PostgreSQL administrado, Redis administrado y servicio web/worker separado. - **Observabilidad:** logs estructurados, Sentry/OpenTelemetry opcional, métricas de errores de integración y tiempos de respuesta. ## 5. Modelo de datos inicial Tablas principales: - `tenants`: spa/cuenta, zona horaria, configuración y estado. - `users`: usuarios internos, correo, estado y último acceso. - `roles`, `user_roles`: administradora y empleada. - `employees`: perfil operativo, especialidades, horarios y comisión. - `services`: nombre, categoría, duración, precio, buffer, activo. - `employee_services`: servicios que puede realizar cada empleada. - `customers`: nombre, teléfono normalizado, correo, consentimiento, `ghl_contact_id`. - `customer_tags`: etiquetas operativas y de adquisición. - `appointments`: cliente, empleada, servicio, inicio, fin, estado, origen, notas y `ghl_appointment_id`. - `appointment_events`: historial de cambios de una cita. - `payments`: monto, método, estado, referencia y fecha. - `campaign_attributions`: UTM, campaña, fuente, medio y primer/último contacto. - `conversations`: referencia a conversación/canal en GHL; no necesariamente almacenar todo el contenido si GHL es la fuente principal. - `integration_connections`: ubicación GHL, tokens cifrados, scopes y estado. - `integration_events`: webhook/evento recibido, payload hash, estado, reintentos e idempotency key. - `outbox_events`: eventos internos pendientes de enviar a GHL. - `audit_logs`: quién cambió qué, cuándo y desde dónde. ### Reglas importantes - Normalizar teléfonos a formato E.164 (`+52...`) antes de buscar o crear contactos. - `UNIQUE (tenant_id, normalized_phone)` para evitar duplicados básicos. - Guardar fechas en UTC y mostrar en `America/Mexico_City`. - Usar `timestamptz` y rangos para impedir doble reserva. - Crear una restricción de exclusión PostgreSQL por empleada para evitar solapamientos de citas confirmadas. - No borrar clientes físicamente; usar estado, anonimización y política de retención. ## 6. Integración con GoHighLevel ### 6.1 Autenticación y configuración Preferir OAuth 2.0 para una integración comercial reutilizable. Para una sola subcuenta controlada por el equipo, puede iniciarse con credenciales de ubicación/API adecuadas, almacenadas cifradas en el servidor. No guardar tokens en frontend ni en PostgreSQL en texto plano. Usar un gestor de secretos o variables de entorno del servidor; las variables deben contener secretos, no configuración funcional. Configurar en GHL: - Location/Sub-account ID del spa. - Client ID y Client Secret de la aplicación, si se usa OAuth. - Scopes mínimos necesarios. - URLs de redirección OAuth. - URLs de webhooks. - Firma/secreto de validación de webhooks, si está disponible en el evento utilizado. ### 6.2 Sincronización de contactos **Crear desde la app:** 1. La empleada captura teléfono y nombre. 2. La API busca primero en PostgreSQL por teléfono normalizado. 3. Si existe `ghl_contact_id`, actualiza o reutiliza el contacto. 4. Si no existe, consulta GHL por teléfono/correo. 5. Si tampoco existe, crea el contacto mediante API. 6. Guarda `ghl_contact_id`, respuesta resumida y evento de sincronización. 7. La cita se crea solamente después de resolver el cliente local. **Actualizar desde la app:** usar una cola `outbox_events`, con reintentos y clave de idempotencia. La pantalla no debe quedar bloqueada si GHL está temporalmente fuera de servicio; debe mostrar “guardado local / sincronización pendiente”. **Recibir desde GHL:** registrar webhooks de creación/actualización de contacto, cambios relevantes y eventos de conversación disponibles para la cuenta. El webhook debe responder rápido con HTTP 2xx y procesarse en segundo plano. ### 6.3 Conversaciones y mensajes La app puede mostrar una vista resumida de conversaciones, pero conviene mantener GHL como sistema principal de mensajería omnicanal: - GHL recibe mensajes de WhatsApp, Facebook e Instagram. - GHL dispara webhooks hacia la plataforma cuando exista un evento compatible. - La plataforma almacena metadatos y referencias, no necesariamente todo el historial. - Cuando la dueña o empleada envía un mensaje desde la app, el backend ejecuta una petición autenticada a la API de GHL. - El frontend nunca llama directamente a GHL. **Flujo de envío:** ```text Frontend -> POST /api/conversations/{id}/messages -> valida permiso y contenido -> crea outbox_event -> worker llama API GHL -> guarda resultado/id externo -> frontend recibe estado enviado/fallido ``` Debe contemplar límites de frecuencia, reintentos con backoff, mensajes duplicados, archivos multimedia y errores de permisos. Las capacidades exactas de envío deben validarse contra la versión actual de la API y los canales habilitados en la subcuenta. ### 6.4 Webhooks seguros e idempotentes Endpoint sugerido: ```text POST /api/integrations/gohighlevel/webhooks/{tenant_id} ``` Proceso: 1. Validar firma, secreto o mecanismo oficial disponible. 2. Validar tamaño y estructura del payload. 3. Calcular hash del evento y revisar `integration_events`. 4. Si ya fue procesado, responder 200 sin duplicar efectos. 5. Insertar el evento en la bandeja de entrada. 6. Responder 200 rápidamente. 7. Worker transforma el evento y actualiza contacto/conversación/cita. 8. Registrar resultado, duración y número de reintentos. ## 7. API interna sugerida ```text POST /api/auth/login GET /api/dashboard/summary?from=&to= GET /api/calendar?from=&to=&employee_id= POST /api/appointments PATCH /api/appointments/{id} POST /api/appointments/{id}/confirm POST /api/appointments/{id}/complete POST /api/appointments/{id}/cancel GET /api/customers?query= POST /api/customers GET /api/customers/{id} PATCH /api/customers/{id} GET /api/services POST /api/services GET /api/employees GET /api/reports/sales GET /api/reports/performance GET /api/conversations POST /api/conversations/{id}/messages POST /api/integrations/gohighlevel/connect POST /api/integrations/gohighlevel/sync POST /api/integrations/gohighlevel/webhooks/{tenant_id} GET /api/integrations/jobs/{id} ``` Todos los endpoints deben validar `tenant_id`, rol, permisos de recurso y esquema de entrada. La API debe devolver errores consistentes (`code`, `message`, `details`, `request_id`). ## 8. Métricas que importan al dueño ### Ventas - Ingresos brutos/netos por periodo. - Ticket promedio. - Ventas por servicio, empleada y canal. - Métodos de pago. - Comisiones. ### Operación - Utilización de horas disponibles. - Citas atendidas, canceladas, reprogramadas y no-show. - Tiempo promedio entre citas. - Huecos disponibles próximos 7/14 días. ### Clientes - Clientes nuevos vs recurrentes. - Recompra a 30/60/90 días. - Frecuencia y valor acumulado. - Clientes inactivos. - Fuente de adquisición y campaña. ### Marketing/GHL - Contactos creados. - Conversaciones iniciadas. - Leads que terminaron en cita. - Citas por campaña/UTM. - Tiempo de respuesta, si GHL expone el dato necesario. Los dashboards deben mostrar periodo, filtros, definición de cada métrica y fuente del dato. No presentar “ROI” si no se cuenta con costo de campaña confiable. ## 9. Experiencia de usuario y responsive Prioridad de diseño: **la empleada opera con una mano y pocos segundos disponibles**. - Mobile-first; soportar 360 px de ancho como mínimo. - Botón persistente “Nueva cita”. - Búsqueda global rápida de cliente. - Calendario con colores por estado, no solamente por empleada. - Formularios cortos y autoguardado de notas. - Confirmación clara antes de cancelar o modificar una cita. - Estados offline/pending para sincronizaciones. - Accesibilidad WCAG 2.2 AA como objetivo. - PWA para acceso desde la pantalla de inicio; no asumir aplicación nativa en el MVP. ## 10. Seguridad, privacidad y operación - HTTPS obligatorio y cookies `Secure`, `HttpOnly`, `SameSite`. - Hash de contraseñas con Argon2id o bcrypt configurado correctamente. - Rate limiting en login, búsquedas y envío de mensajes. - Validación de permisos en backend. - Auditoría de cambios sensibles. - Cifrado de secretos y datos sensibles en reposo cuando el proveedor lo permita. - Backups automáticos de PostgreSQL y prueba periódica de restauración. - Protección contra CSRF si se usan cookies de sesión. - Sanitización de notas y contenido de mensajes. - Política de privacidad, consentimiento para marketing y procedimiento de eliminación/anonimización. - No guardar datos completos de tarjeta; integrar un proveedor de pagos si después se requiere cobro en línea. ## 11. Fases recomendadas ### Fase 0 — Descubrimiento técnico - Confirmar documentación y scopes vigentes de GHL. - Confirmar canales disponibles y eventos de webhook. - Levantar catálogo, horarios, empleadas, reglas de reserva y métodos de pago. - Definir si la fuente principal de agenda será la nueva app o AgendaPro durante la transición. ### Fase 1 — MVP operativo - Login y RBAC. - Clientes y búsqueda anti-duplicados. - Servicios y empleadas. - Calendario y nueva cita rápida. - Estados de cita. - Dashboard básico. - PostgreSQL, migraciones, backups y auditoría. ### Fase 2 — Integración GHL - Conexión segura con subcuenta. - Crear/actualizar contactos. - Sincronización inicial controlada. - Webhooks idempotentes. - Outbox y workers. - Vista de conversaciones y envío de mensajes compatible con canales habilitados. ### Fase 3 — Analítica y crecimiento - Ventas y pagos. - Comisiones. - Campañas/UTM. - Recompra y reactivación. - Reportes exportables. - Paquetes, promociones, recordatorios y membresías. ## 12. Criterios de aceptación del MVP - Una empleada puede crear una cita en menos de un minuto desde móvil. - La búsqueda por teléfono encuentra un cliente existente sin crear duplicado. - Dos usuarios no pueden reservar el mismo horario para la misma empleada. - La administradora puede filtrar citas, ventas y rendimiento por periodo y empleada. - Un cliente creado localmente se sincroniza con GHL o queda claramente marcado como pendiente. - Un webhook repetido no duplica clientes, citas ni mensajes. - Una caída temporal de GHL no borra ni impide guardar la operación local. - Cada cambio relevante deja registro de usuario, fecha y acción. - Los permisos impiden a una empleada consultar reportes globales o modificar precios. - Los datos mostrados en dashboard incluyen su periodo y fuente. ## 13. Riesgos y decisiones pendientes 1. **API de GHL:** endpoints, scopes, límites y eventos disponibles pueden variar por versión y plan; deben validarse en un spike antes de comprometer el alcance. 2. **Doble agenda:** operar simultáneamente AgendaPro y la nueva app puede producir conflictos. Se debe elegir una fuente de verdad o construir sincronización explícita. 3. **Mensajería omnicanal:** Instagram, Facebook y WhatsApp pueden tener restricciones distintas; el sistema debe degradar con gracia y mostrar el estado real. 4. **Migración de datos:** antes de importar contactos hay que normalizar teléfonos y definir política de duplicados. 5. **Privacidad:** nombre, teléfono, historial y conversaciones requieren consentimiento, controles de acceso y política de retención. 6. **Pagos:** si inicialmente solo se registra pago manual, etiquetarlo como registro operativo y no como conciliación bancaria. ## Recomendación final Construir primero una **agenda operacional mobile-first con clientes y dashboard**, y después agregar la capa omnicanal de GHL mediante una arquitectura de eventos (`outbox`, `event inbox`, workers e idempotencia). PostgreSQL es una elección adecuada para escalar la operación y los mensajes referenciados, pero GHL debe permanecer como sistema de conversaciones mientras la app se consolida como sistema de agenda, clientes y rendimiento. El siguiente paso técnico recomendable es un **spike de integración de 3–5 días** que pruebe: autenticación GHL, creación/búsqueda de contacto, recepción de un webhook, envío de un mensaje permitido y sincronización de una cita. El resultado debe incluir scopes reales, payloads, límites y decisiones de fuente de verdad antes de iniciar el desarrollo completo.