Files
boc/backend/handlers/unified.go
T
Bernt 78b57273e2 security: Add proper authentication, RBAC, and tenant isolation
- Add password hashing with bcrypt
- Add AuthService with proper login
- Add password strength validation
- Add RBAC middleware (AdminOnly, ManagerOrAdmin)
- Add tenant isolation middleware
- Update CRM handler with tenant filtering
- Add JWT fallback for development mode
- Add user context helpers
- Build successful
2026-08-10 12:52:48 +00:00

172 lines
4.0 KiB
Go

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, &currency, &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
}