125 lines
4.3 KiB
Python
125 lines
4.3 KiB
Python
from fastapi import APIRouter, HTTPException
|
|
from app.core.database import execute_query
|
|
from typing import Dict, Any, List
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
@router.get("/stats", response_model=Dict[str, Any])
|
|
async def get_dashboard_stats():
|
|
"""
|
|
Get aggregated statistics for the dashboard
|
|
"""
|
|
try:
|
|
logger.info("📊 Fetching dashboard stats...")
|
|
|
|
# 1. Customer Counts
|
|
logger.info("Fetching customer count...")
|
|
customer_res = execute_query("SELECT COUNT(*) as count FROM customers WHERE deleted_at IS NULL", fetchone=True)
|
|
customer_count = customer_res['count'] if customer_res else 0
|
|
|
|
# 2. Contact Counts
|
|
logger.info("Fetching contact count...")
|
|
contact_res = execute_query("SELECT COUNT(*) as count FROM contacts", fetchone=True)
|
|
contact_count = contact_res['count'] if contact_res else 0
|
|
|
|
# 3. Vendor Counts
|
|
logger.info("Fetching vendor count...")
|
|
vendor_res = execute_query("SELECT COUNT(*) as count FROM vendors", fetchone=True)
|
|
vendor_count = vendor_res['count'] if vendor_res else 0
|
|
|
|
# 4. Recent Customers (Real "Activity")
|
|
logger.info("Fetching recent customers...")
|
|
recent_customers = execute_query("""
|
|
SELECT id, name, created_at, 'customer' as type
|
|
FROM customers
|
|
WHERE deleted_at IS NULL
|
|
ORDER BY created_at DESC
|
|
LIMIT 5
|
|
""")
|
|
|
|
# 5. Vendor Categories Distribution
|
|
logger.info("Fetching vendor distribution...")
|
|
vendor_categories = execute_query("""
|
|
SELECT category, COUNT(*) as count
|
|
FROM vendors
|
|
GROUP BY category
|
|
""")
|
|
|
|
logger.info("✅ Dashboard stats fetched successfully")
|
|
return {
|
|
"counts": {
|
|
"customers": customer_count,
|
|
"contacts": contact_count,
|
|
"vendors": vendor_count
|
|
},
|
|
"recent_activity": recent_customers or [],
|
|
"vendor_distribution": vendor_categories or [],
|
|
"system_status": "online"
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"❌ Error fetching dashboard stats: {e}", exc_info=True)
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/search", response_model=Dict[str, List[Any]])
|
|
async def global_search(q: str):
|
|
"""
|
|
Global search across customers, contacts, and vendors
|
|
"""
|
|
if not q or len(q) < 2:
|
|
return {"customers": [], "contacts": [], "vendors": []}
|
|
|
|
search_term = f"%{q}%"
|
|
|
|
try:
|
|
# Search Customers
|
|
customers = execute_query("""
|
|
SELECT id, name, email, 'Kunde' as type
|
|
FROM customers
|
|
WHERE deleted_at IS NULL AND (
|
|
name ILIKE %s OR
|
|
email ILIKE %s OR
|
|
cvr_number ILIKE %s OR
|
|
phone ILIKE %s OR
|
|
mobile_phone ILIKE %s
|
|
)
|
|
LIMIT 5
|
|
""", (search_term, search_term, search_term, search_term, search_term))
|
|
|
|
# Search Contacts
|
|
contacts = execute_query("""
|
|
SELECT id, first_name || ' ' || last_name as name, email, 'Kontakt' as type
|
|
FROM contacts
|
|
WHERE first_name ILIKE %s OR
|
|
last_name ILIKE %s OR
|
|
email ILIKE %s OR
|
|
phone ILIKE %s OR
|
|
mobile ILIKE %s
|
|
LIMIT 5
|
|
""", (search_term, search_term, search_term, search_term, search_term))
|
|
|
|
# Search Vendors
|
|
vendors = execute_query("""
|
|
SELECT id, name, email, 'Leverandør' as type
|
|
FROM vendors
|
|
WHERE is_active = true AND (
|
|
name ILIKE %s OR
|
|
email ILIKE %s OR
|
|
cvr_number ILIKE %s OR
|
|
phone ILIKE %s
|
|
)
|
|
LIMIT 5
|
|
""", (search_term, search_term, search_term, search_term))
|
|
|
|
return {
|
|
"customers": customers or [],
|
|
"contacts": contacts or [],
|
|
"vendors": vendors or []
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"❌ Error performing global search: {e}", exc_info=True)
|
|
return {"customers": [], "contacts": [], "vendors": []}
|