package controllers import ( "strconv" "strings" "github.com/gofiber/fiber/v2" "github.com/sujit-baniya/fiber-boilerplate/pkg/models" "github.com/sujit-baniya/fiber-boilerplate/pkg/services" ) // La bandeja de pendientes: lo que el asistente preparó y espera tu visto bueno. // GetUmindAccionesHandler — GET /umind/acciones?tenant_id=N&historial=1 func GetUmindAccionesHandler(c *fiber.Ctx) error { tenantID, _ := strconv.ParseUint(c.Query("tenant_id"), 10, 64) if err := accesoTenant(c, uint(tenantID)); err != nil { return err } items, err := models.GetUmindAccionesPendientes(uint(tenantID), c.Query("historial") == "1") if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{ "items": items, "pendientes": models.ContarUmindAccionesPendientes(uint(tenantID)), }) } // AprobarUmindAccionHandler ejecuta el payload guardado, tal cual se aprobó. // POST /umind/acciones/:id/aprobar func AprobarUmindAccionHandler(c *fiber.Ctx) error { accion, err := accionConAcceso(c) if err != nil { return err } if accion.Estado != "pendiente" { return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": "esa solicitud ya fue resuelta"}) } if err := services.EjecutarAccionAprobada(accion, quienResuelve(c)); err != nil { return c.Status(fiber.StatusBadGateway).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true}) } // RechazarUmindAccionHandler descarta la acción. El motivo es para el dueño, // no para el cliente: al cliente se le dice que le responde una persona. // POST /umind/acciones/:id/rechazar {motivo} func RechazarUmindAccionHandler(c *fiber.Ctx) error { accion, err := accionConAcceso(c) if err != nil { return err } if accion.Estado != "pendiente" { return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": "esa solicitud ya fue resuelta"}) } var req struct { Motivo string `json:"motivo"` } _ = c.BodyParser(&req) if err := models.CerrarAccion(accion.ID, "rechazada", quienResuelve(c), strings.TrimSpace(req.Motivo), ""); err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true}) } func accionConAcceso(c *fiber.Ctx) (*models.UmindAccionPendiente, error) { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return nil, c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"}) } accion, err := models.GetUmindAccionByID(uint(id)) if err != nil { return nil, errSinAcceso(c) } if err := accesoTenant(c, accion.TenantID); err != nil { return nil, err } return accion, nil } // quienResuelve deja registrado quién aprobó. No hay roles dentro de un // cliente: aprueba cualquiera de sus usuarios, y por eso importa el nombre. func quienResuelve(c *fiber.Ctx) string { if u, ok := c.Locals("portal_user").(*models.PortalUser); ok && u != nil { return u.Nombre + " <" + u.Email + ">" } return "staff" }