Files
SKEEN-Proyecto/migracion/sync_odoo_to_wacrm.py
Consultoría Alcaraz Salazar a718592291 Initial commit: SKEEN Derma Experts - Sistema Integral de Gestión Clínica
- Frontend React (SKEEN Brand) con Vite, TypeScript, Tailwind
- Frontend Homenest (versión alternativa)
- Módulos Odoo 17 custom (citas, pacientes, monedero, pagos, ventas, inventario, whatsapp)
- WACRM fork (Next.js 16 + Supabase)
- Hermes + Bridge + Skills (Qwen3.6 via Nan Builders)
- Scripts de migración y operación
- Documentación extensiva en docs/
2026-07-20 07:44:23 +00:00

126 lines
3.7 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Sincroniza pacientes de Odoo → WACRM (Supabase self-hosted).
Inserta/actualiza contactos en la tabla public.contacts.
Uso:
source /root/odoo-venv/bin/activate && python3 /root/migracion/sync_odoo_to_wacrm.py
"""
import sys
from pathlib import Path
ODOO_PATH = Path('/root/skeen-odoo')
sys.path.insert(0, str(ODOO_PATH))
import odoo
from odoo import api, SUPERUSER_ID
import psycopg2
from psycopg2.extras import execute_values
# Configuración de Supabase / WACRM
SUPABASE_HOST = 'localhost'
SUPABASE_PORT = 6543
SUPABASE_USER = 'postgres.your-tenant-id'
SUPABASE_PASSWORD = '8bbf201d9d60488a1e86e5396b31e22d'
SUPABASE_DB = 'postgres'
WACRM_ACCOUNT_ID = 'a2dc0db3-dea0-4bd8-8733-1d62975c5f89'
WACRM_OWNER_USER_ID = '00000000-0000-0000-0000-000000000001'
def get_odoo_env(database='skeen_odoo'):
odoo.tools.config.parse_config(['-c', '/root/skeen-odoo/odoo.conf'])
db = odoo.sql_db.db_connect(database)
cr = db.cursor()
return api.Environment(cr, SUPERUSER_ID, {}), cr
def get_wacrm_connection():
return psycopg2.connect(
host=SUPABASE_HOST,
port=SUPABASE_PORT,
user=SUPABASE_USER,
password=SUPABASE_PASSWORD,
dbname=SUPABASE_DB,
)
def normalize_phone(phone):
digits = ''.join(c for c in (phone or '') if c.isdigit())
if digits and not digits.startswith('52') and len(digits) == 10:
digits = '52' + digits
return digits
def sync_contacts(limit=None):
env, cr = get_odoo_env()
try:
domain = [('is_patient', '=', True), ('phone', '!=', False), ('phone', '!=', '')]
partners = env['res.partner'].sudo().search(domain)
if limit:
partners = partners[:limit]
rows = []
for p in partners:
phone = normalize_phone(p.phone)
if not phone:
continue
rows.append((
WACRM_OWNER_USER_ID,
phone,
p.name or 'Paciente',
p.email or '',
'', # company
'', # avatar_url
WACRM_ACCOUNT_ID,
))
if not rows:
print('No hay pacientes para sincronizar')
return
conn = get_wacrm_connection()
try:
with conn.cursor() as cur:
# UPSERT por (account_id, phone_normalized)
execute_values(cur, """
INSERT INTO public.contacts
(user_id, phone, name, email, company, avatar_url, account_id)
VALUES %s
ON CONFLICT (account_id, phone_normalized) WHERE phone_normalized <> ''
DO UPDATE SET
name = EXCLUDED.name,
email = EXCLUDED.email,
company = EXCLUDED.company,
avatar_url = EXCLUDED.avatar_url,
user_id = EXCLUDED.user_id,
updated_at = NOW()
RETURNING id, phone
""", rows, page_size=1000)
result = cur.fetchall()
phone_to_id = {phone: str(cid) for cid, phone in result}
# Actualizar referencia en Odoo
for p in partners:
phone = normalize_phone(p.phone)
if phone in phone_to_id:
p.write({
'wacrm_synced': True,
'wacrm_contact_id': phone_to_id[phone],
})
conn.commit()
print(f'Sincronizados {len(rows)} contactos a WACRM')
finally:
conn.close()
finally:
cr.commit()
cr.close()
if __name__ == '__main__':
sync_contacts()