# Plan — Sistema Veterinaria (vertical activable por giro)

> Estado: **propuesta para revisión** (no se construyó nada todavía).
> Fecha: 2026-06-22. Base: investigación profunda del codebase (3+ agentes).

---

## 0. Principio rector — TODO detrás del giro

El vertical completo se enciende **solo** al marcar el giro **"Veterinaria"** en el alta del cliente (super-admin). Una farmacia/botica **no ve nada** de esto. Mecanismo (mismo patrón que `is_pharmacy`):

- **Flag `is_veterinary`** en `configurations` (por tenant) → gatea menús, campos y pantallas.
- **Módulo `Vet`** (`modules/Vet/`) + sus **niveles** (Mascotas, Citas, Historia, Agenda, Hospedaje, Carné).
- **Giro "Veterinaria"** = 3er radio en el form de Clientes + bundle `group_veterinary` que pre-marca módulos base + el módulo Vet.
- El **core compartido** (POS, facturación, inventario, compras, finanzas) NO se duplica ni se toca su comportamiento para farmacias.

---

## 1. Arquitectura

- **Módulo `modules/Vet/`** (nwidart, auto-registrado por `module.json`). Clona la estructura mínima de `Digemid` + el patrón de entidades de `Hotel`/`Item`.
- **Frontend:** la SPA admin es **multipágina con islas Vue** (no hay Vue Router). Cada pantalla = un blade que extiende `tenant.layouts.app` y monta un componente registrado en `resources/js/app.js` (bundle único). Navegación = links del sidebar (recarga). Las pantallas vet siguen ese patrón.
- **Gating:** menú en `sidebar.blade.php` con `@if($configuration->isVeterinary() && in_array('vet_x', $vc_module_levels))`. Campos en forms con `v-if="config.is_veterinary"`.

---

## 2. Modelo de datos (tablas nuevas — prefijo `vet_` para evitar colisiones con el clínico viejo)

| Tabla | Campos clave | Notas |
|---|---|---|
| `vet_pets` (Mascota) | `person_id`(dueño→`persons`), name, species, breed, sex, birthdate, color, weight, microchip, photo, notes, active | Núcleo. Dueño = `Person` cliente (NO meter mascota en `persons`). |
| `vet_vaccination_records` (Carné) | `pet_id`, `item_id`(vacuna), vaccine_name(snapshot), applied_date, lot_code, `next_dose_date`, `veterinarian_id`(→users), `document_id`/`sale_note_id`, observations | El carné = lista por `pet_id`. `next_dose_date` dispara recordatorio. |
| `vet_appointments` (Cita) | `pet_id`, `person_id`, `user_id`(vet), `establishment_id`, datetime, status(reservada/confirmada/atendida/no-show), type(grooming/consulta), reason | Agenda por sucursal. |
| `vet_doctor_schedules` (Horarios) | `user_id`(vet), `establishment_id`, día/franjas | Disponibilidad del vet. |
| `vet_medical_consultations` (Historia) | `pet_id`, `appointment_id`, `user_id`, anamnesis, examen, peso/temp, plan | 1 consulta = 1 entrada de historia. |
| `vet_consultation_diagnoses` | `consultation_id`, `prescription_cie10_id` | Junction → reutiliza catálogo de diagnósticos existente. |
| `vet_consultation_procedures` | `consultation_id`, `procedure_id` | Junction. |
| `vet_procedures` (catálogo) | name, `item_id`(nullable, para facturar) | Procedimiento clínico; si tiene `item_id` se cobra como servicio. |
| `vet_specialties` (catálogo) | name | Especialidades. |
| `reminders` (motor recordatorios) | `person_id`, `pet_id`, type(vaccine/antiparasitic/appointment), `due_date`, status, channel, sent_at, template_name, payload, attempts, last_error | Transversal (sirve también para farmacia: crónicos). |

**Extensiones a tablas existentes (aditivas, idempotentes):**
- `users` += `specialty_id`, `clinic_role_id` (el vet que atiende).
- `hotel_rents` += `pet_id` (nullable) — si extendemos Hotel para hospedaje.
- `persons` += `birthdate`, `gender` (opcional, solo si lo quieren del dueño).
- `configurations` += `is_veterinary`.

Convenciones: modelos extienden `ModelTenant`; migraciones en `database/migrations/tenant/` con guards idempotentes; índices sin FK dura (dirección reciente del repo); `establishment_id` en tablas operativas.

---

## 3. Las 8 features — detalle de cómo queda cada una

### 1) Categorías + Reporte por Área 🟡 construir reporte
- **Categorías ya existen** (tabla `categories`, `items.category_id`, CRUD `CategoryController`). Categorizar el catálogo = **data entry** (ya tenemos el mapeo de San Francisco a 5 áreas listo para validar).
- **Reporte por Área:** los reportes actuales (`ReportSaleConsolidated`) agrupan por **producto**, no por categoría. → **Construir "Ventas por Área"** clonando `ReportSaleConsolidated` y cambiando el `groupBy` a `category_id` + subtotales por área. Toda la infra de filtros (mes/semana/rango), export Excel/PDF, ya está.
- **Queda:** reporte con selector de período, agrupado por las 5 áreas, con subtotales — idéntico al Excel del cliente. Exportable.

### 2) Ficha Cliente + Mascota 🔴 construir (núcleo)
- **Dueño = `Person`** (reutiliza clientes, ya enlaza ventas/puntos). **Mascota = `vet_pets`** nueva (especie/raza/sexo/peso/foto).
- Pantalla "Mascotas" (CRUD) + en la ficha del cliente, sus mascotas. **Historial unificado** por mascota: timeline de compras + vacunas + citas + consultas (reuniendo de `documents`, `vet_vaccination_records`, `vet_appointments`, `vet_medical_consultations`).
- **Queda:** desde un cliente ves sus mascotas; desde una mascota ves todo su historial.

### 3) Recordatorios WhatsApp 🟡 infra existe, construir motor
- **Existe:** WhatsApp Cloud API oficial (`WhatsAppCloudApi`, config por tenant en `companies`) + scheduler multi-tenant (`tasks:run` lee `clients.tasks` y ejecuta commands por tenant a una hora).
- **Construir:** tabla `reminders` + command `reminders:dispatch` (registrado como Task del tenant, corre diario) que envía por WhatsApp los vencidos. **Agregar soporte de `template`** a `WhatsAppCloudApi` (los mensajes proactivos EXIGEN plantillas aprobadas por Meta).
- **Generación:** al vender antipulgas → `reminder` a +30 días; al registrar vacuna con `next_dose_date` → `reminder`; al agendar cita → `reminder` el día previo.
- **Queda:** "A Firulais le toca su antipulgas / su vacuna Quíntuple / tiene cita mañana" automático.
- ⚠️ Ver Riesgos (templates Meta, onboarding por tenant, costo).

### 4) Carné de vacunación digital 🔴 construir (sobre #2)
- **`vet_vaccination_records`** por mascota. Al vender una vacuna (ítem) eligiendo la mascota → se crea el registro (con lote, fecha, próxima dosis, vet) y se enlaza a la venta.
- **Carné = PDF/pantalla** que lista las vacunas de la mascota (reusa DomPDF). Opcional: exponerlo en la **app móvil** (módulo `MobileApp` existe).
- **Queda:** carné digital imprimible/compartible + alimenta los recordatorios de próxima dosis.

### 5) Agenda de citas 🔴 construir
- **`vet_appointments` + `vet_doctor_schedules`**, por sucursal (`establishment_id`). Estados (reservada/atendida/no-show). Cita → puede generar la consulta (historia) y el recordatorio.
- **UI calendario:** NO hay componente reutilizable en el admin (el de los themes es jQuery legacy). → Incorporar **`@fullcalendar/vue3`** o un timeline propio.
- **Queda:** agenda por veterinario/sucursal, reserva, y al atender abre la historia clínica.

### 6) Limpieza de catálogo 🟢 script (ya tenemos el patrón)
- Dedup (como el dedup DIGEMID que ya hicimos) + quitar basura/test (`D`, `demoeeee`, duplicados de "Baño"/"Tratamiento"). Mapeo de San Francisco ya hecho.
- **Queda:** catálogo limpio y categorizado, base para el reporte por área.

### 7) Hospedaje / Guardería 🟡 extender Hotel
- **Módulo `Hotel` tiene el backend completo** (jaula=habitación con estados, estadía=rent, consumos, pagos, check-in/out/extender). Pero: su **capa Vue está desconectada** (comentada en `app.js`) y **no tiene calendario** (solo grilla por estado).
- **Extender** (no clonar): `hotel_rents += pet_id`, re-habilitar y portar su Vue a Vue3/EP2, y **construir agenda por fechas** (reserva anticipada + anti-solapamiento — el gap más grande). Renombrar UI (Habitación→Jaula, Huésped→Mascota).
- **Queda:** reservar/registrar estadías de mascotas con consumos y cobro integrado.

### 8) Fidelización / puntos 🟢 REUTILIZAR (¡ya existe!)
- **El sistema de puntos al CLIENTE ya está construido y funcional:** `PointSystemService`, `persons.accumulated_points`, config `enabled_point_system` (X soles → Y puntos), acumulación automática al vender, canje de productos por puntos en POS. **Solo hay que activarlo** por tenant.
- **Opcional a construir:** catálogo de "premios" canjeables (baño gratis, consulta) clonando el molde `seller_reward`/`seller_reward_redemption` → `customer_reward`; y/o ledger de movimientos para historial de puntos del cliente.
- **Queda:** el dueño acumula puntos por sus compras y canjea premios/productos.

---

## 4. Recomendaciones adicionales (mías, para analizar)

1. **Historial unificado por mascota** (timeline) — alto valor, bajo costo (reúne data que ya existe + las nuevas).
2. **Reporte "Mascotas con vacuna/antiparasitario vencido"** — lista accionable para llamar/recordar (convierte el carné en ventas).
3. **Consentimientos/autorizaciones firmados** (cirugía, anestesia) — adjuntos a la cita/consulta (`appointment_documents`).
4. **Comisiones por veterinario** — el sistema YA tiene módulo de comisiones; aplicarlo a servicios por vet.
5. **Etiqueta/QR de jaula** en hospedaje (identificación rápida).
6. **Cumpleaños de mascota** → saludo/recordatorio WhatsApp (marketing de fidelización).
7. **Carné en la app móvil** del dueño (el módulo MobileApp existe) — diferencial fuerte.
8. **Alertas de vencimiento de vacunas en stock** (cadena de frío) — reutiliza el sistema FEFO/lotes existente.

---

## 5. Ajustes a código existente (qué se toca)

| Archivo / área | Ajuste | Riesgo |
|---|---|---|
| `configurations` (+modelo) | columna `is_veterinary` + métodos `isVeterinary()` | bajo (aditivo) |
| `ClientController@tables` / `form.vue` (system clients) | giro "Veterinaria" + bundle `group_veterinary` | bajo |
| `sidebar.blade.php` | menú Vet gateado por `is_veterinary` | bajo |
| `resources/js/app.js` | registrar componentes Vet (+ re-habilitar Hotel) | bajo |
| `WhatsAppCloudApi` | agregar `type:'template'` + subir versión API | medio |
| Flujo de venta (POS/SaleNote/Document) | hook opcional: al vender vacuna con mascota → crear `vaccination_record` + `reminder`; al vender antipulgas → `reminder` | medio (no romper venta normal; todo opcional + gated) |
| `users` | `specialty_id`, `clinic_role_id` | bajo |
| `hotel_rents` + Hotel Vue | `pet_id` + portar Vue a Vue3 | medio |

**Regla de oro:** ningún ajuste cambia el comportamiento para farmacias. Todo lo vet va detrás de `is_veterinary` o es aditivo/opcional.

---

## 6. Roadmap por fases (orden sugerido)

- **F0 — Andamiaje:** módulo `Vet` + flag `is_veterinary` + giro + menú gateado. (Verificable: prender Veterinaria en un tenant → aparece el menú.)
- **F1 — Mascotas + Dueño:** `vet_pets` + CRUD + mascotas en la ficha del cliente. Limpieza/categorización del catálogo (#6, #1 categorías).
- **F2 — Carné de vacunas:** `vet_vaccination_records` + registro al vender + PDF.
- **F3 — Recordatorios:** tabla `reminders` + `reminders:dispatch` + templates WhatsApp (antipulgas + vacuna).
- **F4 — Agenda de citas:** `vet_appointments` + `vet_doctor_schedules` + calendario.
- **F5 — Historia clínica:** `vet_medical_consultations` + diagnósticos/procedimientos + historial unificado.
- **F6 — Hospedaje:** extender Hotel (pet_id + Vue + agenda).
- **F7 — Reportes vet + Fidelización:** "Ventas por Área", "vacunas vencidas", comisiones por vet; activar puntos-cliente (+ premios opcional).

Cada fase es desplegable de forma incremental (todo gated; no afecta farmacias).

---

## 7. Riesgos a tener en cuenta

1. **Plantillas WhatsApp (Meta)** — mensajes proactivos exigen templates aprobados (categoría "Utility"); aprobación toma tiempo, rechazan copy promocional. `WhatsAppCloudApi` hoy NO soporta templates → hay que agregarlo.
2. **API WhatsApp v14 obsoleta** — subir a v19+ antes de prod.
3. **Onboarding WhatsApp por tenant** — cada veterinaria necesita su `ws_api_phone_number_id` + token en `companies` (hoy manual).
4. **Costo/rate-limits WhatsApp** — se cobra por conversación iniciada por negocio; tiers por calidad del número; opt-out obligatorio.
5. **Queue en `sync`** — envíos masivos bloquean; conviene worker de cola para recordatorios.
6. **Hotel Vue desconectada** — re-habilitarla implica portar componentes Vue2→3 (puede traer ajustes EP1→EP2).
7. **Calendario de agenda** — no hay reutilizable; incorporar `@fullcalendar/vue3` (dependencia nueva).
8. **NO resucitar el clínico viejo** — era para clínica humana, mal estructurado y eliminado; el vet es greenfield.

---

## 12. Tablas comparativas (WhatsApp + Calendario)

### 12.1 WhatsApp / canales de notificación

> Recordá: **WhatsApp es UN canal**. El **backbone gratis real = Email + Push**. WhatsApp suma alcance pero (oficial) cuesta.

| Herramienta | Costo | Oficial / Baneo | Hosting | Beneficios | Contras |
|---|---|---|---|---|---|
| **WhatsApp Cloud API (Meta oficial)** | **Por mensaje** (utility ~fracción de centavo–céntimos PE) · setup $0 | ✅ Oficial, **sin riesgo de baneo** | Meta (nube) | Confiable, compliant, plantillas, escalable, per-tenant limpio (token por tenant en `companies`) | Cuesta por mensaje; requiere cuenta Meta + número verificado + plantillas aprobadas |
| **`netflie/whatsapp-cloud-api` (paquete PHP)** | Paquete **$0** (la API debajo = Meta, pago) | = oficial | — | Implementa el camino oficial en Laravel sin armar HTTP a mano; maneja templates/webhooks | No es canal aparte: es la **lib para usar el oficial** |
| **Evolution API (self-hosted)** | **$0/mensaje** · solo VPS (~$0–5/mes) | ⛔ **No oficial → riesgo de baneo** | Vos o el tenant | Gratis por mensaje, ilimitado, panel visual, Docker en min | Viola ToS Meta (banea el número); mantenés uptime; **N instancias** en multi-tenant |
| **whatsapp-web.js / Baileys (DIY)** | **$0/mensaje** · solo VPS | ⛔ No oficial → riesgo de baneo | Vos | Control total, base de los gateways | Hay que programar + mantener; mismo riesgo de baneo |
| **BSP intermediario** (Twilio, Wati, 360dialog, Gupshup) | Costo Meta **+ markup** (+ a veces fee mensual) | ✅ Oficial | Proveedor | Fácil, soporte, dashboards, onboarding asistido | **Más caro** que Meta directo |
| **Gateway QR gestionado local** (apisperu, etc.) | **Suscripción mensual barata** (S/), $0/mensaje | ⛔ **No oficial → baneo** (modelo QR/device) | El proveedor (no vos) | **Barato + fácil** (QR, sin verificación Meta ni plantillas); mismo proveedor que ya usás (RUC/DNI); manda bulk + PDFs; **probablemente = el `API_WHATSAPP` que ya manda facturas** | Riesgo de baneo (peor con recordatorios masivos); dependés de su uptime; un tercero tiene tu sesión; sin SLA |
| **Email** *(no-WhatsApp)* | **$0 real** | n/a (sin baneo) | Tu SMTP | Ya configurado, gratis, confiable | Menor apertura que WhatsApp |
| **Push móvil FCM** *(no-WhatsApp)* | **$0 real** | n/a | Firebase free tier | Ya en la app Flutter, buena UX | Requiere que el dueño tenga la app |

**Recomendación:** default **Email + Push ($0)**; **WhatsApp oficial** (vía `netflie/whatsapp-cloud-api`) como opción premium per-tenant; gateway self-hosted solo "a riesgo del tenant", nunca operado por nosotros.

### 12.2 Calendario / agenda

| Herramienta | Licencia | Costo | Columnas-por-vet | Vue 3 | Theming a tus tokens | Veredicto |
|---|---|---|---|---|---|---|
| **vkurko Event Calendar** | MIT | **$0** (recursos+timeline incl.) | ✅ gratis | wrapper (~20 líneas) | ✅ variables CSS `--ec-*` (fácil) | 🥇 **Lean** (theming) |
| **DayPilot Lite** | Apache 2.0 | **$0** (recursos vertical incl.) | ✅ gratis | ✅ nativo | ⚠️ CSS propio (reescribir) | 🥈 Plan B |
| **FullCalendar** | MIT core / Scheduler pago | Core $0; **resource ~$480/año** | ⚠️ **pago** | ✅ | ✅ | ❌ recurso pago |
| **Schedule-X** | Core libre / resource pago | Core $0; **resource pago** | ⚠️ **pago** | ✅ nativo | ✅ | ❌ recurso pago |
| **Toast UI Calendar** | MIT | **$0** | ❌ (colores, no columnas) | wrapper | medio | Solo sin columnas-por-vet |
| **vue-cal** | MIT | **$0** | ⚠️ parcial (split-days) | ✅ | medio | Liviano, recurso limitado |
| **DHTMLX Scheduler** | GPL / comercial | GPL "gratis" / comercial pago | ✅ (Units) | wrapper | medio | ❌ GPL **obliga a abrir tu código** |
| **Bryntum Scheduler** | Comercial | 💲💲 caro | ✅ | ✅ | ✅ | ❌ solo industrial |
| **Google Calendar API** | — | API $0 (cuota) | n/a (externo) | n/a | n/a | ❌ **NO como fuente** (datos afuera de tu BD) |

**Recomendación:** **vkurko** (theming + columnas-por-vet gratis), **DayPilot Lite** plan B. Decisión final en spike F4. **Costo $0.**

---

## Resumen ejecutivo

- **Ya existe (reutilizar):** puntos-cliente, categorías, diagnósticos CIE-10, servicios facturables (ítems ZZ), backend de Hospedaje (Hotel), scheduler multi-tenant, WhatsApp Cloud API, multi-sucursal.
- **Construir nuevo (núcleo vet):** Mascotas, Carné de vacunas, Citas+Agenda, Historia clínica, motor de Recordatorios, reporte "Ventas por Área".
- **Todo activable solo con el giro "Veterinaria"** — cero impacto en farmacias.
- **Clínica humana = fase posterior:** el mismo módulo `Vet`/`Clinic` con el paciente como persona (en vez de mascota), reutilizando el 80%.

---

## 8. Costos / gastos de por medio

| Concepto | ¿Cuesta? | Detalle |
|---|---|---|
| **WhatsApp Cloud API (Meta)** | 💲 **SÍ, recurrente (bajo)** | Único costo externo real. Meta cobra **por mensaje** de plantilla (utility) iniciado por el negocio. Dentro de la ventana de 24h de atención al cliente = gratis; proactivo (recordatorio) = se paga. En Perú el rate de "utility" es bajo (céntimos por mensaje). San Francisco ≈ ~120 recordatorios/mes → **costo ínfimo (~pocos US$/mes)**. PERO: cada veterinaria necesita su **WhatsApp Business + número verificado + método de pago en Meta**. *(Confirmar tarifa vigente en el rate card de Meta para Perú — la pricing cambió a por-mensaje en 2025.)* |
| **Plantillas Meta** | Gratis (aprobación) | Aprobar templates no cuesta, pero **toma días** y rechazan copy promocional. |
| **FullCalendar (agenda)** | **Gratis** si usamos las vistas estándar (day/week/list, MIT). Solo el plugin "resource-timeline" (columnas por veterinario) es **pago** (~US$480/año). Se puede hacer la agenda sin él. |
| **Servidor / infra** | **$0 extra** | Mismo Docker. El motor de recordatorios usa el cron que ya existe. Worker de cola (si hace falta) corre en el mismo server. |
| **App móvil (carné)** | $0 extra | El módulo MobileApp ya existe. Si se quieren **push notifications** en vez de WhatsApp → Firebase (free tier generoso). |
| **Storage** (fotos mascota, PDFs carné/consentimientos) | Marginal | Disco del server existente. |
| **SMS (alternativa a WhatsApp)** | 💲 Más caro | No recomendado (per-SMS > WhatsApp). |
| **Desarrollo** | Tiempo | El costo real es horas de construcción (núcleo vet). |

**Resumen:** el único gasto externo recurrente es **WhatsApp** (bajo volumen = pocos US$/mes por veterinaria) y requiere setup en Meta. Todo lo demás = tiempo de desarrollo + infra que ya pagás. La agenda puede ser 100% gratis.

## 9. Detalles que faltan definir (input del cliente / negocio)

- **WhatsApp:** copy de las plantillas; quién crea la cuenta Meta por veterinaria; mecanismo de **consentimiento/opt-out**.
- **Catálogo de especies/razas:** ¿lista predefinida (seed) o texto libre?
- **Protocolo de vacunas:** qué vacunas y cada cuánto (para auto-calcular "próxima dosis") — ¿config o manual?
- **Intervalo antiparasitario:** ¿fijo 30 días o **por producto**? (Nexgard 30d vs Bravecto 90d) → conviene config por ítem.
- **Plan comercial:** ¿el giro "Veterinaria" es un **add-on pago** (tier)? (decisión de negocio).
- **Roles/permisos:** qué ve cada rol (veterinario / recepción / admin).
- **Agenda:** duración de cita, horarios por veterinario/sucursal, ¿cuántas sucursales?
- **Hospedaje:** precio por noche, tamaños de jaula/zonas.
- **Legal:** privacidad de datos del dueño + consentimiento WhatsApp.

## 10. Por dónde empezar (recomendación)

**Arrancar por F0 + F1, en paralelo con la limpieza/reporte — todo SIN costo externo:**

1. **F0 — Andamiaje** (módulo `Vet` + flag `is_veterinary` + giro + menú gateado). Es la base; valida el mecanismo del giro. Riesgo bajo, $0.
2. **F1 — Mascotas + Dueño** (`vet_pets` + CRUD + mascotas en la ficha del cliente). Es la entidad de la que cuelga TODO (carné, citas, historia).
3. **En paralelo (quick win, $0):** categorizar el catálogo de San Francisco (mapeo ya hecho) + **reporte "Ventas por Área"** → valor inmediato y visible para el cliente, sin depender de nada externo.

**Dejar para después** (cuando esté el setup de Meta): F3 Recordatorios WhatsApp. Y la agenda (F4) cuando definamos si va con FullCalendar gratis.

> Lógica: F0+F1 no cuestan nada, son la fundación, y dan algo usable rápido (registrar mascotas, ver historial por cliente). El único gasto (WhatsApp) recién aparece en F3, y para entonces ya tenés mascotas + carné que lo alimentan.

---

## 11. Alternativas GRATIS / más económicas (investigado)

### Notificaciones / recordatorios — backbone $0 real = email + push; WhatsApp = costo bajo VARIABLE

> Corrección honesta de una versión anterior que decía "$0 total". WhatsApp NO es $0.

| Canal | Costo | Estado | Veredicto |
|---|---|---|---|
| **Email** | **$0 real** | ✅ SMTP/Mailables configurados | **Backbone gratis.** Menor apertura, pero self-hosted de verdad. |
| **Push móvil (FCM)** | **$0 real** | ✅ App Flutter ya tiene Firebase Messaging | **Backbone gratis.** Requiere que el dueño tenga la app. |
| **WhatsApp Cloud API (oficial)** | 💲 **bajo pero real** | A construir (templates) | Desde **1-jul-2025** Meta cobra **por mensaje**; el recordatorio en frío (utility) **se paga** (fracción de centavo–centavos en LatAm). **Gratis solo** dentro de la **ventana de servicio de 24h** iniciada por el cliente (servicio gratis desde 1-nov-2024). |
| **WhatsApp self-hosted** (Baileys/whatsapp-web) | "$0" engañoso | Gateway `API_WHATSAPP` en el repo (manda PDFs) | ⛔ **NO usar como canal core.** Viola ToS de Meta → **banea el número**. Recordatorios proactivos masivos = alto riesgo. Un día la clínica se queda sin recordatorios y con el número muerto. |

**Reencuadre honesto:**
- **Backbone $0 real = Email + Push** (los únicos self-hosted de verdad).
- **WhatsApp = costo bajo VARIABLE, no cero, y solo por la vía OFICIAL.** Diseñar para que muchas confirmaciones caigan en la **ventana de servicio gratuita de 24h** (cliente escribe primero / responde) → el costo tiende a casi-cero, pero **no es "$0 garantizado"**.
- **El gateway self-hosted NO va como canal del producto** (baneo inaceptable para un SaaS comercial). Si se ofreciera, sería opt-in explícito "a tu riesgo, no oficial", nunca default.
- Motor "channel-agnostic" (columna `channel` en `reminders`): **default Email + Push (gratis)**; **WhatsApp oficial = opción premium por tenant** (con su costo + onboarding Meta).
- ⚠️ Verificar la **tarifa utility exacta para Perú** en el rate card vigente de Meta (cambia seguido).

**Implementación WhatsApp oficial (PHP):** usar el paquete **`netflie/whatsapp-cloud-api`** (maneja templates + webhooks) en vez de armar el HTTP a mano — más limpio que extender `WhatsAppCloudApi` desde cero.

**Self-hosted "a riesgo del tenant" (NO operado por nosotros):** como el motor es channel-agnostic, un tenant que insista en WhatsApp gratis puede apuntar el canal a **su propio gateway** (Evolution API / whatsapp-web.js en su número). Matiz real: el riesgo de baneo **escala con el spam** — recordatorios de vacuna (bajo volumen, opt-in, alta respuesta) son **menos riesgosos** que marketing masivo, así que para una clínica chica es defendible *a su riesgo*. Pero **nunca como canal que el producto hostea/garantiza** (un baneo mata el número-negocio del cliente y nos hace responsables).

**UX a adoptar (cualquier canal):** mensaje que cierra con **"Responde 1=Confirmar / 2=Reprogramar"** + **webhook** que actualiza el estado de la cita. Bonus en API oficial: la respuesta del cliente **abre la ventana de servicio de 24h** → los follow-ups salen **gratis**.

### Agenda / calendario — 100% GRATIS (evitar FullCalendar Premium)

No hace falta el plugin pago. **OJO:** en Schedule-X y FullCalendar la **vista de recursos (columnas por veterinario) es de pago**. Las dos que dan columnas-por-recurso **gratis**:
- **DayPilot Lite** (Apache 2.0) — paquete Vue nativo `@daypilot/daypilot-lite-vue`, `viewType="Resources"` + `:columns` con tus veterinarios. Tiene tutoriales backend PHP/MySQL. **← recomendada (Vue nativo, encaja con el patrón de islas).**
- **Event Calendar (vkurko/calendar)** (MIT) — API tipo FullCalendar, vista de recursos + timeline gratis, ~37kb sin deps. Se consume vía JSON. **← alternativa MIT si prefieren API FullCalendar.**
- Evitar: Schedule-X (resource pago), FullCalendar Scheduler (~$480/año), DHTMLX (GPL → obliga a abrir código), Bryntum (caro).

**❌ Google Calendar API como fuente de las citas: NO.** Las citas deben vivir en `vet_appointments` (ligadas a mascota/dueño/vet/historia/venta). Google Calendar = datos afuera + 2 fuentes de verdad (sync hell) + OAuth-por-tenant (más overhead, verificación de app, tokens que caducan — ya lo sufrimos con GSC). El motor de recordatorios **lee NUESTRA BD**, no un calendario externo. Único uso válido (opcional, futuro): **export one-way** de nuestras citas al Google Calendar del vet (para verlas en el celular), pero la **fuente de verdad sigue siendo la BD**.

**Recomendación de librería (matizada tras debate):** el factor decisivo **NO es el wrapper Vue** (~20 líneas una vez) sino el **theming**. DayPilot Lite trae su propio CSS (`calendar_default_*`, callback `onBeforeEventRender`) que **no consume nuestros tokens** → reescribir CSS para alinear con Element Plus/Cuba + paleta Carbón&vino. **vkurko (Event Calendar) usa variables CSS (`--ec-*`)** → mucho más dócil a nuestro design system token-driven; **puede ganar** dado cuánto cuidamos el diseño. Matiz a favor de DayPilot: `onBeforeEventRender` da control **programático por-evento** (colorear por estado/área). **Decisión final = spike en F4** que pese: (1) **theming con nuestros tokens [eje decisivo]**; (2) comportamientos en Lite (arrastrar-reprogramar, redimensionar, modal de edición — la vertical por-vet alcanza; el timeline horizontal vive cerca de Pro); (3) riesgo de vendor: DayPilot = comercial con Lite como embudo a Pro (gating futuro) vs vkurko = MIT independiente (bus-factor 1 mantenedor). **Costo: $0 en ambas.**

### Resumen de costos REAL (corregido tras debate)
- **Agenda:** **$0** (DayPilot Lite o vkurko, ambas libres con columnas-por-vet).
- **Recordatorios backbone:** **$0** con **email + push** (self-hosted de verdad).
- **WhatsApp:** **costo bajo VARIABLE, no cero**, y **solo vía oficial** (Cloud API). Optimizable hacia casi-cero con la ventana de servicio de 24h, pero **no garantizado $0**. Nunca por gateway no oficial (baneo).
- **Resto:** $0 (infra existente).
- → **$0 en agenda + email + push; WhatsApp = costo bajo no-cero como opción premium.** No venderlo internamente como "$0 garantizado".
</content>
