package expense import ( "errors" "time" "github.com/gofiber/fiber/v2" "github.com/jackc/pgx/v5" "github.com/techxcar/backend/internal/auth" "github.com/techxcar/backend/pkg/database" ) var allowedTypes = map[string]bool{ "fuel": true, "parts": true, "tools": true, "other": true, } func RegisterRoutes(app *fiber.App, db *database.DB, secret string) { ro := []fiber.Handler{ auth.RequireAuth(secret), auth.RequireRole("tenant_admin", "manager", "technician"), auth.TenantMiddleware(db), } write := []fiber.Handler{ auth.RequireAuth(secret), auth.RequireRole("tenant_admin", "manager"), auth.TenantMiddleware(db), } app.Get("/api/v1/expenses", append(ro, listExpensesH())...) app.Post("/api/v1/expenses", append(write, createExpenseH())...) app.Delete("/api/v1/expenses/:id", append(write, deleteExpenseH())...) } func listExpensesH() fiber.Handler { return func(c *fiber.Ctx) error { conn := auth.GetConn(c) list, err := ListExpenses(c.Context(), conn, c.Query("type")) if err != nil { return fiber.NewError(500, "erro ao listar despesas") } if list == nil { list = []*Expense{} } return c.JSON(fiber.Map{"data": list, "error": nil}) } } type expenseBody struct { VehicleID string `json:"vehicle_id"` Type string `json:"type"` Amount float64 `json:"amount"` Description string `json:"description"` Date string `json:"date"` // YYYY-MM-DD } func createExpenseH() fiber.Handler { return func(c *fiber.Ctx) error { var b expenseBody if err := c.BodyParser(&b); err != nil { return fiber.NewError(400, "corpo do pedido inválido") } if !allowedTypes[b.Type] { return fiber.NewError(400, "tipo inválido: fuel, parts, tools, other") } if b.Amount <= 0 { return fiber.NewError(400, "valor deve ser positivo") } if b.Date == "" { return fiber.NewError(400, "data obrigatória") } date, err := time.Parse("2006-01-02", b.Date) if err != nil { return fiber.NewError(400, "data inválida (formato: YYYY-MM-DD)") } var vehicleID *string if b.VehicleID != "" { vehicleID = &b.VehicleID } conn := auth.GetConn(c) e, err := CreateExpense(c.Context(), conn, vehicleID, b.Type, b.Description, b.Amount, date) if err != nil { return fiber.NewError(500, "erro ao registar despesa") } return c.Status(201).JSON(fiber.Map{"data": e, "error": nil}) } } func deleteExpenseH() fiber.Handler { return func(c *fiber.Ctx) error { id := c.Params("id") conn := auth.GetConn(c) err := DeleteExpense(c.Context(), conn, id) if errors.Is(err, pgx.ErrNoRows) { return fiber.NewError(404, "despesa não encontrada") } if err != nil { return fiber.NewError(500, "erro ao eliminar despesa") } return c.SendStatus(204) } }