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 @@
-
-
+
+ Global
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
- 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.