DevBlog Jon Quintanilla

Mis Aportaciones al proyecto Tuxeria

Introducción a los Eventos del Sistema

Publicado: Noviembre 2023

El sistema Tuxeria implementa 3 eventos programados que ejecutan tareas de mantenimiento y análisis de forma automática y periódica. Estos eventos trabajan sobre las tablas auxiliares creadas previamente para optimización.

Características principales de los eventos:

Importante: Para que los eventos funcionen, debe estar activado el event scheduler:

SET GLOBAL event_scheduler = ON;

Evento 1: topclientes

Programación: Cada 1 minuto

Código completo:

DROP EVENT IF EXISTS topclientes; DELIMITER // CREATE EVENT topclientes ON SCHEDULE EVERY 1 MINUTE DO BEGIN TRUNCATE TABLE top_clientes; INSERT INTO top_clientes (nombre, cant_pedidos, cant_pizzas) SELECT C.nombre, COUNT(DISTINCT P.num_pedido) AS Pedidos_Mes_Anterior, IFNULL(SUM(LP.unidades), 0) AS Unidades_Mes_Anterior FROM Cliente C LEFT JOIN Pedido P ON C.DNI = P.dni_cliente AND P.fechahora >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01') AND P.fechahora < DATE_FORMAT(CURDATE(), '%Y-%m-01') LEFT JOIN LineaPedido LP ON P.num_pedido = LP.num_pedido GROUP BY C.DNI, C.nombre HAVING Pedidos_Mes_Anterior >= 5 OR Unidades_Mes_Anterior >= 9 ORDER BY Pedidos_Mes_Anterior DESC, C.nombre; END //

Funcionamiento:

Lógica del filtro temporal:

P.fechahora >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01') AND P.fechahora < DATE_FORMAT(CURDATE(), '%Y-%m-01')

Este filtro selecciona pedidos del mes completo anterior (ej: si hoy es 15/11, selecciona pedidos de octubre).

Ejemplo de datos generados:

nombre cant_pedidos cant_pizzas
Juan Pérez 7 12
María García 5 8
Carlos López 4 10

Carlos López aparece porque tiene 10 pizzas (cumple el segundo criterio).

Evento 2: clientesanti

Programación: Cada 10 minutos

Código completo (simplificado):

CREATE EVENT clientesanti ON SCHEDULE EVERY 10 MINUTE ON COMPLETION PRESERVE ENABLE DO BEGIN -- Declaración de variables y cursor DECLARE c CURSOR FOR SELECT c.*, p.fechahora FROM Cliente c JOIN Pedido p ON c.DNI = p.dni_cliente GROUP BY c.DNI HAVING TIMESTAMPDIFF(YEAR, MAX(p.fechahora), CURDATE()) >= 1; -- Lógica con cursor para procesar cada cliente -- ... TRUNCATE TABLE clientes_antiguos; -- Inserta clientes inactivos en la tabla de archivo END //

Funcionamiento:

Lógica del cursor:

  1. Selecciona clientes que han hecho al menos un pedido
  2. Agrupa por DNI para obtener el último pedido de cada cliente
  3. Filtra aquellos cuyo último pedido fue hace 1 año o más
  4. Procesa cada resultado con un cursor

Condición clave:

TIMESTAMPDIFF(YEAR, MAX(p.fechahora), CURDATE()) >= 1

Esta condición calcula la diferencia en años entre la fecha del último pedido y la fecha actual.

Problema potencial:

El evento no considera clientes sin pedidos porque hace JOIN con la tabla Pedido. Un cliente registrado hace más de 1 año pero sin pedidos no sería archivado.

Evento 3: clientessinped

Programación: Cada 10 minutos

Código completo (simplificado):

CREATE EVENT clientessinped ON SCHEDULE EVERY 10 MINUTE ON COMPLETION PRESERVE ENABLE DO BEGIN -- Cursor para clientes nuevos sin pedidos DECLARE c CURSOR FOR SELECT * FROM Cliente WHERE TIMESTAMPDIFF(MONTH, fecha_alta, CURDATE()) >= 1 AND ped_realizados = 0; -- Procesamiento con cursor -- ... TRUNCATE TABLE clientes_nuevossinped; -- Inserta clientes nuevos sin pedidos END //

Funcionamiento:

Condiciones de filtrado:

TIMESTAMPDIFF(MONTH, fecha_alta, CURDATE()) >= 1 AND ped_realizados = 0

Esta lógica aprovecha el campo ped_realizados que mantienen los triggers, evitando un JOIN costoso con la tabla Pedido.

Propósito de negocio:

Identificar clientes potenciales que se registraron pero no completaron ninguna compra, útil para campañas de remarketing o seguimiento comercial.

Análisis Comparativo de Eventos

Resumen de funcionalidades:

Evento Frecuencia Tabla Destino Propósito
topclientes 1 minuto top_clientes Identificar clientes VIP
clientesanti 10 minutos clientes_antiguos Archivar clientes inactivos
clientessinped 10 minutos clientes_nuevossinped Identificar leads no convertidos

Uso de Cursors vs Consultas Directas:

Optimizaciones posibles:

  1. topclientes: Cambiar frecuencia a mensual en producción
  2. clientesanti: Reemplazar cursor con INSERT...SELECT directo
  3. clientessinped: Ya está optimizado al usar ped_realizados

Versión optimizada de clientesanti:

-- Sin cursor, más eficiente CREATE EVENT clientesanti_optimizado ON SCHEDULE EVERY 1 DAY DO BEGIN TRUNCATE TABLE clientes_antiguos; INSERT INTO clientes_antiguos SELECT c.*, MAX(p.fechahora) as ultimo_pedido FROM Cliente c JOIN Pedido p ON c.DNI = p.dni_cliente GROUP BY c.DNI, c.nombre, c.direccion, c.poblacion, c.telefono, c.email, c.fecha_alta, c.ped_realizados, c.pizzastotales HAVING TIMESTAMPDIFF(YEAR, MAX(p.fechahora), CURDATE()) >= 1; END //

Integración con el Sistema Completo

Flujo de datos completo:

  1. En tiempo real: Triggers actualizan contadores en Cliente y Pizza
  2. Cada minuto: topclientes recalcula clientes VIP
  3. Cada 10 minutos:
    • clientesanti archiva inactivos
    • clientessinped identifica leads fríos

Ventajas de esta arquitectura:

Casos de uso empresarial:

Conclusión

Los eventos programados en Tuxeria completan el ecosistema de automatización junto con los triggers:

Triggers vs Eventos:

Aspecto Triggers Eventos
Activación Por operaciones DML Por tiempo/cron
Frecuencia En tiempo real Periódica
Propósito Mantener consistencia Mantenimiento/análisis
Ejemplo Actualizar contadores Generar reportes

Recomendaciones para producción:

  1. Ajustar frecuencias según necesidades reales (1 minuto es excesivo para topclientes)
  2. Monitorizar ejecución de eventos en logs
  3. Considerar backups antes de TRUNCATE en tablas críticas
  4. Implementar manejo de errores en eventos

El sistema demuestra una arquitectura completa donde las alteraciones de tablas, triggers y eventos trabajan conjuntamente para crear un sistema autónomo y eficiente.