92 lines
4.6 KiB
Markdown
92 lines
4.6 KiB
Markdown
# 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 | **clinica.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: clinica.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`.
|