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/
This commit is contained in:
125
migracion/sync_odoo_to_wacrm.py
Executable file
125
migracion/sync_odoo_to_wacrm.py
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user