[30e88f42] ✦ In dieser Sitzung haben wir den End-to-End-Test der SuperOffice-Schnittstelle erfolgreich von der automatisierten Simulation bis zum produktiven Live-Lauf

✦ In dieser Sitzung haben wir den End-to-End-Test der SuperOffice-Schnittstelle erfolgreich von der automatisierten Simulation bis zum produktiven Live-Lauf
  mit Echtdaten abgeschlossen.
This commit is contained in:
2026-02-22 08:20:28 +00:00
parent 32332c092d
commit 11d2bc03bf
20 changed files with 732 additions and 70 deletions

View File

@@ -104,6 +104,8 @@ class ProvisioningResponse(BaseModel):
# Enrichment Data for Write-Back
address_city: Optional[str] = None
address_zip: Optional[str] = None
address_street: Optional[str] = None
address_country: Optional[str] = None
vat_id: Optional[str] = None
@@ -278,12 +280,19 @@ def provision_superoffice_contact(
# 2. Find Contact (Person)
if req.so_person_id is None:
# Just a company sync, no texts needed
# Just a company sync, but return all company-level metadata
return ProvisioningResponse(
status="success",
company_name=company.name,
website=company.website,
vertical_name=company.industry_ai
vertical_name=company.industry_ai,
opener=company.ai_opener,
opener_secondary=company.ai_opener_secondary,
address_city=company.city,
address_street=company.street,
address_zip=company.zip_code,
address_country=company.country,
vat_id=company.crm_vat
)
person = db.query(Contact).filter(Contact.so_person_id == req.so_person_id).first()
@@ -353,6 +362,8 @@ def provision_superoffice_contact(
opener_secondary=company.ai_opener_secondary,
texts=texts,
address_city=company.city,
address_street=company.street,
address_zip=company.zip_code,
address_country=company.country,
# TODO: Add VAT field to Company model if not present, for now using crm_vat if available
vat_id=company.crm_vat

View File

@@ -34,6 +34,8 @@ class Company(Base):
industry_ai = Column(String, nullable=True) # The AI suggested industry
# Location (Golden Record)
street = Column(String, nullable=True) # NEW: Street + Number
zip_code = Column(String, nullable=True) # NEW: Postal Code
city = Column(String, nullable=True)
country = Column(String, default="DE")

View File

@@ -220,8 +220,49 @@ AUSGABE: NUR den fertigen Satz.
logger.error(f"Opener Error: {e}")
return None
def _sync_company_address_data(self, db: Session, company: Company):
"""Extracts address and VAT data from website scrape if available."""
from ..database import EnrichmentData
enrichment = db.query(EnrichmentData).filter_by(
company_id=company.id, source_type="website_scrape"
).order_by(EnrichmentData.created_at.desc()).first()
if enrichment and enrichment.content and "impressum" in enrichment.content:
imp = enrichment.content["impressum"]
if imp and isinstance(imp, dict):
changed = False
# City
if imp.get("city") and not company.city:
company.city = imp.get("city")
changed = True
# Street
if imp.get("street") and not company.street:
company.street = imp.get("street")
changed = True
# Zip / PLZ
zip_val = imp.get("zip") or imp.get("plz")
if zip_val and not company.zip_code:
company.zip_code = zip_val
changed = True
# Country
if imp.get("country_code") and (not company.country or company.country == "DE"):
company.country = imp.get("country_code")
changed = True
# VAT ID
if imp.get("vat_id") and not company.crm_vat:
company.crm_vat = imp.get("vat_id")
changed = True
if changed:
db.commit()
logger.info(f"Updated Address/VAT from Impressum for {company.name}: City={company.city}, VAT={company.crm_vat}")
def classify_company_potential(self, company: Company, db: Session) -> Company:
logger.info(f"--- Starting FULL Analysis v3.0 for {company.name} ---")
# Ensure metadata is synced from scrape
self._sync_company_address_data(db, company)
industries = self._load_industry_definitions(db)
website_content, _ = self._get_website_content_and_url(db, company)
if not website_content or len(website_content) < 100: