Files
SKEEN-Proyecto/docs/segunda-instancia.md
Consultoría Alcaraz Salazar 582c267ec0 segunda instancia white-label (clinica2) + fix de orden de menus en instalacion limpia
Infra (todo convive en la misma VPS, mismo addons_path read-only):
- infra/clinica2/: odoo.conf (puerto 8070, db clinica2_odoo, data_dir
  propio), odoo-clinica2.service (sin env vars de WACRM/Supabase/Hermes),
  nginx-vhost (80 con server_name clinica2.consultoria-as.com + 8880 LAN,
  /api/odoo -> 8070, /wacrm/ cortado con 403), postinstall.py (brand neutro,
  menu WACRM vacio, admin con password propio y must_change_password)
- docs/segunda-instancia.md: mapa completo de la instalacion, pasos para
  reproducir (instancia 3+), pendiente del hostname en dashboard del tunel
  (remotamente administrado), aislamiento de datos escenario B
- frontend/public/brand/: logos SVG neutros + favicon para la instancia 2

Fix de menus (aplica a todas las instalaciones limpias, una sola pasada):
- menu_skeen_root se mueve a skeen_pacientes (modulo raiz de la jerarquia);
  en bases existentes se transfirio el ownership del xmlid (ir_model_data)
  asi actualizar no duplica el menu
- menu_skeen_citas (padre) se declara en skeen_citas/views/menus.xml que
  carga antes que bloqueo/lista_espera; menu_views.xml conserva las entradas
  con action (cargan despues de cita_views, donde se define la accion)
- referencias actualizadas: pacientes(catalogos/recetas), monedero, ventas,
  inventario, visitas -> skeen_pacientes.menu_skeen_root

Verificacion: produccion (skeen_odoo) actualizada sin duplicar menus y API
intacta; instalacion limpia clinica2_odoo 9 modulos OK; 15/15 tests
end-to-end (brand neutro, login admin, WACRM oculto+403, datos vacios)
2026-10-08 00:44:30 +00:00

92 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Segunda instancia white-label (sin branding SKEEN)
Segunda clínica sobre el mismo código y la misma VPS. La marca no vive en el
código: sale del parámetro `skeen.clinic.brand` (ver `GET /skeen/frontend/v1/brand`),
así que esta y futuras instancias son solo infra + config.
## Mapa de la instalación
| Componente | SKEEN (instancia 1) | Clínica 2 (instancia white-label) |
|---|---|---|
| Odoo HTTP | 8069 | **8070** |
| Odoo longpolling | 8072 | **8073** |
| Base de datos | `skeen_odoo` | **`clinica2_odoo`** |
| Conf | `/root/skeen-odoo/odoo.conf` | **`/root/clinica2-odoo.conf`** |
| Systemd | `odoo-skeen.service` | **`odoo-clinica2.service`** |
| Frontend | `/var/www/skeen-frontend` | **`/var/www/clinica2-frontend`** |
| Nginx | vhost `skeen-crm` (80) | **vhost `clinica2` (80 + 8880)** |
| Acceso LAN | http://192.168.10.114 | **http://192.168.10.114:8880** |
| Acceso público | skeen.consultoria-as.com | **clinica2.consultoria-as.com (pendiente: dashboard del túnel)** |
| WhatsApp (WACRM) | integrado | **oculto + bloqueado (escenario B)** |
`addons_path` se comparte (read-only): `/root/skeen-odoo/addons`. Un solo
código, N bases de datos.
## Cómo se levantó (orden de pasos)
Los archivos canónicos están en `infra/clinica2/`:
1. `odoo.conf` — copia del de SKEEN con `db_name=clinica2_odoo`, `http_port=8070`,
`longpolling_port=8073`, `data_dir=/var/lib/odoo-clinica2`.
2. Crear la base (el rol `skeen` no tiene CREATEDB; se crea como `postgres`):
`CREATE DATABASE clinica2_odoo OWNER skeen ...`
3. Instalar módulos limpio (sin demo):
`odoo-bin -c /root/clinica2-odoo.conf -d clinica2_odoo --without-demo=all --init=skeen_whatsapp,skeen_chat,skeen_visitas --stop-after-init --no-http`
(skeen_whatsapp arrastra citas/pacientes/ventas/pagos/monedero; visitas
arrastra inventario).
4. `postinstall.py` — brand neutro (`skeen.clinic.brand`), menú WACRM vacío
para todos (`skeen.menu_roles`), password de admin propio +
`must_change_password`, empresa renombrada.
5. `systemctl enable --now odoo-clinica2`.
6. `nginx-vhost` → `/etc/nginx/sites-enabled/clinica2` + `nginx -t && reload`.
7. Frontend: mismo build de SKEEN (`rsync -a dist/ /var/www/clinica2-frontend/`)
más `public/brand/` (logos SVG neutros + favicon, versionados en el repo).
## Pendiente para acceso público (único paso manual)
El túnel cloudflared corre con `--token` (remotamente administrado): el
`config.yml` local NO aplica. En el dashboard de Cloudflare (Zero Trust →
Networks → Tunnels → f2517233…) agregar el ingress:
```yaml
- hostname: clinica2.consultoria-as.com
service: http://localhost:80
```
El vhost nginx ya escucha en el 80 con ese `server_name`; al agregar el
hostname el túnel enruta solo. El 8880 queda como acceso LAN permanente.
## Aislamiento de datos (escenario B: sin WhatsApp)
- Sin `SUPABASE_URL` / `WACRM_API_*` / `HERMES_BRIDGE_URL` en la unit systemd
(el backend respondería "Falta configuración").
- Aun así, el backend tiene fallback a `localhost:3000`; por eso el vhost
nginx corta `/api/odoo/skeen/frontend/v1/wacrm/` con `return 403;` — doble
candado, la instancia 2 no puede leer ni escribir las conversaciones de
SKEEN aunque alguien llame la API a mano.
- Menú WACRM oculto para todos los roles vía matriz (`/wacrm/*: []`).
Para activar WhatsApp en la instancia 2 (escenario A) se necesita: número
propio de WhatsApp Business + decisión de WACRM multi-clínica (estimar aparte).
## Fix de menús que esta fase destapó (aplica a TODAS las instancias)
Las vistas XML referenciaban `skeen_citas.menu_skeen_root`, pero `skeen_citas`
depende de `skeen_pacientes`: en instalación limpia de una sola pasada el
xmlid aún no existe y la carga falla (la base de SKEEN se construyó por fases
y por eso nunca explotó). Se movió el menú raíz a `skeen_pacientes` (módulo
raíz de la jerarquía) y todas las referencias apuntan a
`skeen_pacientes.menu_skeen_root`. En bases existentes se transfirió el
ownership del xmlid (`UPDATE ir_model_data SET module='skeen_pacientes' …`),
así actualizar no duplica el menú. Mismo tratamiento para el menú padre de
Citas (`skeen_citas/views/menus.xml` carga antes que bloqueos/lista de espera).
## Operación habitual
- Logs: `tail -f /tmp/odoo2.log` (instancia 2) vs `/tmp/odoo.log` (SKEEN).
- Ambas instancias comparten código: un `git pull` + rebuild afecta el build
de ambas solo si se vuelven a copiar los `dist/` (cada uno tiene el suyo).
- Para una tercera clínica: repetir pasos 1–7 con `clinica3` (puertos 8074/8075,
db `clinica3_odoo`, vhost propio) y setear su brand desde
Configuración → Clínica o con `PUT /brand`.