package handlers import ( "database/sql" "net/http" ) // UnifiedHandler hanterar allt i ett enda API type UnifiedHandler struct { DB *sql.DB } func NewUnifiedHandler(db *sql.DB) *UnifiedHandler { return &UnifiedHandler{DB: db} } // GetUnifiedDashboard returnerar allt på ett ställe func (h *UnifiedHandler) GetUnifiedDashboard(w http.ResponseWriter, r *http.Request) { // 1. Hämta CRM-data från BOC-databasen customers := []map[string]interface{}{} customerRows, err := h.DB.Query(` SELECT id, name, email, status, created_at FROM boc_customers WHERE status = 'active' ORDER BY created_at DESC `) if err == nil { defer customerRows.Close() for customerRows.Next() { var c map[string]interface{} var id, name, email, status string var createdAt sql.NullTime if err := customerRows.Scan(&id, &name, &email, &status, &createdAt); err != nil { continue } c = map[string]interface{}{ "id": id, "name": name, "email": email, "status": status, } if createdAt.Valid { c["created_at"] = createdAt.Time.Format("2006-01-02") } customers = append(customers, c) } } // 2. Hämta deals från BOC-databasen deals := []map[string]interface{}{} dealRows, err := h.DB.Query(` SELECT id, name, customer_id, value, currency, stage, status FROM boc_deals ORDER BY CASE stage WHEN 'negotiation' THEN 1 WHEN 'proposal' THEN 2 WHEN 'closed' THEN 3 ELSE 4 END, value DESC `) if err == nil { defer dealRows.Close() for dealRows.Next() { var d map[string]interface{} var id, name, customerID, currency, stage, status string var value float64 if err := dealRows.Scan(&id, &name, &customerID, &value, ¤cy, &stage, &status); err != nil { continue } d = map[string]interface{}{ "id": id, "name": name, "customer_id": customerID, "value": value, "currency": currency, "stage": stage, "status": status, } deals = append(deals, d) } } // 3. Hämta mail-statistik mailCount := 0 mailRows, err := h.DB.Query(` SELECT COUNT(*) FROM boc_mail_messages `) if err == nil && mailRows.Next() { mailRows.Scan(&mailCount) mailRows.Close() } // 4. Hämta analytics var revenue, moms float64 analyticsRows, err := h.DB.Query(` SELECT kpi_key, value FROM boc_analytics_kpis WHERE kpi_key IN ('revenue_h1', 'moms_att_betala') `) if err == nil { defer analyticsRows.Close() for analyticsRows.Next() { var key string var value float64 if err := analyticsRows.Scan(&key, &value); err != nil { continue } if key == "revenue_h1" { revenue = value } else if key == "moms_att_betala" { moms = value } } } // 5. Hämta team team := []map[string]interface{}{} teamRows, err := h.DB.Query(` SELECT first_name, last_name, position, department, status FROM boc_employees WHERE status = 'active' ORDER BY department, first_name `) if err == nil { defer teamRows.Close() for teamRows.Next() { var firstName, lastName, position, department, status string if err := teamRows.Scan(&firstName, &lastName, &position, &department, &status); err != nil { continue } team = append(team, map[string]interface{}{ "name": firstName + " " + lastName, "position": position, "department": department, "status": status, }) } } writeJSON(w, http.StatusOK, map[string]interface{}{ "ok": true, "dashboard": map[string]interface{}{ "crm": map[string]interface{}{ "customers": customers, "deals": deals, "total_pipeline": calculatePipeline(deals), }, "finance": map[string]interface{}{ "revenue": revenue, "moms": moms, }, "mail": map[string]interface{}{ "total_messages": mailCount, }, "team": team, }, }) } func calculatePipeline(deals []map[string]interface{}) float64 { var total float64 for _, deal := range deals { if status, ok := deal["status"].(string); ok && status == "open" { if value, ok := deal["value"].(float64); ok { total += value } } } return total }