Add: Sync e-conomic customer numbers fra Simply-CRM + auto-link timetracking customers

This commit is contained in:
Christian 2026-01-05 11:08:49 +01:00
parent 24a517a10c
commit 1380369dff

View File

@ -288,6 +288,120 @@ async def update_customer(customer_id: int, update: CustomerUpdate):
raise HTTPException(status_code=500, detail=str(e))
@router.post("/customers/sync-economic-from-simplycrm")
async def sync_economic_numbers_from_simplycrm():
"""
🔗 Sync e-conomic customer numbers fra Simply-CRM til Hub customers.
Henter cf_854 (economic_customer_number) fra Simply-CRM accounts og
opdaterer matching Hub customers baseret navn.
"""
try:
from app.services.simplycrm_service import SimplyCRMService
logger.info("🚀 Starting e-conomic number sync from Simply-CRM...")
stats = {
"simplycrm_accounts": 0,
"accounts_with_economic_number": 0,
"hub_customers_updated": 0,
"hub_customers_not_found": 0,
"errors": 0
}
async with SimplyCRMService() as simplycrm:
# Hent alle accounts fra Simply-CRM
logger.info("📥 Fetching accounts from Simply-CRM...")
query = "SELECT accountname, cf_854 FROM Accounts LIMIT 5000;"
accounts = await simplycrm.query(query)
stats["simplycrm_accounts"] = len(accounts)
logger.info(f"✅ Found {len(accounts)} accounts in Simply-CRM")
if not accounts:
return {
"status": "success",
"message": "No accounts found in Simply-CRM",
"stats": stats
}
# Filter accounts med economic customer number
accounts_with_economic = [
acc for acc in accounts
if acc.get('cf_854') and str(acc.get('cf_854')).strip() not in ['', '0', 'null', 'NULL']
]
stats["accounts_with_economic_number"] = len(accounts_with_economic)
logger.info(f"{len(accounts_with_economic)} accounts have e-conomic customer numbers")
# Map company name → economic_customer_number
name_to_economic = {}
for acc in accounts_with_economic:
company_name = acc.get('accountname', '').strip()
economic_number = str(acc.get('cf_854', '')).strip()
if company_name and economic_number:
# Normalize navn til lowercase for matching
name_key = company_name.lower()
name_to_economic[name_key] = {
'original_name': company_name,
'economic_customer_number': economic_number
}
logger.info(f"📊 Mapped {len(name_to_economic)} unique company names")
# Hent alle Hub customers
hub_customers = execute_query("SELECT id, name FROM customers")
logger.info(f"📊 Found {len(hub_customers)} customers in Hub")
# Match og opdater
for customer in hub_customers:
customer_name_key = customer['name'].strip().lower()
if customer_name_key in name_to_economic:
economic_data = name_to_economic[customer_name_key]
economic_number = economic_data['economic_customer_number']
try:
execute_query(
"""UPDATE customers
SET economic_customer_number = %s,
last_synced_at = NOW()
WHERE id = %s""",
(economic_number, customer['id'])
)
logger.info(f"✅ Updated {customer['name']} → e-conomic #{economic_number}")
stats["hub_customers_updated"] += 1
except Exception as update_error:
logger.error(f"❌ Failed to update customer {customer['id']}: {update_error}")
stats["errors"] += 1
else:
stats["hub_customers_not_found"] += 1
logger.info(f"✅ Sync complete: {stats}")
# Auto-link tmodule_customers after sync
try:
logger.info("🔗 Running auto-link for timetracking customers...")
link_results = execute_query("SELECT * FROM link_tmodule_customers_to_hub()")
logger.info(f"✅ Linked {len(link_results)} timetracking customers")
stats["tmodule_customers_linked"] = len(link_results)
except Exception as link_error:
logger.warning(f"⚠️ Auto-linking failed (non-critical): {link_error}")
return {
"status": "success",
"message": f"Synced {stats['hub_customers_updated']} customers with e-conomic numbers from Simply-CRM",
"stats": stats
}
except Exception as e:
logger.error(f"❌ Simply-CRM sync failed: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/customers/{customer_id}/link-economic")
async def link_economic_customer(customer_id: int, link_request: dict):
"""Manually link customer to e-conomic customer number"""