up
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
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),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user