"""Genera 05_construccion_clientes_intel/ (SQL CTAS de cada tabla de clientes_intel) y 00b_FUENTES_DE_CLIENTE.txt (mapa fuente-de-cliente -> consulta que la lee). Fuente de datos: scratchpad/intel_build.json (SQL de construccion capturado de INFORMATION_SCHEMA.JOBS) y scratchpad/intel_lineage.json (tablas implicadas). """ import json import os import textwrap DEST = "/mnt/c/Users/egutierrez/Desktop/linaje_customer_marts" PROJECT = "autingo-159109" builds = json.load(open("scratchpad/intel_build.json")) lin = json.load(open("scratchpad/intel_lineage.json")) # Tablas para las que escribimos el SQL de construccion: las del linaje de customer_marts # + las que leen fuentes de cliente/Salesforce. EXTRA = ["seg_vega_persona", "fact_campana_respuesta__sfnew"] want = sorted(set(lin["intel_involved"]) | set(EXTRA)) want = [t for t in want if t in builds] # solo las que tienen SQL capturado DESC = { "_persona_records": "IDENTIDAD DEL CLIENTE (nucleo). UNION de 7 fuentes -> normaliza DNI/NIE/CIF, email y " "telefono -> resuelve persona_id (FARM_FINGERPRINT de persona_key) con nivel de confianza. " "AQUI es donde se juntan TPV customers, customers web, OTR, Navision, citaprevia, users y " "Salesforce contacts_latest.", "dim_persona": "Dimension PERSONA final: una fila por persona_id, elegida desde _persona_records " "(prioriza el mejor registro por fuente/confianza) + banderas de contacto.", "dim_vehiculo": "Dimension VEHICULO: una fila por vehiculo (matricula/bastidor) desde TPV vehicles, OTR, " "citaprevia matriculas y calibrado de ano de matricula.", "map_persona_fuente": "Mapeo persona -> fuente(s) de origen (tpv/web/otr/navision/citaprevia/users/salesforce). " "Registra de que sistemas proviene cada persona.", "map_persona_vehiculo": "Mapeo N:N persona <-> vehiculo (quien conduce/posee que coche) desde OTR, TPV vehicleowner " "y citaprevia matriculas.", "map_persona_canal8": "Mapeo persona -> canal8 (canal de entrada del cliente).", "fact_transaccion": "Tabla de HECHOS de transaccion (linea/venta por persona). Base de los marts monetarios.", "fact_visita": "Tabla de HECHOS de visita (visitas del cliente al taller/tienda).", "fact_campana_respuesta": "HECHOS de respuesta a campanas: cruza envios/aperturas/clics/sms de Salesforce con personas.", "fact_campana_respuesta__sfnew": "Variante de fact_campana_respuesta con el esquema nuevo de Salesforce (email_sent/opened/clicked/sms).", "feat_cliente_persona": "Features agregadas por PERSONA (RFM, mix de canal, ticket medio, margen, recencia...).", "feat_cliente_vehiculo": "Features agregadas por VEHICULO.", "seg_cliente_360": "Segmentacion 360 del cliente (segmentos/clusters de negocio).", "seg_vega_persona": "Segmentacion VEGA por persona (contactabilidad/valor); lee fuentes de cliente para calcular " "disponibilidad de contacto.", "seg_cluster_persona": "Clustering de personas (asignacion de cluster) que alimenta la segmentacion.", "reco_acciones": "Recomendaciones / proxima mejor accion (NBA) por cliente.", "data_points_contacto": "Puntos de dato de contacto (email/telefono) consolidados y calidad por persona.", "_margen_rate_producto": "Tasa de margen por producto (auxiliar para features monetarias).", "_plate_year_calib": "Calibrado del ano a partir de la matricula (auxiliar para dim_vehiculo).", "dim_cp_provincia": "Diccionario codigo postal -> provincia/CCAA.", "tipologia_cliente": "Tipologia de cliente (clasificacion de negocio).", } # Descripcion corta de cada fuente de cliente. SRC_DESC = { "psql_dcpublic.tpv_customers": "Clientes del TPV (mostrador). Replica Postgres ANJANA (DCPublic).", "psql_dcpublic.customers": "Clientes web (e-commerce). Replica Postgres ANJANA (DCPublic).", "psql_dcpublic.otr_customers": "Clientes de OTR (ordenes de reparacion/taller). Replica Postgres ANJANA.", "psql_dcpublic.users": "Usuarios (cuentas). Replica Postgres ANJANA (DCPublic).", "mssql2022_dbo.anjana_customer": "Cliente de NAVISION (SQL Server 2022, esquema dbo). Campos no_/e_mail/movil/name/post_code.", "salesforce_ew1.contacts_latest": "Contactos de SALESFORCE (ultima version). Dataset en europe-west1.", "salesforce_ew1.email_sent": "Envios de email de Salesforce (Marketing Cloud).", "salesforce_ew1.email_opened": "Aperturas de email de Salesforce.", "salesforce_ew1.email_clicked": "Clics de email de Salesforce.", "salesforce_ew1.sms": "SMS de Salesforce.", "citaprevia_aurphcp.clientes": "Clientes de CITA PREVIA (aurphcp).", "citaprevia_aurphcp.clientes_matriculas": "Matriculas por cliente en cita previa.", "psql_dcpublic.tpv_vehicles_vehicle": "Vehiculos del TPV. Replica Postgres ANJANA.", "psql_dcpublic.tpv_vehicles_vehicleowner": "Propietarios de vehiculo del TPV (N:N). Replica Postgres ANJANA.", } CUST_SOURCES = list(SRC_DESC.keys()) SEP = "=" * 78 + "\n" def w(path, text): full = os.path.join(DEST, path) os.makedirs(os.path.dirname(full), exist_ok=True) with open(full, "w", newline="\r\n", encoding="utf-8") as f: f.write(text) def build_file(tbl): b = builds[tbl] out = [SEP, f"OBJETO : {PROJECT}.clientes_intel.{tbl}\n", f"TIPO : TABLA BASE construida por {b['stmt']} (se reconstruye periodicamente)\n", f"ULTIMA EJECUCION CAPTURADA: {b['last_run']}\n", SEP, "\nQUE ES\n------\n", textwrap.fill(DESC.get(tbl, "(sin descripcion)"), width=78) + "\n"] if b["refs"]: out.append("\nLEE DE (tablas fuente / intermedias)\n------------------------------------\n") for r in b["refs"]: note = " << FUENTE DE CLIENTE" if r in SRC_DESC else "" out.append(f" - {PROJECT}.{r}{note}\n") out.append("\nSQL DE CONSTRUCCION (copiable)\n------------------------------\n\n") out.append(b["query"].strip() + "\n") return "".join(out) for t in want: w(f"05_construccion_clientes_intel/{t}.txt", build_file(t)) # 00b_FUENTES_DE_CLIENTE.txt f = [SEP, "FUENTES DE CLIENTE -> QUE CONSULTA DE clientes_intel LAS USA\n", SEP, "\nResponde a: de donde salen los clientes (TPV, web, OTR, Navision, Salesforce, cita\n" "previa) y en que consulta se juntan. El punto de union de identidades es\n" "_persona_records (ver 05_construccion_clientes_intel/_persona_records.txt).\n\n"] f.append(SEP + "RESUMEN: LO QUE PEDISTE\n" + SEP + "\n") mapping = [ ("TPV customers", "psql_dcpublic.tpv_customers"), ("customers (web)", "psql_dcpublic.customers"), ("customers (OTR / taller)", "psql_dcpublic.otr_customers"), ("users", "psql_dcpublic.users"), ("customer de NAVISION", "mssql2022_dbo.anjana_customer"), ("SALESFORCE (contactos)", "salesforce_ew1.contacts_latest"), ] for label, src in mapping: f.append(f" {label:26s} -> {PROJECT}.{src}\n") f.append("\n SI: tenemos Salesforce. El dataset es `salesforce_ew1` (europe-west1):\n" " contactos en contacts_latest; marketing en email_sent/opened/clicked y sms.\n\n") for src in CUST_SOURCES: consumers = sorted(t for t, b in builds.items() if src in b["refs"]) f.append(SEP) f.append(f"{PROJECT}.{src}\n") f.append(SEP) f.append(f" {SRC_DESC[src]}\n") f.append(" La leen estas tablas de clientes_intel (con su SQL en 05_construccion_...):\n") if consumers: for t in consumers: star = " [SQL disponible]" if t in want else "" f.append(f" - {t} ({builds[t]['stmt']}){star}\n") else: f.append(" (ninguna la referencia directamente)\n") f.append("\n") w("00b_FUENTES_DE_CLIENTE.txt", "".join(f)) print("Generado:") print(f" 05_construccion_clientes_intel/ -> {len(want)} archivos con SQL de construccion") print(f" 00b_FUENTES_DE_CLIENTE.txt") print("\nTablas con SQL de construccion escrito:") for t in want: print(f" - {t}")