Moibe commited on
Commit
fd0df2b
·
1 Parent(s): 4a81627

Tabla funel_compra

Browse files
create_funel_compra_table.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Script para crear la tabla funel_compra"""
2
+
3
+ from connection import get_connection
4
+ import logging
5
+
6
+ logging.basicConfig(level=logging.INFO, format='%(message)s')
7
+ logger = logging.getLogger(__name__)
8
+
9
+ def create_funel_compra_table():
10
+ """Crea la tabla funel_compra en la BD"""
11
+
12
+ conn = get_connection()
13
+
14
+ if not conn:
15
+ logger.error("❌ No se pudo conectar a la base de datos")
16
+ return False
17
+
18
+ try:
19
+ cursor = conn.cursor()
20
+
21
+ logger.info("📝 Creando tabla funel_compra...")
22
+
23
+ sql = """
24
+ CREATE TABLE IF NOT EXISTS `funel_compra` (
25
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
26
+ `usuario` VARCHAR(255) NOT NULL,
27
+ `mail` VARCHAR(255) NOT NULL,
28
+ `accion` VARCHAR(255) NOT NULL,
29
+ `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(),
30
+ INDEX idx_usuario (usuario),
31
+ INDEX idx_mail (mail),
32
+ INDEX idx_accion (accion),
33
+ INDEX idx_created_at (created_at)
34
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
35
+ """
36
+
37
+ cursor.execute(sql)
38
+ conn.commit()
39
+
40
+ logger.info("✅ Tabla 'funel_compra' creada exitosamente")
41
+
42
+ # Describir tabla
43
+ cursor.execute("DESCRIBE funel_compra")
44
+ fields = cursor.fetchall()
45
+ cursor.close()
46
+ conn.close()
47
+
48
+ logger.info("\n📋 Estructura de la tabla:")
49
+ logger.info("=" * 100)
50
+ logger.info(f"{'Campo':<20} | {'Tipo':<25} | {'Null':<6} | {'Key':<8} | {'Extra':<30}")
51
+ logger.info("-" * 100)
52
+ for field in fields:
53
+ field_name = field[0]
54
+ field_type = field[1]
55
+ field_null = field[2]
56
+ field_key = field[3]
57
+ field_extra = str(field[5]) if field[5] else '-'
58
+ logger.info(f"{field_name:<20} | {field_type:<25} | {field_null:<6} | {field_key:<8} | {field_extra:<30}")
59
+ logger.info("=" * 100)
60
+
61
+ return True
62
+
63
+ except Exception as e:
64
+ logger.error(f"❌ Error al crear la tabla: {str(e)}")
65
+ conn.close()
66
+ return False
67
+
68
+
69
+ if __name__ == "__main__":
70
+ create_funel_compra_table()
funciones.py CHANGED
@@ -589,3 +589,204 @@ def obtener_todas_acciones(limit: int = 10, offset: int = 0) -> dict:
589
  "success": False,
590
  "error": f"Error al obtener acciones: {str(e)}"
591
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  "success": False,
590
  "error": f"Error al obtener acciones: {str(e)}"
591
  }
592
+
593
+
594
+ def crear_evento_funel(datos) -> dict:
595
+ """
596
+ Crea un evento en el funel de compra.
597
+
598
+ Args:
599
+ datos: Object FunelCompraRequest con usuario, mail, accion
600
+
601
+ Returns:
602
+ dict: Evento creado o error
603
+ """
604
+
605
+ conn = get_connection()
606
+
607
+ if not conn:
608
+ logger.error("❌ No se pudo conectar a la base de datos")
609
+ return {
610
+ "success": False,
611
+ "error": "No se pudo conectar a la base de datos"
612
+ }
613
+
614
+ try:
615
+ logger.info(f"📊 Registrando evento funel - Usuario: {datos.usuario}, Mail: {datos.mail}, Acción: {datos.accion}")
616
+
617
+ cursor = conn.cursor()
618
+
619
+ sql = """
620
+ INSERT INTO `funel_compra`
621
+ (usuario, mail, accion)
622
+ VALUES (%s, %s, %s)
623
+ """
624
+
625
+ valores = (datos.usuario, datos.mail, datos.accion)
626
+
627
+ cursor.execute(sql, valores)
628
+ conn.commit()
629
+
630
+ logger.info(f"✅ Evento funel registrado en BD - Usuario: {datos.usuario}")
631
+
632
+ # Recuperar el evento creado
633
+ cursor.execute(
634
+ "SELECT * FROM `funel_compra` WHERE usuario = %s AND mail = %s AND accion = %s ORDER BY created_at DESC LIMIT 1",
635
+ (datos.usuario, datos.mail, datos.accion)
636
+ )
637
+
638
+ evento = cursor.fetchone()
639
+ cursor.close()
640
+ conn.close()
641
+
642
+ if evento:
643
+ logger.info(f"✅ Evento recuperado - ID: {evento[0]}")
644
+ return {
645
+ "success": True,
646
+ "data": {
647
+ "id": evento[0],
648
+ "usuario": evento[1],
649
+ "mail": evento[2],
650
+ "accion": evento[3],
651
+ "created_at": evento[4]
652
+ }
653
+ }
654
+ else:
655
+ logger.error("❌ No se pudo recuperar el evento creado")
656
+ return {
657
+ "success": False,
658
+ "error": "No se pudo recuperar el evento"
659
+ }
660
+
661
+ except Exception as e:
662
+ logger.error(f"❌ Error al crear evento funel: {str(e)}")
663
+ return {
664
+ "success": False,
665
+ "error": f"Error al crear evento: {str(e)}"
666
+ }
667
+
668
+
669
+ def obtener_eventos_funel(usuario: str) -> dict:
670
+ """
671
+ Obtiene todos los eventos de funel para un usuario.
672
+
673
+ Args:
674
+ usuario: Nombre del usuario
675
+
676
+ Returns:
677
+ dict: Lista de eventos o error
678
+ """
679
+
680
+ conn = get_connection()
681
+
682
+ if not conn:
683
+ logger.error("❌ No se pudo conectar a la base de datos")
684
+ return {
685
+ "success": False,
686
+ "error": "No se pudo conectar a la base de datos"
687
+ }
688
+
689
+ try:
690
+ logger.info(f"🔍 Buscando eventos funel - Usuario: {usuario}")
691
+ cursor = conn.cursor()
692
+
693
+ cursor.execute(
694
+ "SELECT * FROM `funel_compra` WHERE usuario = %s ORDER BY created_at DESC",
695
+ (usuario,)
696
+ )
697
+
698
+ eventos = cursor.fetchall()
699
+ cursor.close()
700
+ conn.close()
701
+
702
+ datos = []
703
+ for evento in eventos:
704
+ datos.append({
705
+ "id": evento[0],
706
+ "usuario": evento[1],
707
+ "mail": evento[2],
708
+ "accion": evento[3],
709
+ "created_at": evento[4]
710
+ })
711
+
712
+ logger.info(f"✅ Se obtuvieron {len(datos)} eventos para el usuario: {usuario}")
713
+
714
+ return {
715
+ "success": True,
716
+ "data": datos,
717
+ "total": len(datos)
718
+ }
719
+
720
+ except Exception as e:
721
+ logger.error(f"❌ Error al obtener eventos funel: {str(e)}")
722
+ return {
723
+ "success": False,
724
+ "error": f"Error al obtener eventos: {str(e)}"
725
+ }
726
+
727
+
728
+ def obtener_todos_eventos_funel(limit: int = 10, offset: int = 0) -> dict:
729
+ """
730
+ Obtiene todos los eventos del funel con paginación.
731
+
732
+ Args:
733
+ limit: Cantidad máxima de registros
734
+ offset: Desplazamiento para paginación
735
+
736
+ Returns:
737
+ dict: Lista de eventos paginada o error
738
+ """
739
+
740
+ conn = get_connection()
741
+
742
+ if not conn:
743
+ logger.error("❌ No se pudo conectar a la base de datos")
744
+ return {
745
+ "success": False,
746
+ "error": "No se pudo conectar a la base de datos"
747
+ }
748
+
749
+ try:
750
+ logger.info(f"📚 Obteniendo todos los eventos funel - Limit: {limit}, Offset: {offset}")
751
+ cursor = conn.cursor()
752
+
753
+ # Obtener total
754
+ cursor.execute("SELECT COUNT(*) FROM `funel_compra`")
755
+ total = cursor.fetchone()[0]
756
+ logger.info(f"📊 Total de eventos: {total}")
757
+
758
+ # Obtener con paginación
759
+ cursor.execute(
760
+ "SELECT * FROM `funel_compra` ORDER BY created_at DESC LIMIT %s OFFSET %s",
761
+ (limit, offset)
762
+ )
763
+
764
+ eventos = cursor.fetchall()
765
+ logger.info(f"✅ Se obtuvieron {len(eventos)} eventos")
766
+ cursor.close()
767
+ conn.close()
768
+
769
+ datos = []
770
+ for evento in eventos:
771
+ datos.append({
772
+ "id": evento[0],
773
+ "usuario": evento[1],
774
+ "mail": evento[2],
775
+ "accion": evento[3],
776
+ "created_at": evento[4]
777
+ })
778
+
779
+ return {
780
+ "success": True,
781
+ "data": datos,
782
+ "total": total,
783
+ "limit": limit,
784
+ "offset": offset
785
+ }
786
+
787
+ except Exception as e:
788
+ logger.error(f"❌ Error al obtener eventos funel: {str(e)}")
789
+ return {
790
+ "success": False,
791
+ "error": f"Error al obtener eventos: {str(e)}"
792
+ }
imagen_log.sql CHANGED
@@ -41,3 +41,15 @@ CREATE TABLE `actions` (
41
  `created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
42
  `updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
43
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  `created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
42
  `updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
43
  );
44
+
45
+ CREATE TABLE `funel_compra` (
46
+ `id` int AUTO_INCREMENT PRIMARY KEY,
47
+ `usuario` varchar(255) NOT NULL,
48
+ `mail` varchar(255) NOT NULL,
49
+ `accion` varchar(255) NOT NULL,
50
+ `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
51
+ INDEX idx_usuario (usuario),
52
+ INDEX idx_mail (mail),
53
+ INDEX idx_accion (accion),
54
+ INDEX idx_created_at (created_at)
55
+ );
main.py CHANGED
@@ -5,8 +5,8 @@ Aplicación FastAPI - Endpoints
5
  import logging
6
  from fastapi import FastAPI, HTTPException, Query
7
  from fastapi.responses import JSONResponse
8
- from models import RegistroRequest, RegistroResponse, CalificacionRequest, ActionRequest, ActionResponse
9
- from funciones import crear_registro, obtener_registros, actualizar_calificacion, crear_o_actualizar_action, obtener_action, obtener_todas_acciones
10
  from datetime import datetime
11
 
12
  # Configurar logging
@@ -277,10 +277,82 @@ async def obtener_acciones(
277
  )
278
 
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
- if __name__ == "__main__":
282
- import uvicorn
283
- uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
 
285
 
286
  if __name__ == "__main__":
 
5
  import logging
6
  from fastapi import FastAPI, HTTPException, Query
7
  from fastapi.responses import JSONResponse
8
+ from models import RegistroRequest, RegistroResponse, CalificacionRequest, ActionRequest, ActionResponse, FunelCompraRequest, FunelCompraResponse
9
+ from funciones import crear_registro, obtener_registros, actualizar_calificacion, crear_o_actualizar_action, obtener_action, obtener_todas_acciones, crear_evento_funel, obtener_eventos_funel, obtener_todos_eventos_funel
10
  from datetime import datetime
11
 
12
  # Configurar logging
 
277
  )
278
 
279
 
280
+ @app.post("/funel-compra", response_model=dict, tags=["Funel Compra"])
281
+ async def registrar_funel_compra(datos: FunelCompraRequest):
282
+ """
283
+ Registra un evento en el funel de compra.
284
+
285
+ Acciones típicas: inicio, visualizacion, intento_compra, compra_exitosa, abandono
286
+ """
287
+ logger.info(f"📊 POST /funel-compra - Usuario: {datos.usuario}, Mail: {datos.mail}, Acción: {datos.accion}")
288
+
289
+ resultado = crear_evento_funel(datos)
290
+
291
+ if resultado["success"]:
292
+ logger.info(f"✅ Evento registrado: {resultado['data']}")
293
+ return {
294
+ "success": True,
295
+ "data": resultado["data"]
296
+ }
297
+ else:
298
+ logger.error(f"❌ Error al registrar evento: {resultado['error']}")
299
+ raise HTTPException(
300
+ status_code=400,
301
+ detail=resultado["error"]
302
+ )
303
 
304
+
305
+ @app.get("/funel-compra/{usuario}", response_model=dict, tags=["Funel Compra"])
306
+ async def obtener_funel_usuario(usuario: str):
307
+ """
308
+ Obtiene todos los eventos del funel de compra para un usuario específico.
309
+ """
310
+ logger.info(f"🔍 GET /funel-compra/{usuario}")
311
+
312
+ resultado = obtener_eventos_funel(usuario)
313
+
314
+ if resultado["success"]:
315
+ logger.info(f"✅ Se obtuvieron {resultado['total']} eventos para {usuario}")
316
+ return {
317
+ "success": True,
318
+ "data": resultado["data"],
319
+ "total": resultado["total"]
320
+ }
321
+ else:
322
+ logger.error(f"❌ Error al obtener eventos: {resultado['error']}")
323
+ raise HTTPException(
324
+ status_code=500,
325
+ detail=resultado["error"]
326
+ )
327
+
328
+
329
+ @app.get("/funel-compra", response_model=dict, tags=["Funel Compra"])
330
+ async def listar_funel_compra(limit: int = Query(10, ge=1, le=100), offset: int = Query(0, ge=0)):
331
+ """
332
+ Obtiene todos los eventos del funel de compra con paginación.
333
+ """
334
+ logger.info(f"📚 GET /funel-compra - Limit: {limit}, Offset: {offset}")
335
+
336
+ resultado = obtener_todos_eventos_funel(limit, offset)
337
+
338
+ if resultado["success"]:
339
+ logger.info(f"✅ Se obtuvieron {len(resultado['data'])} eventos (Total: {resultado['total']})")
340
+ return {
341
+ "success": True,
342
+ "data": resultado["data"],
343
+ "pagination": {
344
+ "total": resultado["total"],
345
+ "limit": limit,
346
+ "offset": offset,
347
+ "pages": (resultado["total"] + limit - 1) // limit
348
+ }
349
+ }
350
+ else:
351
+ logger.error(f"❌ Error al obtener eventos: {resultado['error']}")
352
+ raise HTTPException(
353
+ status_code=500,
354
+ detail=resultado["error"]
355
+ )
356
 
357
 
358
  if __name__ == "__main__":
models.py CHANGED
@@ -160,3 +160,35 @@ class ActionResponse(BaseModel):
160
  "created_at": "2025-01-13T10:30:00",
161
  "updated_at": "2025-02-06T15:45:00"
162
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  "created_at": "2025-01-13T10:30:00",
161
  "updated_at": "2025-02-06T15:45:00"
162
  }
163
+
164
+
165
+ class FunelCompraRequest(BaseModel):
166
+ """Modelo para crear/registrar un evento en el funel de compra"""
167
+ usuario: str = Field(..., max_length=255, description="Nombre de usuario")
168
+ mail: str = Field(..., description="Email del usuario")
169
+ accion: str = Field(..., max_length=255, description="Acción realizada en el funel (ej: inicio, visualizacion, intento_compra, compra_exitosa)")
170
+
171
+ class Config:
172
+ example = {
173
+ "usuario": "moibe",
174
+ "mail": "moi.estrello@gmail.com",
175
+ "accion": "compra_exitosa"
176
+ }
177
+
178
+
179
+ class FunelCompraResponse(BaseModel):
180
+ """Modelo para respuesta de registros del funel de compra"""
181
+ id: int = Field(..., description="ID único del registro")
182
+ usuario: str
183
+ mail: str
184
+ accion: str
185
+ created_at: datetime
186
+
187
+ class Config:
188
+ example = {
189
+ "id": 1,
190
+ "usuario": "moibe",
191
+ "mail": "moi.estrello@gmail.com",
192
+ "accion": "compra_exitosa",
193
+ "created_at": "2026-02-11T10:30:00"
194
+ }
test_funel_compra.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Script para probar los endpoints del funel de compra"""
2
+
3
+ import requests
4
+ import json
5
+
6
+ BASE_URL = "http://localhost:8000"
7
+
8
+ # Test 1: Registrar un evento
9
+ print("=" * 80)
10
+ print("TEST 1: Registrar evento en funel de compra")
11
+ print("=" * 80)
12
+
13
+ evento1 = {
14
+ "usuario": "moibe",
15
+ "mail": "moi.estrello@gmail.com",
16
+ "accion": "inicio"
17
+ }
18
+
19
+ response = requests.post(f"{BASE_URL}/funel-compra", json=evento1)
20
+ print(f"Status Code: {response.status_code}")
21
+ print(f"Response: {json.dumps(response.json(), indent=2)}")
22
+
23
+ # Test 2: Registrar más eventos para el mismo usuario
24
+ print("\n" + "=" * 80)
25
+ print("TEST 2: Registrar más eventos")
26
+ print("=" * 80)
27
+
28
+ eventos = [
29
+ {"usuario": "moibe", "mail": "moi.estrello@gmail.com", "accion": "visualizacion"},
30
+ {"usuario": "moibe", "mail": "moi.estrello@gmail.com", "accion": "intento_compra"},
31
+ {"usuario": "moibe", "mail": "moi.estrello@gmail.com", "accion": "compra_exitosa"},
32
+ {"usuario": "juan_perez", "mail": "juan@example.com", "accion": "inicio"},
33
+ {"usuario": "juan_perez", "mail": "juan@example.com", "accion": "visualizacion"},
34
+ ]
35
+
36
+ for evento in eventos:
37
+ response = requests.post(f"{BASE_URL}/funel-compra", json=evento)
38
+ print(f"✅ {evento['accion']} para {evento['usuario']}: Status {response.status_code}")
39
+
40
+ # Test 3: Obtener eventos de un usuario
41
+ print("\n" + "=" * 80)
42
+ print("TEST 3: Obtener eventos para un usuario")
43
+ print("=" * 80)
44
+
45
+ response = requests.get(f"{BASE_URL}/funel-compra/moibe")
46
+ print(f"Status Code: {response.status_code}")
47
+ print(f"Response: {json.dumps(response.json(), indent=2)}")
48
+
49
+ # Test 4: Obtener todos los eventos
50
+ print("\n" + "=" * 80)
51
+ print("TEST 4: Obtener todos los eventos (paginación)")
52
+ print("=" * 80)
53
+
54
+ response = requests.get(f"{BASE_URL}/funel-compra?limit=5&offset=0")
55
+ print(f"Status Code: {response.status_code}")
56
+ print(f"Response: {json.dumps(response.json(), indent=2)}")
57
+
58
+ print("\n" + "=" * 80)
59
+ print("✅ PRUEBAS COMPLETADAS")
60
+ print("=" * 80)
test_funel_simple.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test rápido de funciones del funel de compra"""
2
+
3
+ import logging
4
+ from models import FunelCompraRequest
5
+ from funciones import crear_evento_funel, obtener_eventos_funel, obtener_todos_eventos_funel
6
+
7
+ logging.basicConfig(level=logging.INFO, format='%(message)s')
8
+ logger = logging.getLogger(__name__)
9
+
10
+ print("\n" + "=" * 80)
11
+ print("TEST 1: Crear evento funel")
12
+ print("=" * 80)
13
+
14
+ evento1 = FunelCompraRequest(
15
+ usuario="moibe",
16
+ mail="moi.estrello@gmail.com",
17
+ accion="inicio"
18
+ )
19
+
20
+ resultado = crear_evento_funel(evento1)
21
+ print(f"Resultado: {resultado}\n")
22
+
23
+ print("=" * 80)
24
+ print("TEST 2: Crear más eventos")
25
+ print("=" * 80)
26
+
27
+ eventos_data = [
28
+ ("moibe", "moi.estrello@gmail.com", "visualizacion"),
29
+ ("moibe", "moi.estrello@gmail.com", "intento_compra"),
30
+ ("moibe", "moi.estrello@gmail.com", "compra_exitosa"),
31
+ ("juan_perez", "juan@example.com", "inicio"),
32
+ ("juan_perez", "juan@example.com", "visualizacion"),
33
+ ("juan_perez", "juan@example.com", "abandono"),
34
+ ]
35
+
36
+ for usuario, mail, accion in eventos_data:
37
+ evento = FunelCompraRequest(usuario=usuario, mail=mail, accion=accion)
38
+ resultado = crear_evento_funel(evento)
39
+ if resultado['success']:
40
+ print(f"✅ Evento creado: {accion} para {usuario}")
41
+ else:
42
+ print(f"❌ Error: {resultado['error']}")
43
+
44
+ print("\n" + "=" * 80)
45
+ print("TEST 3: Obtener eventos de un usuario")
46
+ print("=" * 80)
47
+
48
+ resultado = obtener_eventos_funel("moibe")
49
+ print(f"Total eventos para moibe: {resultado['total']}")
50
+ for evento in resultado['data']:
51
+ print(f" - {evento['accion']} ({evento['created_at']})")
52
+
53
+ print("\n" + "=" * 80)
54
+ print("TEST 4: Obtener todos los eventos (paginación)")
55
+ print("=" * 80)
56
+
57
+ resultado = obtener_todos_eventos_funel(limit=5, offset=0)
58
+ print(f"Total eventos: {resultado['total']}")
59
+ print(f"Mostrando: {len(resultado['data'])} de {resultado['total']}")
60
+ for evento in resultado['data']:
61
+ print(f" - {evento['usuario']}: {evento['accion']}")
62
+
63
+ print("\n" + "=" * 80)
64
+ print("✅ TODOS LOS TESTS COMPLETADOS")
65
+ print("=" * 80 + "\n")
test_output.txt ADDED
Binary file (3.8 kB). View file