[30388f42] Infrastructure Hardening: Repaired CE/Connector DB schema, fixed frontend styling build, implemented robust echo shield in worker v2.1.1, and integrated Lead Engine into gateway.
This commit is contained in:
@@ -5,8 +5,9 @@ import sqlite3
|
||||
|
||||
# Füge das Hauptverzeichnis zum Python-Pfad hinzu, damit der Connector gefunden wird
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
from company_explorer_connector import handle_company_workflow
|
||||
from db import get_leads, DB_PATH
|
||||
from company_explorer_connector import handle_company_workflow, get_company_details
|
||||
from db import get_leads, DB_PATH, update_lead_metadata
|
||||
from lookup_role import lookup_person_role
|
||||
|
||||
def update_lead_enrichment(lead_id, data, status):
|
||||
"""Aktualisiert einen Lead in der Datenbank mit neuen Enrichment-Daten und einem neuen Status."""
|
||||
@@ -18,9 +19,129 @@ def update_lead_enrichment(lead_id, data, status):
|
||||
conn.close()
|
||||
print(f"Lead {lead_id} aktualisiert. Neuer Status: {status}")
|
||||
|
||||
def refresh_ce_data(lead_id, ce_id):
|
||||
"""
|
||||
Holt die aktuellsten Daten (inkl. Analyse-Ergebnis) vom Company Explorer
|
||||
und aktualisiert den lokalen Lead.
|
||||
"""
|
||||
print(f"Refreshing data for CE ID {ce_id}...")
|
||||
ce_data = get_company_details(ce_id)
|
||||
|
||||
# Bestehende Enrichment-Daten holen
|
||||
leads = get_leads()
|
||||
lead = next((l for l in leads if l['id'] == lead_id), None)
|
||||
|
||||
enrichment_data = {}
|
||||
if lead and lead.get('enrichment_data'):
|
||||
try:
|
||||
enrichment_data = json.loads(lead['enrichment_data'])
|
||||
except:
|
||||
pass
|
||||
|
||||
enrichment_data.update({
|
||||
"sync_status": "refreshed",
|
||||
"ce_id": ce_id,
|
||||
"message": "Data refreshed from CE",
|
||||
"ce_data": ce_data
|
||||
})
|
||||
|
||||
update_lead_enrichment(lead_id, enrichment_data, status='synced')
|
||||
return ce_data
|
||||
|
||||
def enrich_contact_role(lead):
|
||||
"""
|
||||
Versucht, die Rolle des Kontakts via SerpAPI zu finden und speichert sie in den Metadaten.
|
||||
"""
|
||||
meta = {}
|
||||
if lead.get('lead_metadata'):
|
||||
try:
|
||||
meta = json.loads(lead.get('lead_metadata'))
|
||||
except:
|
||||
pass
|
||||
|
||||
# Skip if we already have a role (and it's not None/Unknown)
|
||||
if meta.get('role') and meta.get('role') != "Unbekannt":
|
||||
return meta.get('role')
|
||||
|
||||
print(f"Looking up role for {lead['contact_name']} at {lead['company_name']}...")
|
||||
role = lookup_person_role(lead['contact_name'], lead['company_name'])
|
||||
|
||||
if role:
|
||||
print(f" -> Found role: {role}")
|
||||
meta['role'] = role
|
||||
update_lead_metadata(lead['id'], meta)
|
||||
else:
|
||||
print(" -> No role found.")
|
||||
|
||||
return role
|
||||
|
||||
def sync_single_lead(lead_id):
|
||||
"""
|
||||
Verarbeitet einen einzelnen Lead: Rolle suchen, CE-Sync, Analyse triggern.
|
||||
"""
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.row_factory = sqlite3.Row
|
||||
c = conn.cursor()
|
||||
c.execute('SELECT * FROM leads WHERE id = ?', (lead_id,))
|
||||
lead = c.fetchone()
|
||||
conn.close()
|
||||
|
||||
if not lead:
|
||||
return {"status": "error", "message": "Lead not found"}
|
||||
|
||||
lead_dict = dict(lead)
|
||||
company_name = lead_dict['company_name']
|
||||
print(f"\n--- Manually Syncing Lead ID: {lead_id}, Company: '{company_name}' ---")
|
||||
|
||||
# 1. Contact Enrichment (Role Lookup)
|
||||
role = enrich_contact_role(lead_dict)
|
||||
|
||||
# 2. Prepare Contact Info
|
||||
meta = {}
|
||||
if lead_dict.get('lead_metadata'):
|
||||
try: meta = json.loads(lead_dict['lead_metadata'])
|
||||
except: pass
|
||||
|
||||
# Smarter name splitting if meta is empty (for repaired leads)
|
||||
full_name = lead_dict.get('contact_name', '')
|
||||
first_name = meta.get('contact_first')
|
||||
last_name = meta.get('contact_last')
|
||||
|
||||
if not first_name and full_name:
|
||||
parts = full_name.strip().split(' ')
|
||||
if len(parts) > 1:
|
||||
first_name = parts[0]
|
||||
last_name = ' '.join(parts[1:])
|
||||
else:
|
||||
last_name = full_name
|
||||
first_name = ''
|
||||
|
||||
contact_info = {
|
||||
"first_name": first_name,
|
||||
"last_name": last_name,
|
||||
"email": lead_dict['email'],
|
||||
"job_title": meta.get('role', role),
|
||||
"role": None, # Set to None so CE can use its RoleMappingService
|
||||
"is_primary": True
|
||||
}
|
||||
|
||||
# 3. CE Workflow
|
||||
result = handle_company_workflow(company_name, contact_info=contact_info)
|
||||
|
||||
# 4. Save results
|
||||
enrichment_data = {
|
||||
"sync_status": result.get("status"),
|
||||
"ce_id": result.get("data", {}).get("id") if result.get("data") else None,
|
||||
"message": result.get("message", "Manual sync successful"),
|
||||
"ce_data": result.get("data")
|
||||
}
|
||||
|
||||
update_lead_enrichment(lead_id, enrichment_data, status='synced')
|
||||
return result
|
||||
|
||||
def run_sync():
|
||||
"""
|
||||
Haupt-Synchronisationsprozess.
|
||||
Haupt-Synchronisationsprozess (Batch).
|
||||
Holt alle neuen Leads und stößt den Company Explorer Workflow für jeden an.
|
||||
"""
|
||||
# Hole nur die Leads, die wirklich neu sind und noch nicht verarbeitet wurden
|
||||
@@ -36,15 +157,33 @@ def run_sync():
|
||||
company_name = lead['company_name']
|
||||
print(f"\n--- Processing Lead ID: {lead['id']}, Company: '{company_name}' ---")
|
||||
|
||||
# Rufe den zentralen Workflow auf, den wir im Connector definiert haben
|
||||
# Diese Funktion kümmert sich um alles: prüfen, erstellen, discovern, pollen, analysieren
|
||||
result = handle_company_workflow(company_name)
|
||||
# 1. Contact Enrichment (Role Lookup via SerpAPI)
|
||||
role = enrich_contact_role(lead)
|
||||
|
||||
# 2. Prepare Contact Info for CE
|
||||
meta = {}
|
||||
if lead.get('lead_metadata'):
|
||||
try:
|
||||
meta = json.loads(lead.get('lead_metadata'))
|
||||
except:
|
||||
pass
|
||||
|
||||
contact_info = {
|
||||
"first_name": meta.get('contact_first', ''),
|
||||
"last_name": meta.get('contact_last', lead['contact_name'].split(' ')[-1] if lead['contact_name'] else ''),
|
||||
"email": lead['email'],
|
||||
"job_title": meta.get('role', role), # The raw title or Gemini result
|
||||
"role": meta.get('role', role) # Currently mapped to same field
|
||||
}
|
||||
|
||||
# 3. Company Enrichment (CE Workflow with Contact)
|
||||
result = handle_company_workflow(company_name, contact_info=contact_info)
|
||||
|
||||
# Bereite die Daten für die Speicherung in der DB vor
|
||||
enrichment_data = {
|
||||
"sync_status": result.get("status"),
|
||||
"ce_id": result.get("data", {}).get("id") if result.get("data") else None,
|
||||
"message": result.get("message"),
|
||||
"message": result.get("message", "Sync successful"),
|
||||
"ce_data": result.get("data")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user