package models import ( "time" "github.com/sujit-baniya/fiber-boilerplate/app" "gorm.io/gorm" ) // UmindVigilancia mira una API cada tanto y avisa cuando pasa algo: // "avisame por correo cuando esta API devuelva stock en cero". // // Apunta a una HERRAMIENTA ya configurada del agente y no a una URL libre. // Así hereda entero el blindaje de LlamarHerramientaWebhook —resolución de DNS // en el connect, IPs internas rechazadas, sin redirects, respuesta acotada— // sin escribir una línea de eso de nuevo. type UmindVigilancia struct { gorm.Model AgenteID uint `json:"agente_id" gorm:"column:agente_id;index;not null"` TenantID uint `json:"tenant_id" gorm:"column:tenant_id;index"` Nombre string `json:"nombre" gorm:"column:nombre;size:150;not null"` Herramienta string `json:"herramienta" gorm:"column:herramienta;size:60;not null"` // Condicion en lenguaje natural: "el stock está en cero", "hay pedidos sin // despachar hace más de dos días". Condicion string `json:"condicion" gorm:"column:condicion;type:text;not null"` IntervaloMin int `json:"intervalo_min" gorm:"column:intervalo_min;default:30"` Destino string `json:"destino" gorm:"column:destino;size:120"` Activa bool `json:"activa" gorm:"column:activa;default:true"` // HashUltimo es lo que evita quemar plata: si la respuesta no cambió, no // hay nada que evaluar y no se gasta un token. HashUltimo string `json:"-" gorm:"column:hash_ultimo;size:64"` // EnCondicion recuerda si la última evaluación dio que sí. Se avisa al // ENTRAR en condición, no en cada chequeo que la siga cumpliendo — es la // lección que el monitor de sitios ya aprendió con las transiciones. EnCondicion bool `json:"en_condicion" gorm:"column:en_condicion;default:false"` UltimoCheckAt *time.Time `json:"ultimo_check_at" gorm:"column:ultimo_check_at"` UltimoError string `json:"ultimo_error" gorm:"column:ultimo_error;type:text"` FallosNoOk int `json:"-" gorm:"column:fallos_no_ok;default:0"` } func (UmindVigilancia) TableName() string { return "umind_vigilancias" } // UmindVigilanciaMax acota cuántas puede tener un agente: cada una es una // llamada saliente y, cuando cambia, una consulta a la IA. const UmindVigilanciaMax = 5 // UmindVigilanciaIntervaloMin es el piso. Menos que esto es martillarle la API // a un tercero para ganar segundos que un aviso no necesita. const UmindVigilanciaIntervaloMin = 5 func CreateUmindVigilancia(v *UmindVigilancia) error { var n int64 app.Http.Database.DB.Model(&UmindVigilancia{}). Where("agente_id = ? AND activa = ? AND deleted_at IS NULL", v.AgenteID, true).Count(&n) if n >= UmindVigilanciaMax { return gorm.ErrInvalidData } if v.IntervaloMin < UmindVigilanciaIntervaloMin { v.IntervaloMin = 30 } return app.Http.Database.DB.Create(v).Error } func GetUmindVigilanciasByAgente(agenteID uint) ([]UmindVigilancia, error) { var items []UmindVigilancia err := app.Http.Database.DB.Where("agente_id = ?", agenteID). Order("created_at DESC").Find(&items).Error return items, err } func GetUmindVigilanciaByID(id uint) (*UmindVigilancia, error) { var v UmindVigilancia if err := app.Http.Database.DB.First(&v, id).Error; err != nil { return nil, err } return &v, nil } func DeleteUmindVigilancia(id uint) error { return app.Http.Database.DB.Delete(&UmindVigilancia{}, id).Error } // GetUmindVigilanciasPendientes devuelve las que ya les toca según su propio // intervalo, igual que los canales de correo. func GetUmindVigilanciasPendientes() ([]UmindVigilancia, error) { var items []UmindVigilancia err := app.Http.Database.DB. Where("activa = ? AND deleted_at IS NULL", true). Where("ultimo_check_at IS NULL OR ultimo_check_at < NOW() - (intervalo_min || ' minutes')::interval"). Limit(200).Find(&items).Error return items, err } func ActualizarVigilancia(id uint, updates map[string]interface{}) { ahora := time.Now() updates["ultimo_check_at"] = &ahora app.Http.Database.DB.Model(&UmindVigilancia{}).Where("id = ?", id).Updates(updates) } // DesactivarVigilancia la apaga tras demasiados fallos seguidos. Una API que // dejó de existir no puede seguir consultándose para siempre — ni gastando el // plan de quien la configuró. func DesactivarVigilancia(id uint, motivo string) { app.Http.Database.DB.Model(&UmindVigilancia{}).Where("id = ?", id). Updates(map[string]interface{}{"activa": false, "ultimo_error": motivo}) }