package workorder import ( "errors" "github.com/gofiber/fiber/v2" "github.com/jackc/pgx/v5" "github.com/techxcar/backend/internal/auth" "github.com/techxcar/backend/pkg/database" ) 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/work-orders", append(ro, listWOsH())...) app.Post("/api/v1/work-orders", append(write, createWOH())...) app.Get("/api/v1/work-orders/:id", append(ro, getWODetailH())...) app.Put("/api/v1/work-orders/:id", append(write, updateWOH())...) app.Post("/api/v1/work-orders/:id/transition", append(write, transitionWOH())...) app.Post("/api/v1/work-orders/:id/items", append(write, addItemH())...) app.Delete("/api/v1/work-orders/:id/items/:itemId", append(write, removeItemH())...) app.Post("/api/v1/work-orders/:id/staff-hours", append(write, addStaffHoursH())...) app.Delete("/api/v1/work-orders/:id/staff-hours/:shId", append(write, removeStaffHoursH())...) } func listWOsH() fiber.Handler { return func(c *fiber.Ctx) error { conn := auth.GetConn(c) list, err := ListWorkOrders(c.Context(), conn, c.Query("status")) if err != nil { return fiber.NewError(500, "erro ao listar ordens") } if list == nil { list = []*WorkOrder{} } return c.JSON(fiber.Map{"data": list, "error": nil}) } } type woBody struct { ClientID string `json:"client_id"` VehicleID string `json:"vehicle_id"` InternalNotes string `json:"internal_notes"` ClientNotes string `json:"client_notes"` } func createWOH() fiber.Handler { return func(c *fiber.Ctx) error { var b woBody if err := c.BodyParser(&b); err != nil { return fiber.NewError(400, "corpo inválido") } claims, _ := c.Locals("claims").(*auth.Claims) createdBy := "" if claims != nil { createdBy = claims.UserID } conn := auth.GetConn(c) wo, err := CreateWorkOrder(c.Context(), conn, b.ClientID, b.VehicleID, b.InternalNotes, createdBy) if err != nil { return fiber.NewError(500, "erro ao criar ordem") } return c.Status(201).JSON(fiber.Map{"data": wo, "error": nil}) } } func getWODetailH() fiber.Handler { return func(c *fiber.Ctx) error { conn := auth.GetConn(c) detail, err := GetWorkOrderDetail(c.Context(), conn, c.Params("id")) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return fiber.NewError(404, "ordem não encontrada") } return fiber.NewError(500, "erro ao obter ordem") } return c.JSON(fiber.Map{"data": detail, "error": nil}) } } func updateWOH() fiber.Handler { return func(c *fiber.Ctx) error { var b woBody if err := c.BodyParser(&b); err != nil { return fiber.NewError(400, "corpo inválido") } conn := auth.GetConn(c) wo, err := UpdateWorkOrder(c.Context(), conn, c.Params("id"), b.ClientID, b.VehicleID, b.InternalNotes, b.ClientNotes) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return fiber.NewError(404, "ordem não encontrada") } return fiber.NewError(500, "erro ao actualizar ordem") } return c.JSON(fiber.Map{"data": wo, "error": nil}) } } func transitionWOH() fiber.Handler { return func(c *fiber.Ctx) error { var body struct { Status string `json:"status"` } if err := c.BodyParser(&body); err != nil || body.Status == "" { return fiber.NewError(400, "status é obrigatório") } claims, _ := c.Locals("claims").(*auth.Claims) changedBy := "" if claims != nil { changedBy = claims.UserID } conn := auth.GetConn(c) wo, err := TransitionStatus(c.Context(), conn, c.Params("id"), body.Status, changedBy) if err != nil { return fiber.NewError(400, err.Error()) } return c.JSON(fiber.Map{"data": wo, "error": nil}) } } type woItemBody struct { CatalogItemID string `json:"catalog_item_id"` Description string `json:"description"` Qty float64 `json:"qty"` UnitPrice float64 `json:"unit_price"` DiscountPct float64 `json:"discount_pct"` } func addItemH() fiber.Handler { return func(c *fiber.Ctx) error { var b woItemBody if err := c.BodyParser(&b); err != nil { return fiber.NewError(400, "corpo inválido") } if b.Description == "" || b.Qty <= 0 || b.UnitPrice < 0 { return fiber.NewError(400, "descrição, quantidade e preço unitário são obrigatórios") } conn := auth.GetConn(c) item, err := AddItem(c.Context(), conn, c.Params("id"), b.CatalogItemID, b.Description, b.Qty, b.UnitPrice, b.DiscountPct) if err != nil { return fiber.NewError(500, "erro ao adicionar item") } return c.Status(201).JSON(fiber.Map{"data": item, "error": nil}) } } func removeItemH() fiber.Handler { return func(c *fiber.Ctx) error { conn := auth.GetConn(c) if err := RemoveItem(c.Context(), conn, c.Params("id"), c.Params("itemId")); err != nil { return fiber.NewError(500, "erro ao remover item") } return c.SendStatus(204) } } type staffHoursBody struct { StaffID string `json:"staff_id"` Hours float64 `json:"hours"` CostPerHour float64 `json:"cost_per_hour"` } func addStaffHoursH() fiber.Handler { return func(c *fiber.Ctx) error { var b staffHoursBody if err := c.BodyParser(&b); err != nil { return fiber.NewError(400, "corpo inválido") } if b.StaffID == "" || b.Hours <= 0 { return fiber.NewError(400, "funcionário e horas são obrigatórios") } conn := auth.GetConn(c) sh, err := AddStaffHours(c.Context(), conn, c.Params("id"), b.StaffID, b.Hours, b.CostPerHour) if err != nil { return fiber.NewError(500, "erro ao adicionar horas") } return c.Status(201).JSON(fiber.Map{"data": sh, "error": nil}) } } func removeStaffHoursH() fiber.Handler { return func(c *fiber.Ctx) error { conn := auth.GetConn(c) if err := RemoveStaffHours(c.Context(), conn, c.Params("id"), c.Params("shId")); err != nil { return fiber.NewError(500, "erro ao remover horas") } return c.SendStatus(204) } }