From 1e1ba682b0580c163f08d38ad733c2fd02a2d905 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:41:20 -0500 Subject: [PATCH] up --- pkg/models/ai_config.go | 69 +++++++++++++------- resources/views/ai_config.html | 81 ++++++++++++++++++------ rest/controllers/ai_config_controller.go | 4 +- 3 files changed, 110 insertions(+), 44 deletions(-) diff --git a/pkg/models/ai_config.go b/pkg/models/ai_config.go index 6bc52af..3ebe9ed 100644 --- a/pkg/models/ai_config.go +++ b/pkg/models/ai_config.go @@ -1,7 +1,9 @@ package models import ( + "fmt" "log" + "strings" "github.com/sujit-baniya/fiber-boilerplate/app" "gorm.io/gorm" @@ -70,39 +72,62 @@ func GetActiveAiConfig(provider string) (*AiConfig, error) { return &item, nil } +// SplitModulos parte el campo Modulo (comma-separated) en un slice limpio. +// "" → [] (config global), "landing,query_runner" → ["landing","query_runner"] +func SplitModulos(modulo string) []string { + var out []string + for _, s := range strings.Split(modulo, ",") { + if s = strings.TrimSpace(s); s != "" { + out = append(out, s) + } + } + return out +} + +// JoinModulos normaliza y une un slice de módulos en comma-separated. +func JoinModulos(modules []string) string { + var clean []string + for _, s := range modules { + if s = strings.TrimSpace(s); s != "" { + clean = append(clean, s) + } + } + return strings.Join(clean, ",") +} + // GetAiConfigForService retorna la config activa asignada al módulo indicado. // Lógica de prioridad: -// 1. Config activa con modulo == service (exclusiva del servicio) +// 1. Config activa con modulo conteniendo service (puede ser comma-separated) // 2. Config activa con modulo == "" (global, fallback) // 3. Cualquier config activa (último recurso) func GetAiConfigForService(service string) (*AiConfig, error) { - var item AiConfig + var items []AiConfig + if err := app.Http.Database.DB.Where("is_active = ?", true).Order("id ASC").Find(&items).Error; err != nil { + return nil, fmt.Errorf("error leyendo ai_configs: %w", err) + } + if len(items) == 0 { + return nil, fmt.Errorf("no hay configs de IA activas") + } - // 1. Buscar config específica para el servicio + // 1. Config específica para el servicio (puede tener varios módulos) if service != "" { - err := app.Http.Database.DB. - Where("is_active = ? AND modulo = ?", true, service). - First(&item).Error - if err == nil { - return &item, nil + for i := range items { + for _, m := range SplitModulos(items[i].Modulo) { + if m == service { + return &items[i], nil + } + } } } - // 2. Buscar config global (modulo vacío) - err := app.Http.Database.DB. - Where("is_active = ? AND (modulo = '' OR modulo IS NULL)", true). - First(&item).Error - if err == nil { - return &item, nil + // 2. Config global (modulo vacío = sin restricción de servicio) + for i := range items { + if strings.TrimSpace(items[i].Modulo) == "" { + return &items[i], nil + } } // 3. Cualquier config activa como último recurso - err = app.Http.Database.DB. - Where("is_active = ?", true). - First(&item).Error - if err != nil { - log.Printf("[AI_CONFIG] No se encontró config activa para servicio '%s': %v", service, err) - return nil, err - } - return &item, nil + log.Printf("[AI_CONFIG] No se encontró config para servicio '%s', usando cualquier activa", service) + return &items[0], nil } diff --git a/resources/views/ai_config.html b/resources/views/ai_config.html index 47ca1ed..cdceaac 100644 --- a/resources/views/ai_config.html +++ b/resources/views/ai_config.html @@ -64,14 +64,22 @@
- Asigna esta IA a un servicio específico. "Global" actúa de fallback cuando un servicio no tiene IA propia. + "Global" actúa de fallback. Si seleccionas servicios específicos, solo se usará para ellos.