Files
aggios.app/backend/internal/api/handlers/crm.go
2025-12-17 13:36:23 -03:00

471 lines
12 KiB
Go

package handlers
import (
"aggios-app/backend/internal/domain"
"aggios-app/backend/internal/repository"
"aggios-app/backend/internal/api/middleware"
"encoding/json"
"log"
"net/http"
"github.com/google/uuid"
"github.com/gorilla/mux"
)
type CRMHandler struct {
repo *repository.CRMRepository
}
func NewCRMHandler(repo *repository.CRMRepository) *CRMHandler {
return &CRMHandler{repo: repo}
}
// ==================== CUSTOMERS ====================
func (h *CRMHandler) CreateCustomer(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
userID, _ := r.Context().Value(middleware.UserIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
var customer domain.CRMCustomer
if err := json.NewDecoder(r.Body).Decode(&customer); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Invalid request body",
"message": err.Error(),
})
return
}
customer.ID = uuid.New().String()
customer.TenantID = tenantID
customer.CreatedBy = userID
customer.IsActive = true
if err := h.repo.CreateCustomer(&customer); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to create customer",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]interface{}{
"customer": customer,
})
}
func (h *CRMHandler) GetCustomers(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
customers, err := h.repo.GetCustomersByTenant(tenantID)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to fetch customers",
"message": err.Error(),
})
return
}
if customers == nil {
customers = []domain.CRMCustomer{}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"customers": customers,
})
}
func (h *CRMHandler) GetCustomer(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
vars := mux.Vars(r)
customerID := vars["id"]
customer, err := h.repo.GetCustomerByID(customerID, tenantID)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]string{
"error": "Customer not found",
"message": err.Error(),
})
return
}
// Buscar listas do cliente
lists, _ := h.repo.GetCustomerLists(customerID)
if lists == nil {
lists = []domain.CRMList{}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"customer": customer,
"lists": lists,
})
}
func (h *CRMHandler) UpdateCustomer(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
vars := mux.Vars(r)
customerID := vars["id"]
var customer domain.CRMCustomer
if err := json.NewDecoder(r.Body).Decode(&customer); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Invalid request body",
"message": err.Error(),
})
return
}
customer.ID = customerID
customer.TenantID = tenantID
if err := h.repo.UpdateCustomer(&customer); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to update customer",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "Customer updated successfully",
})
}
func (h *CRMHandler) DeleteCustomer(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
vars := mux.Vars(r)
customerID := vars["id"]
if err := h.repo.DeleteCustomer(customerID, tenantID); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to delete customer",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "Customer deleted successfully",
})
}
// ==================== LISTS ====================
func (h *CRMHandler) CreateList(w http.ResponseWriter, r *http.Request) {
tenantIDVal := r.Context().Value(middleware.TenantIDKey)
userIDVal := r.Context().Value(middleware.UserIDKey)
log.Printf("🔍 CreateList DEBUG: tenantID type=%T value=%v | userID type=%T value=%v",
tenantIDVal, tenantIDVal, userIDVal, userIDVal)
tenantID, ok := tenantIDVal.(string)
if !ok || tenantID == "" {
log.Printf("❌ CreateList: Missing or invalid tenant_id")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
userID, _ := userIDVal.(string)
var list domain.CRMList
if err := json.NewDecoder(r.Body).Decode(&list); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Invalid request body",
"message": err.Error(),
})
return
}
list.ID = uuid.New().String()
list.TenantID = tenantID
list.CreatedBy = userID
if list.Color == "" {
list.Color = "#3b82f6"
}
if err := h.repo.CreateList(&list); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to create list",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]interface{}{
"list": list,
})
}
func (h *CRMHandler) GetLists(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
lists, err := h.repo.GetListsByTenant(tenantID)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to fetch lists",
"message": err.Error(),
})
return
}
if lists == nil {
lists = []domain.CRMListWithCustomers{}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"lists": lists,
})
}
func (h *CRMHandler) GetList(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
vars := mux.Vars(r)
listID := vars["id"]
list, err := h.repo.GetListByID(listID, tenantID)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]string{
"error": "List not found",
"message": err.Error(),
})
return
}
// Buscar clientes da lista
customers, _ := h.repo.GetListCustomers(listID, tenantID)
if customers == nil {
customers = []domain.CRMCustomer{}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"list": list,
"customers": customers,
})
}
func (h *CRMHandler) UpdateList(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
vars := mux.Vars(r)
listID := vars["id"]
var list domain.CRMList
if err := json.NewDecoder(r.Body).Decode(&list); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Invalid request body",
"message": err.Error(),
})
return
}
list.ID = listID
list.TenantID = tenantID
if err := h.repo.UpdateList(&list); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to update list",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "List updated successfully",
})
}
func (h *CRMHandler) DeleteList(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
if tenantID == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Missing tenant_id",
})
return
}
vars := mux.Vars(r)
listID := vars["id"]
if err := h.repo.DeleteList(listID, tenantID); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to delete list",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "List deleted successfully",
})
}
// ==================== CUSTOMER <-> LIST ====================
func (h *CRMHandler) AddCustomerToList(w http.ResponseWriter, r *http.Request) {
userID, _ := r.Context().Value(middleware.UserIDKey).(string)
vars := mux.Vars(r)
customerID := vars["customer_id"]
listID := vars["list_id"]
if err := h.repo.AddCustomerToList(customerID, listID, userID); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to add customer to list",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "Customer added to list successfully",
})
}
func (h *CRMHandler) RemoveCustomerFromList(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
customerID := vars["customer_id"]
listID := vars["list_id"]
if err := h.repo.RemoveCustomerFromList(customerID, listID); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"error": "Failed to remove customer from list",
"message": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "Customer removed from list successfully",
})
}