171 lines
7.7 KiB
Go
171 lines
7.7 KiB
Go
package models
|
|
|
|
import (
|
|
"github.com/sujit-baniya/fiber-boilerplate/app"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// SaasApiConfig almacena la configuración del endpoint externo al que se notifica
|
|
// cuando un pago es confirmado para un producto SaaS.
|
|
// La vinculación es: Contrato → Servicios (m2m) → servicio_id ↔ SaasProducto.ServicioID → SaasApiConfig.SaasID
|
|
type SaasApiConfig struct {
|
|
gorm.Model
|
|
SaasID uint `json:"saas_id" gorm:"column:saas_id;not null;index"`
|
|
SaasProducto SaasProducto `json:"saas_producto" gorm:"foreignKey:SaasID"`
|
|
Nombre string `json:"nombre" gorm:"column:nombre;not null"` // etiqueta amigable
|
|
// Pasarela que dispara este callback: dlocal | bold | ambas (default)
|
|
Pasarela string `json:"pasarela" gorm:"column:pasarela;default:'ambas'"`
|
|
EndpointURL string `json:"endpoint_url" gorm:"column:endpoint_url;type:text;not null"`
|
|
Metodo string `json:"metodo" gorm:"column:metodo;default:'POST'"` // POST|PUT|GET
|
|
ApiKeyHeader string `json:"api_key_header" gorm:"column:api_key_header"` // ej: "X-API-Key"
|
|
ApiKeyValue string `json:"api_key_value" gorm:"column:api_key_value;type:text"` // valor secreto
|
|
// PayloadTemplate es un JSON con marcadores que se reemplazarán antes de enviar.
|
|
// Variables disponibles: {{.ContratoID}} {{.Referencia}} {{.Email}} {{.Monto}} {{.Moneda}} {{.SaasID}} {{.SaasSlug}} {{.Fuente}} {{.WebhookToken}}
|
|
PayloadTemplate string `json:"payload_template" gorm:"column:payload_template;type:text"`
|
|
TimeoutSeg int `json:"timeout_seg" gorm:"column:timeout_seg;default:10"`
|
|
Activo bool `json:"activo" gorm:"column:activo;default:true"`
|
|
// WebhookToken es un token único por integración que identifica las llamadas entrantes
|
|
// desde el SaaS externo vía POST /webhooks/saas-in/{token}
|
|
WebhookToken string `json:"webhook_token" gorm:"column:webhook_token;uniqueIndex;size:64"`
|
|
}
|
|
|
|
func (SaasApiConfig) TableName() string { return "saas_api_configs" }
|
|
|
|
// ─── SaasWebhookInLog ─────────────────────────────────────────────────────────
|
|
|
|
// SaasWebhookInLog registra cada llamada entrante desde un SaaS externo
|
|
// identificado por su WebhookToken único.
|
|
type SaasWebhookInLog struct {
|
|
gorm.Model
|
|
SaasApiConfigID uint `json:"saas_api_config_id" gorm:"column:saas_api_config_id;index"`
|
|
Token string `json:"token" gorm:"column:token;size:64;index"`
|
|
Metodo string `json:"metodo" gorm:"column:metodo;size:10"`
|
|
IP string `json:"ip" gorm:"column:ip;size:64"`
|
|
Body string `json:"body" gorm:"column:body;type:text"`
|
|
Headers string `json:"headers" gorm:"column:headers;type:text"`
|
|
}
|
|
|
|
func (SaasWebhookInLog) TableName() string { return "saas_webhook_in_logs" }
|
|
|
|
// ─── SaasDispatchLog ──────────────────────────────────────────────────────────
|
|
|
|
// SaasDispatchLog registra cada intento de notificación a un SaaS externo.
|
|
type SaasDispatchLog struct {
|
|
gorm.Model
|
|
SaasApiConfigID uint `json:"saas_api_config_id" gorm:"column:saas_api_config_id;index"`
|
|
SaasApiConfig SaasApiConfig `json:"saas_api_config" gorm:"foreignKey:SaasApiConfigID"`
|
|
ContratoID uint `json:"contrato_id" gorm:"column:contrato_id;index"`
|
|
Referencia string `json:"referencia" gorm:"column:referencia"`
|
|
PayerEmail string `json:"payer_email" gorm:"column:payer_email"`
|
|
Fuente string `json:"fuente" gorm:"column:fuente"` // dlocal | bold | manual
|
|
HttpStatus int `json:"http_status" gorm:"column:http_status"`
|
|
Respuesta string `json:"respuesta" gorm:"column:respuesta;type:text"`
|
|
ErrorMsg string `json:"error_msg" gorm:"column:error_msg;type:text"`
|
|
Estado string `json:"estado" gorm:"column:estado"` // success | failed
|
|
Intentos int `json:"intentos" gorm:"column:intentos;default:1"`
|
|
}
|
|
|
|
func (SaasDispatchLog) TableName() string { return "saas_dispatch_logs" }
|
|
|
|
// ─── Queries SaasApiConfig ────────────────────────────────────────────────────
|
|
|
|
func GetAllSaasApiConfigs(limit, offset int) ([]SaasApiConfig, int64, error) {
|
|
var items []SaasApiConfig
|
|
var total int64
|
|
db := app.Http.Database.DB.Model(&SaasApiConfig{}).Preload("SaasProducto")
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if err := db.Order("created_at DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return items, total, nil
|
|
}
|
|
|
|
func GetSaasApiConfigByID(id uint) (*SaasApiConfig, error) {
|
|
var item SaasApiConfig
|
|
if err := app.Http.Database.DB.Preload("SaasProducto").First(&item, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &item, nil
|
|
}
|
|
|
|
// GetSaasApiConfigsBySaasIDs devuelve configuraciones activas para los saas_ids dados,
|
|
// opcionalmente filtradas por pasarela ("dlocal", "bold" o "" para todas).
|
|
func GetSaasApiConfigsBySaasIDs(saasIDs []uint, pasarela string) ([]SaasApiConfig, error) {
|
|
if len(saasIDs) == 0 {
|
|
return nil, nil
|
|
}
|
|
db := app.Http.Database.DB.
|
|
Preload("SaasProducto").
|
|
Where("saas_id IN ? AND activo = ?", saasIDs, true)
|
|
if pasarela != "" {
|
|
db = db.Where("pasarela = ? OR pasarela = 'ambas'", pasarela)
|
|
}
|
|
var items []SaasApiConfig
|
|
if err := db.Find(&items).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
func CreateSaasApiConfig(item *SaasApiConfig) error {
|
|
return app.Http.Database.DB.Create(item).Error
|
|
}
|
|
|
|
func UpdateSaasApiConfig(item *SaasApiConfig) error {
|
|
return app.Http.Database.DB.Save(item).Error
|
|
}
|
|
|
|
func DeleteSaasApiConfig(id uint) error {
|
|
return app.Http.Database.DB.Delete(&SaasApiConfig{}, id).Error
|
|
}
|
|
|
|
// GetSaasApiConfigByWebhookToken busca una integración por su token de webhook entrante.
|
|
func GetSaasApiConfigByWebhookToken(token string) (*SaasApiConfig, error) {
|
|
var item SaasApiConfig
|
|
if err := app.Http.Database.DB.Preload("SaasProducto").
|
|
Where("webhook_token = ? AND activo = true", token).
|
|
First(&item).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &item, nil
|
|
}
|
|
|
|
// SaveSaasWebhookInLog persiste un log de webhook entrante.
|
|
func SaveSaasWebhookInLog(entry *SaasWebhookInLog) error {
|
|
return app.Http.Database.DB.Create(entry).Error
|
|
}
|
|
|
|
// ─── Queries SaasDispatchLog ──────────────────────────────────────────────────
|
|
|
|
func SaveSaasDispatchLog(entry *SaasDispatchLog) error {
|
|
return app.Http.Database.DB.Create(entry).Error
|
|
}
|
|
|
|
func GetSaasDispatchLogs(limit, offset int) ([]SaasDispatchLog, int64, error) {
|
|
var items []SaasDispatchLog
|
|
var total int64
|
|
db := app.Http.Database.DB.Model(&SaasDispatchLog{}).Preload("SaasApiConfig")
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if err := db.Order("created_at DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return items, total, nil
|
|
}
|
|
|
|
// GetDispatchLogsByContratoID devuelve los pagos/dispatches de un contrato específico
|
|
func GetDispatchLogsByContratoID(contratoID uint) ([]SaasDispatchLog, error) {
|
|
var items []SaasDispatchLog
|
|
if err := app.Http.Database.DB.
|
|
Where("contrato_id = ?", contratoID).
|
|
Order("created_at DESC").
|
|
Limit(50).
|
|
Find(&items).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|