#!/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()