Feat: End-to-End Test & Bidirectional Vertical Sync [30e88f42]

- Implemented comprehensive E2E test  covering full roundtrip and manual overrides.
- Enhanced  to detect manual Vertical changes in SuperOffice and sync them to Company Explorer.
- Updated  to handle industry overrides from CRM and auto-persist Person/Contact data for robust cascade updates.
This commit is contained in:
2026-02-21 20:05:25 +00:00
parent f66df10d4d
commit 4d48b2689b
3 changed files with 350 additions and 7 deletions

View File

@@ -90,6 +90,7 @@ class ProvisioningRequest(BaseModel):
crm_name: Optional[str] = None
crm_website: Optional[str] = None
job_title: Optional[str] = None
crm_industry_name: Optional[str] = None
class ProvisioningResponse(BaseModel):
status: str
@@ -242,6 +243,19 @@ def provision_superoffice_contact(
company.crm_website = req.crm_website
changed = True
# NEW: Handle Vertical Override from SuperOffice
if req.crm_industry_name:
# Check if valid industry
valid_industry = db.query(Industry).filter(Industry.name == req.crm_industry_name).first()
if valid_industry:
if company.industry_ai != req.crm_industry_name:
logger.info(f"Overriding Industry for {company.name}: {company.industry_ai} -> {req.crm_industry_name} (from CRM)")
company.industry_ai = req.crm_industry_name
# Trigger metric re-extraction? Maybe later. For now, just update.
changed = True
else:
logger.warning(f"CRM provided industry '{req.crm_industry_name}' not found in DB. Ignoring.")
# Simple Mismatch Check
if company.website and company.crm_website:
def norm(u): return str(u).lower().replace("https://", "").replace("http://", "").replace("www.", "").strip("/")
@@ -269,19 +283,39 @@ def provision_superoffice_contact(
person = db.query(Contact).filter(Contact.so_person_id == req.so_person_id).first()
# 3. Determine Role
role_name = None
if person and person.role:
role_name = person.role
elif req.job_title:
# Auto-Create/Update Person
if not person:
person = Contact(
company_id=company.id,
so_contact_id=req.so_contact_id,
so_person_id=req.so_person_id,
status="ACTIVE"
)
db.add(person)
logger.info(f"Created new person {req.so_person_id} for company {company.name}")
# Update Job Title & Role logic
if req.job_title:
person.job_title = req.job_title
# Simple classification fallback
mappings = db.query(JobRoleMapping).all()
found_role = None
for m in mappings:
# Check pattern type (Regex vs Simple) - simplified here
pattern_clean = m.pattern.replace("%", "").lower()
if pattern_clean in req.job_title.lower():
role_name = m.role
found_role = m.role
break
if found_role:
person.role = found_role
db.commit()
db.refresh(person)
# 3. Determine Role
role_name = person.role
# 4. Determine Vertical (Industry)
vertical_name = company.industry_ai