From e541758c44e32803b5345cf71075745a5bbae371 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 22 Dec 2025 15:14:31 +0100 Subject: [PATCH] Add: Sync diagnostics endpoint for troubleshooting contact linking --- app/system/backend/sync_router.py | 88 +++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/app/system/backend/sync_router.py b/app/system/backend/sync_router.py index 3e2a068..ee16c1d 100644 --- a/app/system/backend/sync_router.py +++ b/app/system/backend/sync_router.py @@ -523,3 +523,91 @@ async def sync_cvr_to_economic() -> Dict[str, Any]: except Exception as e: logger.error(f"❌ CVR to e-conomic sync error: {e}") raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/sync/diagnostics") +async def sync_diagnostics() -> Dict[str, Any]: + """ + Diagnostics: Check contact linking coverage + Shows why contacts aren't linking to customers + """ + try: + logger.info("🔍 Running sync diagnostics...") + + # Check Hub data + hub_stats = execute_query(""" + SELECT + COUNT(*) as total_customers, + COUNT(vtiger_id) as customers_with_vtiger + FROM customers + """) + + vtiger_ids_in_hub = execute_query( + "SELECT vtiger_id FROM customers WHERE vtiger_id IS NOT NULL" + ) + hub_vtiger_set = set(row['vtiger_id'] for row in vtiger_ids_in_hub) + + contact_stats = execute_query(""" + SELECT + COUNT(*) as total_contacts, + COUNT(vtiger_id) as contacts_with_vtiger + FROM contacts + """) + + link_stats = execute_query(""" + SELECT COUNT(*) as total_links + FROM contact_companies + """) + + # Fetch sample contacts from vTiger + vtiger = get_vtiger_service() + query = "SELECT id, firstname, lastname, account_id FROM Contacts ORDER BY id LIMIT 200;" + contacts = await vtiger.query(query) + + # Analyze + with_account = [c for c in contacts if c.get('account_id')] + account_ids = set(c['account_id'] for c in with_account) + + matched_accounts = [aid for aid in account_ids if aid in hub_vtiger_set] + unmatched_accounts = [aid for aid in account_ids if aid not in hub_vtiger_set] + + result = { + "hub": { + "total_customers": hub_stats[0]['total_customers'], + "customers_with_vtiger_id": hub_stats[0]['customers_with_vtiger'], + "unique_vtiger_ids": len(hub_vtiger_set), + "total_contacts": contact_stats[0]['total_contacts'], + "contacts_with_vtiger_id": contact_stats[0]['contacts_with_vtiger'], + "total_links": link_stats[0]['total_links'] + }, + "vtiger_sample": { + "sample_size": len(contacts), + "contacts_with_account_id": len(with_account), + "unique_account_ids": len(account_ids), + "account_ids_found_in_hub": len(matched_accounts), + "account_ids_missing_in_hub": len(unmatched_accounts), + "match_rate_percent": round((len(matched_accounts) / len(account_ids) * 100), 1) if account_ids else 0 + }, + "examples": { + "matched_account_ids": matched_accounts[:5], + "unmatched_account_ids": unmatched_accounts[:10] + }, + "recommendation": "" + } + + # Add recommendation + match_rate = result['vtiger_sample']['match_rate_percent'] + if match_rate < 50: + result['recommendation'] = f"⚠️ LOW MATCH RATE ({match_rate}%) - Kør først /sync/vtiger for at linke flere accounts" + elif match_rate < 90: + result['recommendation'] = f"⚡ MEDIUM MATCH RATE ({match_rate}%) - Nogen accounts mangler stadig at blive linket" + else: + result['recommendation'] = f"✅ HIGH MATCH RATE ({match_rate}%) - De fleste contacts kan linkes" + + logger.info(f"✅ Diagnostics complete: {result['recommendation']}") + + return result + + except Exception as e: + logger.error(f"❌ Diagnostics error: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e))