Files
soft_usite/rest/controllers/ai_config_controller.go
T
2026-06-04 22:49:16 -05:00

178 lines
5.5 KiB
Go

package controllers
import (
"math"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
)
// AiConfigIndex renderiza la vista del panel de configuraciones de IA.
func AiConfigIndex(c *fiber.Ctx) error {
data := fiber.Map{
"user": c.Locals("user").(map[string]interface{}),
"modules": c.Locals("userModules"),
}
return c.Render("ai_config", data, "layouts/main")
}
// GetAiConfigs devuelve la lista paginada en JSON.
func GetAiConfigs(c *fiber.Ctx) error {
page, _ := strconv.Atoi(c.Query("page", "1"))
if page < 1 {
page = 1
}
limit := 20
offset := (page - 1) * limit
search := c.Query("search", "")
items, total, err := models.GetAllAiConfigs(limit, offset, search)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
// Ocultar la API key en el listado (mostrar solo últimos 4 chars)
type safe struct {
ID uint `json:"ID"`
Nombre string `json:"nombre"`
Provider string `json:"provider"`
ApiKeyHint string `json:"api_key_hint"`
BaseURL string `json:"base_url"`
ModelName string `json:"model_name"`
IsActive bool `json:"is_active"`
Notes string `json:"notes"`
Modulo string `json:"modulo"`
}
safeItems := make([]safe, len(items))
for i, it := range items {
hint := "••••"
if len(it.ApiKey) > 4 {
hint = "••••" + it.ApiKey[len(it.ApiKey)-4:]
}
safeItems[i] = safe{
ID: it.ID,
Nombre: it.Nombre,
Provider: it.Provider,
ApiKeyHint: hint,
BaseURL: it.BaseURL,
ModelName: it.ModelName,
IsActive: it.IsActive,
Notes: it.Notes,
Modulo: it.Modulo,
}
}
return c.JSON(fiber.Map{
"items": safeItems,
"total": total,
"totalPages": int(math.Ceil(float64(total) / float64(limit))),
"page": page,
})
}
// CreateAiConfigHandler crea una nueva configuración de IA.
func CreateAiConfigHandler(c *fiber.Ctx) error {
type Req struct {
Nombre string `json:"nombre"`
Provider string `json:"provider"`
ApiKey string `json:"api_key"`
BaseURL string `json:"base_url"`
ModelName string `json:"model_name"`
IsActive bool `json:"is_active"`
Notes string `json:"notes"`
Modulo string `json:"modulo"`
}
var req Req
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
}
if strings.TrimSpace(req.Nombre) == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "nombre es requerido"})
}
if strings.TrimSpace(req.Provider) == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "provider es requerido"})
}
if strings.TrimSpace(req.ApiKey) == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "api_key es requerido"})
}
item := models.AiConfig{
Nombre: strings.TrimSpace(req.Nombre),
Provider: strings.ToLower(strings.TrimSpace(req.Provider)),
ApiKey: strings.TrimSpace(req.ApiKey),
BaseURL: strings.TrimSpace(req.BaseURL),
ModelName: strings.TrimSpace(req.ModelName),
IsActive: req.IsActive,
Notes: req.Notes,
Modulo: models.JoinModulos(strings.Split(req.Modulo, ",")),
}
if err := models.CreateAiConfig(&item); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"ok": true, "id": item.ID})
}
// UpdateAiConfigHandler actualiza una configuración de IA existente.
func UpdateAiConfigHandler(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 64)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"})
}
type Req struct {
Nombre string `json:"nombre"`
Provider string `json:"provider"`
ApiKey string `json:"api_key"` // vacío = no cambiar
BaseURL string `json:"base_url"`
ModelName string `json:"model_name"`
IsActive bool `json:"is_active"`
Notes string `json:"notes"`
Modulo string `json:"modulo"`
}
var req Req
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
}
updates := map[string]interface{}{
"nombre": strings.TrimSpace(req.Nombre),
"provider": strings.ToLower(strings.TrimSpace(req.Provider)),
"base_url": strings.TrimSpace(req.BaseURL),
"model_name": strings.TrimSpace(req.ModelName),
"is_active": req.IsActive,
"notes": req.Notes,
"modulo": models.JoinModulos(strings.Split(req.Modulo, ",")),
}
if strings.TrimSpace(req.ApiKey) != "" {
updates["api_key"] = strings.TrimSpace(req.ApiKey)
}
if err := models.UpdateAiConfig(uint(id), updates); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"ok": true})
}
// GetAiConfigSelect devuelve lista simple para selects
func GetAiConfigSelect(c *fiber.Ctx) error {
items, err := models.GetAiConfigSelect()
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"registros": items})
}
// DeleteAiConfigHandler elimina una configuración de IA.
func DeleteAiConfigHandler(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 64)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"})
}
if err := models.DeleteAiConfig(uint(id)); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"ok": true})
}