Files
aggios.app/backend/internal/api/handlers/erp_handler.go
2025-12-29 17:23:59 -03:00

400 lines
12 KiB
Go

package handlers
import (
"aggios-app/backend/internal/api/middleware"
"aggios-app/backend/internal/domain"
"aggios-app/backend/internal/repository"
"encoding/json"
"log"
"net/http"
"time"
"github.com/google/uuid"
"github.com/gorilla/mux"
)
type ERPHandler struct {
repo *repository.ERPRepository
}
func NewERPHandler(repo *repository.ERPRepository) *ERPHandler {
return &ERPHandler{repo: repo}
}
// ==================== FINANCE ====================
func (h *ERPHandler) CreateFinancialCategory(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
var cat domain.FinancialCategory
if err := json.NewDecoder(r.Body).Decode(&cat); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
cat.ID = uuid.New()
cat.TenantID, _ = uuid.Parse(tenantID)
cat.IsActive = true
if err := h.repo.CreateFinancialCategory(&cat); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(cat)
}
func (h *ERPHandler) GetFinancialCategories(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
cats, err := h.repo.GetFinancialCategoriesByTenant(tenantID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(cats)
}
func (h *ERPHandler) CreateBankAccount(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
var acc domain.BankAccount
if err := json.NewDecoder(r.Body).Decode(&acc); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
acc.ID = uuid.New()
acc.TenantID, _ = uuid.Parse(tenantID)
acc.IsActive = true
if err := h.repo.CreateBankAccount(&acc); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(acc)
}
func (h *ERPHandler) GetBankAccounts(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
accs, err := h.repo.GetBankAccountsByTenant(tenantID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(accs)
}
func (h *ERPHandler) CreateTransaction(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
userID, _ := r.Context().Value(middleware.UserIDKey).(string)
var t domain.FinancialTransaction
if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
t.ID = uuid.New()
t.TenantID, _ = uuid.Parse(tenantID)
t.CreatedBy, _ = uuid.Parse(userID)
if err := h.repo.CreateTransaction(&t); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(t)
}
func (h *ERPHandler) GetTransactions(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
txs, err := h.repo.GetTransactionsByTenant(tenantID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(txs)
}
// ==================== PRODUCTS ====================
func (h *ERPHandler) CreateProduct(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
var p domain.Product
if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
p.ID = uuid.New()
p.TenantID, _ = uuid.Parse(tenantID)
p.IsActive = true
if err := h.repo.CreateProduct(&p); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(p)
}
func (h *ERPHandler) GetProducts(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
products, err := h.repo.GetProductsByTenant(tenantID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(products)
}
// ==================== ORDERS ====================
type createOrderRequest struct {
Order domain.Order `json:"order"`
Items []domain.OrderItem `json:"items"`
}
func (h *ERPHandler) CreateOrder(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
userID, _ := r.Context().Value(middleware.UserIDKey).(string)
var req createOrderRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
req.Order.ID = uuid.New()
req.Order.TenantID, _ = uuid.Parse(tenantID)
req.Order.CreatedBy, _ = uuid.Parse(userID)
if req.Order.Status == "" {
req.Order.Status = "draft"
}
for i := range req.Items {
req.Items[i].ID = uuid.New()
req.Items[i].OrderID = req.Order.ID
req.Items[i].CreatedAt = time.Now()
}
if err := h.repo.CreateOrder(&req.Order, req.Items); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(req.Order)
}
func (h *ERPHandler) GetOrders(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
orders, err := h.repo.GetOrdersByTenant(tenantID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(orders)
}
// ==================== ENTITIES ====================
func (h *ERPHandler) CreateEntity(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
var e domain.Entity
if err := json.NewDecoder(r.Body).Decode(&e); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
e.ID = uuid.New()
e.TenantID, _ = uuid.Parse(tenantID)
if e.Status == "" {
e.Status = "active"
}
if err := h.repo.CreateEntity(&e); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(e)
}
func (h *ERPHandler) GetEntities(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
entityType := r.URL.Query().Get("type") // customer or supplier
entities, err := h.repo.GetEntitiesByTenant(tenantID, entityType)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(entities)
}
func (h *ERPHandler) UpdateTransaction(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
id, err := uuid.Parse(idStr)
if err != nil {
http.Error(w, "invalid id", http.StatusBadRequest)
return
}
var t domain.FinancialTransaction
if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
t.ID = id
t.TenantID, _ = uuid.Parse(tenantID)
if err := h.repo.UpdateTransaction(&t); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) DeleteTransaction(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
if err := h.repo.DeleteTransaction(idStr, tenantID); err != nil {
log.Printf("❌ Error deleting transaction: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) UpdateEntity(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
id, err := uuid.Parse(idStr)
if err != nil {
http.Error(w, "invalid id", http.StatusBadRequest)
return
}
var e domain.Entity
if err := json.NewDecoder(r.Body).Decode(&e); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
e.ID = id
e.TenantID, _ = uuid.Parse(tenantID)
if err := h.repo.UpdateEntity(&e); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) DeleteEntity(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
if err := h.repo.DeleteEntity(idStr, tenantID); err != nil {
log.Printf("❌ Error deleting entity: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) UpdateProduct(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
id, err := uuid.Parse(idStr)
if err != nil {
http.Error(w, "invalid id", http.StatusBadRequest)
return
}
var p domain.Product
if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
p.ID = id
p.TenantID, _ = uuid.Parse(tenantID)
if err := h.repo.UpdateProduct(&p); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) DeleteProduct(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
if err := h.repo.DeleteProduct(idStr, tenantID); err != nil {
log.Printf("❌ Error deleting product: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) UpdateBankAccount(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
id, err := uuid.Parse(idStr)
if err != nil {
http.Error(w, "invalid id", http.StatusBadRequest)
return
}
var a domain.BankAccount
if err := json.NewDecoder(r.Body).Decode(&a); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
a.ID = id
a.TenantID, _ = uuid.Parse(tenantID)
if err := h.repo.UpdateBankAccount(&a); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) DeleteBankAccount(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
if err := h.repo.DeleteBankAccount(idStr, tenantID); err != nil {
log.Printf("❌ Error deleting bank account: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (h *ERPHandler) DeleteOrder(w http.ResponseWriter, r *http.Request) {
tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
idStr := mux.Vars(r)["id"]
if err := h.repo.DeleteOrder(idStr, tenantID); err != nil {
log.Printf("❌ Error deleting order: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}