package handlers import ( "database/sql" "encoding/json" "net/http" "boc/tenant" ) // TenantHandler hanterar multi-tenancy API type TenantHandler struct { manager *tenant.Manager } func NewTenantHandler(db *sql.DB) *TenantHandler { return &TenantHandler{ manager: tenant.NewManager(db), } } // ListTenants returnerar alla verksamheter användaren har tillgång till func (h *TenantHandler) ListTenants(w http.ResponseWriter, r *http.Request) { // TODO: Filtrera baserat på användarens behörigheter tenants, err := h.manager.ListTenants(r.Context()) if err != nil { http.Error(w, `{"error":"failed to list tenants"}`, http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{ "tenants": tenants, "total": len(tenants), }) } // GetTenant returnerar detaljer för en specifik verksamhet func (h *TenantHandler) GetTenant(w http.ResponseWriter, r *http.Request) { tenantID := r.URL.Query().Get("id") if tenantID == "" { http.Error(w, `{"error":"tenant id required"}`, http.StatusBadRequest) return } t, err := h.manager.GetTenant(r.Context(), tenantID) if err != nil { http.Error(w, `{"error":"tenant not found"}`, http.StatusNotFound) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(t) } // GetTenantHierarchy returnerar koncernstruktur func (h *TenantHandler) GetTenantHierarchy(w http.ResponseWriter, r *http.Request) { // Hämta alla koncerner (root tenants) rows, err := h.manager.ListTenants(r.Context()) if err != nil { http.Error(w, `{"error":"failed to get hierarchy"}`, http.StatusInternalServerError) return } // Bygg hierarki type HierarchyNode struct { *tenant.Tenant Children []*HierarchyNode `json:"children,omitempty"` } // Simplifierad: returnera flat lista för nu w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{ "tenants": rows, }) } // SwitchTenant byter aktiv verksamhet för användaren func (h *TenantHandler) SwitchTenant(w http.ResponseWriter, r *http.Request) { var req struct { TenantID string `json:"tenant_id"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest) return } // Verifiera att tenant finns och är aktiv t, err := h.manager.GetTenant(r.Context(), req.TenantID) if err != nil { http.Error(w, `{"error":"tenant not found or inactive"}`, http.StatusNotFound) return } // TODO: Uppdatera användarens session med ny tenant // TODO: Logga tenant-byte i audit log w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{ "success": true, "tenant_id": t.ID, "tenant_name": t.Name, "message": "Switched to " + t.Name, }) } // GetTenantSummary returnerar sammanfattning för dashboard func (h *TenantHandler) GetTenantSummary(w http.ResponseWriter, r *http.Request) { tenantID := r.URL.Query().Get("tenant_id") if tenantID == "" { tenantID = "default" // Fallback } // För nu, returnera mock-data w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{ "tenant_id": tenantID, "active_users": 5, "customers": 3, "open_deals": 3, "employees": 6, "pipeline_value": 5250000, }) }