#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Importador rápido de pacientes SKEEN a Odoo usando legacy_id como clave única.""" import csv 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 DATA_DIR = Path('/root/migracion/datos') def normalize_bool(v): return str(v).lower() in ('1', 'true', 'si', 'sí') def main(): odoo.tools.config.parse_config(['-c', '/root/skeen-odoo/odoo.conf']) db = odoo.sql_db.db_connect('skeen_odoo') cr = db.cursor() env = api.Environment(cr, SUPERUSER_ID, {}) Partner = env['res.partner'].sudo() Tag = env['skeen.patient.tag'].sudo() Employee = env['hr.employee'].sudo() # Cachés en memoria existing_legacy = {p.legacy_id: p.id for p in Partner.search([('legacy_id', '!=', False)]) if p.legacy_id} doctor_cache = {} tag_cache = {} def get_or_create_doctor(name): name = ' '.join(str(name).split()) if not name: return False if name in doctor_cache: return doctor_cache[name] clean = name.lower().replace('dra.', '').replace('dr.', '').replace('dr ', '').replace('dra ', '').strip() doctor = Employee.search(['|', ('name', 'ilike', name), ('name', 'ilike', clean)], limit=1) if not doctor: doctor = Employee.create({'name': name}) doctor_cache[name] = doctor return doctor def get_tag(name): if name in tag_cache: return tag_cache[name] tag = Tag.search([('name', '=', name)], limit=1) if not tag: tag = Tag.create({'name': name}) tag_cache[name] = tag.id return tag.id rows = [] with open(DATA_DIR / 'pacientes.csv', newline='', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: rows.append(row) print(f'Importando {len(rows)} pacientes...') count = 0 skipped = 0 batch = [] BATCH_SIZE = 500 for row in rows: legacy_id = (row.get('legacy_id') or '').strip() name = ' '.join(filter(None, [ row.get('nombre', ''), row.get('apellido_paterno', ''), row.get('apellido_materno', '') ])).strip() phone = (row.get('telefono') or '').strip() if not name or not phone: skipped += 1 continue if legacy_id and legacy_id in existing_legacy: skipped += 1 continue vals = { 'name': name, 'phone': phone, 'email': row.get('email', ''), 'is_patient': True, 'source': 'other', 'is_vip': normalize_bool(row.get('vip')), } if legacy_id: vals['legacy_id'] = legacy_id if row.get('fecha_nacimiento'): vals['birth_date'] = row.get('fecha_nacimiento') if row.get('sexo'): vals['gender'] = row.get('sexo') # Datos personales if row.get('lugar_nacimiento'): vals['birthplace'] = row.get('lugar_nacimiento') if row.get('empleo'): vals['occupation'] = row.get('empleo') if row.get('estado_civil'): vals['marital_status'] = row.get('estado_civil') if row.get('contacto_emergencia'): vals['emergency_contact'] = row.get('contacto_emergencia') if row.get('telefono_emergencia'): vals['emergency_phone'] = row.get('telefono_emergencia') if row.get('telefono_casa'): vals['home_phone'] = row.get('telefono_casa') if row.get('direccion'): vals['address_notes'] = row.get('direccion') if row.get('recomendado_por'): vals['referred_by'] = row.get('recomendado_por') if row.get('comentarios'): vals['patient_comments'] = row.get('comentarios') # Historia clínica try: vals['children_count'] = int(row.get('hijos', 0) or 0) except Exception: vals['children_count'] = 0 vals['is_pregnant'] = normalize_bool(row.get('embarazada')) vals['is_breastfeeding'] = normalize_bool(row.get('lactancia')) vals['uses_contraceptives'] = normalize_bool(row.get('anticonceptivos')) vals['kidney_problems'] = normalize_bool(row.get('problemas_rinon')) vals['back_pain'] = normalize_bool(row.get('problemas_espalda')) vals['heart_disease'] = normalize_bool(row.get('problemas_cardiacos')) vals['respiratory_problems'] = normalize_bool(row.get('problemas_respiratorios')) vals['blood_pressure'] = normalize_bool(row.get('alta_presion')) or normalize_bool(row.get('baja_presion')) vals['diabetes'] = normalize_bool(row.get('diabetes')) vals['thyroid'] = normalize_bool(row.get('hipertiroidismo')) or normalize_bool(row.get('hipotiroidismo')) vals['colitis'] = normalize_bool(row.get('colitis')) vals['constipation'] = normalize_bool(row.get('estrenimiento')) vals['liver_problems'] = normalize_bool(row.get('problemas_higado')) vals['surgeries'] = normalize_bool(row.get('cirugias')) vals['varicose_veins'] = normalize_bool(row.get('varices')) vals['migraine'] = normalize_bool(row.get('migrana')) vals['faints_with_needles'] = normalize_bool(row.get('desmaya_agujas')) if row.get('alergias'): vals['allergies'] = row.get('alergias') if row.get('medicamentos'): vals['current_medication'] = row.get('medicamentos') if row.get('tratamientos_previos'): vals['medical_history'] = row.get('tratamientos_previos') medico = get_or_create_doctor(row.get('medico_principal', '')) if medico: vals['primary_doctor_id'] = medico.id etiquetas = row.get('etiquetas', '').strip() if etiquetas: tag_ids = [get_tag(t) for t in etiquetas.split(',') if t.strip()] vals['tag_ids'] = [(6, 0, tag_ids)] batch.append(vals) if legacy_id: existing_legacy[legacy_id] = True if len(batch) >= BATCH_SIZE: Partner.create(batch) count += len(batch) batch = [] cr.commit() print(f' {count} pacientes creados') if batch: Partner.create(batch) count += len(batch) cr.commit() cr.commit() cr.close() print(f'Importación completada: {count} pacientes creados, {skipped} omitidos') if __name__ == '__main__': main()