259 lines
8.5 KiB
Go
259 lines
8.5 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sujit-baniya/fiber-boilerplate/app"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
|
|
)
|
|
|
|
type PasoDiagnostico struct {
|
|
Paso string `json:"paso"`
|
|
OK bool `json:"ok"`
|
|
Mensaje string `json:"mensaje"`
|
|
Ms int64 `json:"ms"`
|
|
}
|
|
|
|
// EjecutarTestCiclo ejecuta el ciclo completo de notificaciones sobre datos temporales:
|
|
// 1. Envío de bienvenida
|
|
// 2. Marcar contrato como pagado + enviar confirmación de pago
|
|
// 3. Idempotencia (no reenviar si ya se envió hoy)
|
|
//
|
|
// Crea y destruye los datos de prueba dentro de la misma transacción de limpieza.
|
|
// POST /app/api/diagnostico/ciclo-notificaciones
|
|
func EjecutarTestCiclo(c *fiber.Ctx) error {
|
|
var body struct {
|
|
TestEmail string `json:"test_email"`
|
|
}
|
|
if err := c.BodyParser(&body); err != nil || body.TestEmail == "" {
|
|
return c.Status(400).JSON(fiber.Map{"error": "test_email requerido"})
|
|
}
|
|
|
|
db := app.Http.Database.DB
|
|
suffix := fmt.Sprintf("_diag_%d", time.Now().UnixNano())
|
|
pasos := []PasoDiagnostico{}
|
|
allOK := true
|
|
|
|
paso := func(nombre string, fn func() error) {
|
|
t0 := time.Now()
|
|
err := fn()
|
|
ms := time.Since(t0).Milliseconds()
|
|
ok := err == nil
|
|
msg := "OK"
|
|
if !ok {
|
|
msg = err.Error()
|
|
allOK = false
|
|
}
|
|
pasos = append(pasos, PasoDiagnostico{Paso: nombre, OK: ok, Mensaje: msg, Ms: ms})
|
|
}
|
|
|
|
// ── Datos temporales ──────────────────────────────────────────────────────
|
|
var plantBienvenida, plantPago models.PlantillaCorreo
|
|
var reglaBienvenida, reglaPago models.NotificacionRegla
|
|
var cliente models.Cliente
|
|
var contrato models.Contrato
|
|
|
|
// ── Cleanup siempre al finalizar ──────────────────────────────────────────
|
|
defer func() {
|
|
if contrato.ID > 0 {
|
|
db.Unscoped().Where("cliente_id = ?", cliente.ID).Delete(&models.NotificacionLog{})
|
|
db.Unscoped().Delete(&contrato)
|
|
}
|
|
if cliente.ID > 0 {
|
|
db.Unscoped().Delete(&cliente)
|
|
}
|
|
if reglaBienvenida.ID > 0 {
|
|
db.Unscoped().Delete(®laBienvenida)
|
|
}
|
|
if reglaPago.ID > 0 {
|
|
db.Unscoped().Delete(®laPago)
|
|
}
|
|
if plantBienvenida.ID > 0 {
|
|
db.Unscoped().Delete(&plantBienvenida)
|
|
}
|
|
if plantPago.ID > 0 {
|
|
db.Unscoped().Delete(&plantPago)
|
|
}
|
|
}()
|
|
|
|
// ── SETUP: crear datos de prueba ──────────────────────────────────────────
|
|
paso("setup: plantilla bienvenida", func() error {
|
|
plantBienvenida = models.PlantillaCorreo{
|
|
Nombre: "DIAG Bienvenida" + suffix,
|
|
Asunto: "[TEST] Bienvenido al sistema",
|
|
CuerpoHTML: "<p>Hola {{.ClienteNombre}}, bienvenido. Tu vencimiento es {{.FechaVencimiento}}.</p>",
|
|
Tipo: "bienvenida",
|
|
}
|
|
return db.Create(&plantBienvenida).Error
|
|
})
|
|
|
|
paso("setup: plantilla pago confirmado", func() error {
|
|
plantPago = models.PlantillaCorreo{
|
|
Nombre: "DIAG Pago Confirmado" + suffix,
|
|
Asunto: "[TEST] Tu pago fue recibido",
|
|
CuerpoHTML: "<p>Hola {{.ClienteNombre}}, recibimos tu pago de ${{.Total}}. ¡Gracias!</p>",
|
|
Tipo: "pago",
|
|
}
|
|
return db.Create(&plantPago).Error
|
|
})
|
|
|
|
paso("setup: regla bienvenida", func() error {
|
|
if plantBienvenida.ID == 0 {
|
|
return fmt.Errorf("plantilla bienvenida no creada")
|
|
}
|
|
reglaBienvenida = models.NotificacionRegla{
|
|
Nombre: "DIAG Regla Bienvenida" + suffix,
|
|
TipoEvento: "bienvenida",
|
|
PlantillaID: plantBienvenida.ID,
|
|
Activo: true,
|
|
AplicaA: "todos",
|
|
PasarelaEnlace: "ninguna",
|
|
}
|
|
return db.Create(®laBienvenida).Error
|
|
})
|
|
|
|
paso("setup: regla pago_recibido", func() error {
|
|
if plantPago.ID == 0 {
|
|
return fmt.Errorf("plantilla pago no creada")
|
|
}
|
|
reglaPago = models.NotificacionRegla{
|
|
Nombre: "DIAG Regla Pago" + suffix,
|
|
TipoEvento: "pago_recibido",
|
|
PlantillaID: plantPago.ID,
|
|
Activo: true,
|
|
AplicaA: "todos",
|
|
PasarelaEnlace: "ninguna",
|
|
}
|
|
return db.Create(®laPago).Error
|
|
})
|
|
|
|
paso("setup: cliente y contrato temporales", func() error {
|
|
cliente = models.Cliente{
|
|
Nombre: "DIAG Cliente" + suffix,
|
|
Email: body.TestEmail,
|
|
Empresa: "Diagnóstico Sistema",
|
|
Activo: true,
|
|
}
|
|
if err := db.Create(&cliente).Error; err != nil {
|
|
return err
|
|
}
|
|
now := time.Now()
|
|
contrato = models.Contrato{
|
|
ClienteID: cliente.ID,
|
|
Cliente: cliente,
|
|
FechaInicio: now,
|
|
FechaVencimiento: now.AddDate(1, 0, 0),
|
|
PrecioAcordado: 99.00,
|
|
Estado: "activo",
|
|
}
|
|
if err := db.Create(&contrato).Error; err != nil {
|
|
return err
|
|
}
|
|
contrato.Cliente = cliente
|
|
return nil
|
|
})
|
|
|
|
// Si el setup falló, no continuar con los pasos funcionales
|
|
if !allOK {
|
|
return c.JSON(fiber.Map{"pasos": pasos, "ok": false, "resumen": "Setup falló — ver pasos anteriores"})
|
|
}
|
|
|
|
// ── PASO 1: Enviar correo de bienvenida ───────────────────────────────────
|
|
paso("paso 1 — envío de bienvenida", func() error {
|
|
return services.EnviarNotificacionGrupo(®laBienvenida, &cliente, []models.Contrato{contrato}, "")
|
|
})
|
|
|
|
// Verificar log en DB
|
|
paso("paso 1 — verificar log en historial", func() error {
|
|
var count int64
|
|
db.Model(&models.NotificacionLog{}).
|
|
Where("cliente_id = ? AND regla_id = ? AND estado = 'enviado'", cliente.ID, reglaBienvenida.ID).
|
|
Count(&count)
|
|
if count == 0 {
|
|
return fmt.Errorf("no se encontró log con estado='enviado' para la regla bienvenida")
|
|
}
|
|
return nil
|
|
})
|
|
|
|
// ── PASO 2: Simular recepción de pago ─────────────────────────────────────
|
|
paso("paso 2 — marcar contrato como pagado", func() error {
|
|
return models.MarcarContratoPagado(contrato.ID)
|
|
})
|
|
|
|
paso("paso 2 — verificar pago_confirmado en DB", func() error {
|
|
var c models.Contrato
|
|
db.Select("pago_confirmado, fecha_pago").First(&c, contrato.ID)
|
|
if !c.PagoConfirmado {
|
|
return fmt.Errorf("pago_confirmado sigue siendo false tras MarcarContratoPagado")
|
|
}
|
|
if c.FechaPago == nil {
|
|
return fmt.Errorf("fecha_pago es nil tras MarcarContratoPagado")
|
|
}
|
|
return nil
|
|
})
|
|
|
|
paso("paso 2 — envío de confirmación de pago", func() error {
|
|
// EnviarCorreoConfirmacionPago es void — usar EnviarNotificacionGrupo directamente
|
|
// para capturar el error (la función void loguea pero no retorna)
|
|
reloadContrato, err := models.GetContratoByID(contrato.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return services.EnviarNotificacionGrupo(®laPago, &cliente, []models.Contrato{*reloadContrato}, "")
|
|
})
|
|
|
|
paso("paso 2 — verificar log de pago en historial", func() error {
|
|
var count int64
|
|
db.Model(&models.NotificacionLog{}).
|
|
Where("cliente_id = ? AND regla_id = ? AND estado = 'enviado'", cliente.ID, reglaPago.ID).
|
|
Count(&count)
|
|
if count == 0 {
|
|
return fmt.Errorf("no se encontró log con estado='enviado' para la regla pago_recibido")
|
|
}
|
|
return nil
|
|
})
|
|
|
|
// ── PASO 3: Idempotencia ──────────────────────────────────────────────────
|
|
paso("paso 3 — idempotencia (no reenviar si ya enviado hoy)", func() error {
|
|
// Verificar que YaEnviadoHoy retorna true para ambas reglas
|
|
if !models.YaEnviadoHoy(cliente.ID, reglaBienvenida.ID) {
|
|
return fmt.Errorf("YaEnviadoHoy debería ser true para bienvenida, pero retornó false")
|
|
}
|
|
if !models.YaEnviadoHoy(cliente.ID, reglaPago.ID) {
|
|
return fmt.Errorf("YaEnviadoHoy debería ser true para pago_recibido, pero retornó false")
|
|
}
|
|
return nil
|
|
})
|
|
|
|
// Contar emails en historial para el resumen
|
|
var totalLogs int64
|
|
db.Model(&models.NotificacionLog{}).Where("cliente_id = ?", cliente.ID).Count(&totalLogs)
|
|
|
|
// Serializar IDs para debug
|
|
idsJSON, _ := json.Marshal(map[string]uint{
|
|
"cliente_id": cliente.ID,
|
|
"contrato_id": contrato.ID,
|
|
"regla_bienvenida_id": reglaBienvenida.ID,
|
|
"regla_pago_id": reglaPago.ID,
|
|
"plantilla_bienvenida": plantBienvenida.ID,
|
|
"plantilla_pago": plantPago.ID,
|
|
})
|
|
|
|
resumen := fmt.Sprintf("Ciclo completado — %d emails enviados al historial, destinatario: %s",
|
|
totalLogs, body.TestEmail)
|
|
if !allOK {
|
|
resumen = "Ciclo con errores — revisar pasos"
|
|
}
|
|
|
|
return c.JSON(fiber.Map{
|
|
"pasos": pasos,
|
|
"ok": allOK,
|
|
"resumen": resumen,
|
|
"ids_tmp": string(idsJSON),
|
|
})
|
|
}
|