epok-toolkit 1.11.1__tar.gz → 1.11.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of epok-toolkit might be problematic. Click here for more details.

Files changed (43) hide show
  1. epok_toolkit-1.11.2/PKG-INFO +75 -0
  2. epok_toolkit-1.11.2/README.md +52 -0
  3. epok_toolkit-1.11.2/epok_toolkit/default_settings.py +33 -0
  4. epok_toolkit-1.11.2/epok_toolkit/django/viewsets.py +56 -0
  5. epok_toolkit-1.11.2/epok_toolkit/email/templates.py +173 -0
  6. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/ticket_pdf.py +0 -4
  7. epok_toolkit-1.11.2/epok_toolkit.egg-info/PKG-INFO +75 -0
  8. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit.egg-info/requires.txt +2 -0
  9. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/pyproject.toml +3 -1
  10. epok_toolkit-1.11.1/PKG-INFO +0 -25
  11. epok_toolkit-1.11.1/README.md +0 -4
  12. epok_toolkit-1.11.1/epok_toolkit/default_settings.py +0 -15
  13. epok_toolkit-1.11.1/epok_toolkit/django/viewsets.py +0 -41
  14. epok_toolkit-1.11.1/epok_toolkit/email/templates.py +0 -185
  15. epok_toolkit-1.11.1/epok_toolkit.egg-info/PKG-INFO +0 -25
  16. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/LICENSE +0 -0
  17. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/MANIFEST.in +0 -0
  18. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/__init__.py +0 -0
  19. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/apps.py +0 -0
  20. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/__init__.py +0 -0
  21. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/cache.py +0 -0
  22. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/fields.py +0 -0
  23. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/manager.py +0 -0
  24. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/response.py +0 -0
  25. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/utils/__init__.py +0 -0
  26. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/django/utils/magic_link.py +0 -0
  27. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/email/__init__.py +0 -0
  28. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/email/email_async.py +0 -0
  29. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/email/engine.py +0 -0
  30. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/messaging/__init__.py +0 -0
  31. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/messaging/whatsapp.py +0 -0
  32. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/messaging/whatsapp_instanced.py +0 -0
  33. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/__init__.py +0 -0
  34. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/fuentes/Kollektif-Bold.ttf +0 -0
  35. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/fuentes/Kollektif-BoldItalic.ttf +0 -0
  36. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/fuentes/Kollektif-Italic.ttf +0 -0
  37. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/fuentes/Kollektif.ttf +0 -0
  38. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/plantillas/Ticket_congrats.png +0 -0
  39. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit/pdf/plantillas/Ticket_congrats2.png +0 -0
  40. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit.egg-info/SOURCES.txt +0 -0
  41. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit.egg-info/dependency_links.txt +0 -0
  42. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/epok_toolkit.egg-info/top_level.txt +0 -0
  43. {epok_toolkit-1.11.1 → epok_toolkit-1.11.2}/setup.cfg +0 -0
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.4
2
+ Name: epok-toolkit
3
+ Version: 1.11.2
4
+ Summary: Una herramienta para la gestión de tareas y procesos en Django con Celery.
5
+ Author-email: Fernando Leon Franco <fernanlee2131@gmail.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Framework :: Django
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.12.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: Django>=5.0.2
15
+ Requires-Dist: djangorestframework>=3.16.0
16
+ Requires-Dist: celery[redis]>=5.5.3
17
+ Requires-Dist: django-celery-beat>=2.6.0
18
+ Requires-Dist: colorstreak>=0.1.0
19
+ Requires-Dist: PyJWT>=2.10.1
20
+ Requires-Dist: reportlab>=4.4.3
21
+ Requires-Dist: qrcode>=8.2
22
+ Dynamic: license-file
23
+
24
+
25
+
26
+ # EPOK Toolkit 'v1.11.2'
27
+
28
+ EPOK Toolkit es una librería de utilidades para proyectos Django y Python, diseñada para facilitar tareas comunes como envío de emails, mensajería WhatsApp, generación de PDFs y manejo avanzado de caché en APIs.
29
+
30
+ ---
31
+
32
+
33
+ ## ✉️ Email
34
+ Módulo para envío de correos electrónicos con plantillas HTML y texto plano, registro dinámico y configuración visual.
35
+
36
+ 👉 [Documentación completa del módulo Email](epok_toolkit/email/README.md)
37
+
38
+ ---
39
+
40
+ ## 🟢 Django
41
+ Utilidades avanzadas para proyectos Django y DRF: caché, campos personalizados, managers, respuestas, viewsets y utilidades extra.
42
+
43
+ � [Documentación completa del módulo Django](epok_toolkit/django/README.md)
44
+
45
+ ---
46
+
47
+ ## 💬 Mensajería WhatsApp
48
+ Módulo para envío de mensajes y archivos por WhatsApp, con manejo de conexión y errores.
49
+
50
+ � [Documentación completa del módulo Messaging](epok_toolkit/messaging/README.md)
51
+
52
+ ---
53
+
54
+ ## 🧾 PDF / Ticket Generator
55
+ Módulo para generación de tickets PDF personalizados usando ReportLab y plantillas gráficas.
56
+
57
+ � [Documentación completa del módulo PDF](epok_toolkit/pdf/README.md)
58
+
59
+ ---
60
+
61
+ ## ⚙️ Configuración
62
+
63
+ Toda la configuración se centraliza en `default_settings.py`, permitiendo personalizar colores, datos de empresa, y más.
64
+
65
+ ---
66
+
67
+ ## 🚀 Instalación
68
+
69
+ ```bash
70
+ pip install epok-toolkit
71
+ ```
72
+
73
+ ---
74
+
75
+ ¿Quieres agregar ejemplos avanzados o documentación de otro módulo? ¡Solicítalo!
@@ -0,0 +1,52 @@
1
+
2
+
3
+ # EPOK Toolkit 'v1.11.2'
4
+
5
+ EPOK Toolkit es una librería de utilidades para proyectos Django y Python, diseñada para facilitar tareas comunes como envío de emails, mensajería WhatsApp, generación de PDFs y manejo avanzado de caché en APIs.
6
+
7
+ ---
8
+
9
+
10
+ ## ✉️ Email
11
+ Módulo para envío de correos electrónicos con plantillas HTML y texto plano, registro dinámico y configuración visual.
12
+
13
+ 👉 [Documentación completa del módulo Email](epok_toolkit/email/README.md)
14
+
15
+ ---
16
+
17
+ ## 🟢 Django
18
+ Utilidades avanzadas para proyectos Django y DRF: caché, campos personalizados, managers, respuestas, viewsets y utilidades extra.
19
+
20
+ � [Documentación completa del módulo Django](epok_toolkit/django/README.md)
21
+
22
+ ---
23
+
24
+ ## 💬 Mensajería WhatsApp
25
+ Módulo para envío de mensajes y archivos por WhatsApp, con manejo de conexión y errores.
26
+
27
+ � [Documentación completa del módulo Messaging](epok_toolkit/messaging/README.md)
28
+
29
+ ---
30
+
31
+ ## 🧾 PDF / Ticket Generator
32
+ Módulo para generación de tickets PDF personalizados usando ReportLab y plantillas gráficas.
33
+
34
+ � [Documentación completa del módulo PDF](epok_toolkit/pdf/README.md)
35
+
36
+ ---
37
+
38
+ ## ⚙️ Configuración
39
+
40
+ Toda la configuración se centraliza en `default_settings.py`, permitiendo personalizar colores, datos de empresa, y más.
41
+
42
+ ---
43
+
44
+ ## 🚀 Instalación
45
+
46
+ ```bash
47
+ pip install epok-toolkit
48
+ ```
49
+
50
+ ---
51
+
52
+ ¿Quieres agregar ejemplos avanzados o documentación de otro módulo? ¡Solicítalo!
@@ -0,0 +1,33 @@
1
+ # Configuración de correo electrónico
2
+ EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
3
+ EMAIL_HOST = 'smtp.gmail.com'
4
+ EMAIL_PORT = 465
5
+ EMAIL_USE_SSL = True
6
+ EMAIL_USE_TLS = False
7
+ EMAIL_DEFAULT_FROM_EMAIL = "no-reply@epok.ai"
8
+ EMAIL_HOST_USER = "no-reply@epok.ai"
9
+ EMAIL_HOST_PASSWORD = "your-email-password"
10
+
11
+
12
+ # Configuración de whatsApp
13
+ API_KEY = "your-whatsapp-api-key"
14
+ INSTANCE = "instance-id"
15
+ SERVER_URL = "https://your-server-url.com/"
16
+
17
+
18
+
19
+ # ---------- TEMPLATE DE CORREO ELECTRÓNICO ---------- #
20
+ TEMPLATES_SETTINGS = {
21
+ "company": {
22
+ "name": "Congrats",
23
+ "email": "info@compania.com",
24
+ "eslogan": "Eslogan sin definir",
25
+ "footer": "¡Nos vemos pronto!<br><em> El equipo de Congrats 🥳</em>"
26
+ },
27
+ "colors": {
28
+ "background": "#f9fafb",
29
+ "primary": "#4f46e5",
30
+ "text": "#374151",
31
+ "white": "#ffffff"
32
+ }
33
+ }
@@ -0,0 +1,56 @@
1
+ # core/viewsets.py
2
+ from rest_framework import viewsets
3
+ from rest_framework.pagination import PageNumberPagination
4
+ from rest_framework.permissions import AllowAny
5
+
6
+ class DefaultPagination(PageNumberPagination):
7
+ """
8
+ Clase de paginación por defecto para los ViewSets.
9
+ Puedes personalizarla según tus necesidades.
10
+ """
11
+ page_size = 10
12
+ page_size_query_param = 'page_size'
13
+ max_page_size = 100
14
+
15
+
16
+
17
+ class BaseOptimizedViewSet(viewsets.ModelViewSet):
18
+ queryset = None
19
+ write_serializer_class = None
20
+ update_serializer_class = None
21
+ simple_serializer_class = None
22
+ full_serializer_class = None
23
+ serializer_class = full_serializer_class
24
+ extensions_auto_optimize = True
25
+
26
+ permission_classes = [AllowAny]
27
+
28
+ filterset_fields = []
29
+ search_fields = []
30
+ ordering_fields = []
31
+ ordering = []
32
+
33
+ def get_queryset(self):
34
+ qs = super().get_queryset()
35
+ model_cls = qs.model
36
+ manager = model_cls._default_manager
37
+
38
+ if hasattr(manager, 'simple') and self.action == 'list':
39
+ return manager.simple()
40
+ elif hasattr(manager, 'full'):
41
+ return manager.full()
42
+
43
+
44
+ def get_serializer_class(self):
45
+
46
+ match self.action:
47
+ case 'create':
48
+ return self.write_serializer_class
49
+ case 'update' | 'partial_update':
50
+ return self.update_serializer_class
51
+ case 'list':
52
+ return self.simple_serializer_class
53
+ case 'retrieve':
54
+ return self.full_serializer_class
55
+ case _:
56
+ return super().get_serializer_class()
@@ -0,0 +1,173 @@
1
+ """
2
+
3
+ """
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Dict, List
7
+ from django.conf import settings
8
+ import re
9
+
10
+
11
+ # ============================
12
+ # Config base
13
+ # ============================
14
+
15
+ TEMPLATES_SETTINGS = getattr(settings, "TEMPLATE_SETTINGS", {})
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class Colors:
20
+ BACKGROUND: str = TEMPLATES_SETTINGS.get("colors", {}).get("background", "#f9fafb")
21
+ PRIMARY: str = TEMPLATES_SETTINGS.get("colors", {}).get("primary", "#4f46e5")
22
+ TEXT: str = TEMPLATES_SETTINGS.get("colors", {}).get("text", "#374151")
23
+ WHITE: str = TEMPLATES_SETTINGS.get("colors", {}).get("white", "#ffffff")
24
+
25
+ @dataclass(frozen=True)
26
+ class Company:
27
+ name: str = TEMPLATES_SETTINGS.get("company", {}).get("name", "Congrats")
28
+ email: str = TEMPLATES_SETTINGS.get("company", {}).get("email", "info@compania.com")
29
+ eslogan: str = TEMPLATES_SETTINGS.get("company", {}).get("eslogan", "Eslogan sin definir")
30
+ footer: str = TEMPLATES_SETTINGS.get("company", {}).get("footer", "¡Nos vemos pronto!<br><em>El equipo de Congrats 🥳</em>")
31
+
32
+
33
+
34
+ # ============================
35
+ # Grupper (envoltorio HTML)
36
+ # ============================
37
+
38
+ def wrap_html(content: str) -> str:
39
+ return f"""
40
+ <div style="font-family: Arial, Helvetica, sans-serif; background-color: {Colors.BACKGROUND}; padding: 24px;">
41
+ <table width="100%" cellpadding="0" cellspacing="0" style="max-width: 600px; margin: 0 auto; background: {Colors.WHITE}; border-radius: 8px; overflow: hidden;">
42
+ <tr>
43
+ <td style="background: {Colors.PRIMARY}; padding: 20px 24px; text-align: center;">
44
+ <h1 style="color: {Colors.WHITE}; margin: 0; font-size: 24px;">{Company.name} 🎉</h1>
45
+ </td>
46
+ </tr>
47
+ <tr>
48
+ <td style="padding: 32px 24px;">
49
+ {content}
50
+ </td>
51
+ </tr>
52
+ </table>
53
+ </div>
54
+ """
55
+
56
+
57
+ # ============================
58
+ # Tipos
59
+ # ============================
60
+
61
+ @dataclass(frozen=True)
62
+ class RenderedEmail:
63
+ subject: str
64
+ plain: str
65
+ html: str
66
+
67
+ @dataclass(frozen=True)
68
+ class EmailTemplate:
69
+ subject: str
70
+ plain_body: str
71
+ html_body: str
72
+ required_vars: List[str]
73
+
74
+ def render(self, context: Dict[str, str]) -> RenderedEmail:
75
+ missing = [v for v in self.required_vars if v not in context]
76
+ if missing:
77
+ raise ValueError(f"Faltan llaves en contexto: {missing}")
78
+ return RenderedEmail(
79
+ subject=self.subject.format(**context),
80
+ plain=self.plain_body.format(**context),
81
+ html=self.html_body.format(**context),
82
+ )
83
+
84
+
85
+ # ============================
86
+ # Registro dinámico
87
+ # ============================
88
+
89
+ class TemplateRegistry:
90
+ def __init__(self):
91
+ self._templates: Dict[str, EmailTemplate] = {}
92
+
93
+ def _html_to_plain(self, html: str) -> str:
94
+ return re.sub(r"<[^>]*>", "", html).strip()
95
+
96
+ def register_template(self, key: str, subject: str, html_body: str, required_vars: List[str], plain_body: str | None = None) -> None:
97
+ if key in self._templates:
98
+ raise ValueError(f"Template con clave '{key}' ya está registrado.")
99
+ plain = plain_body or self._html_to_plain(html_body)
100
+ wrapped_html = wrap_html(html_body)
101
+ self._templates[key] = EmailTemplate(
102
+ subject=subject,
103
+ plain_body=plain,
104
+ html_body=wrapped_html,
105
+ required_vars=required_vars
106
+ )
107
+
108
+ @property
109
+ def templates(self) -> Dict[str, EmailTemplate]:
110
+ return self._templates
111
+
112
+ registry = TemplateRegistry()
113
+
114
+ # ============================
115
+ # Registrar plantillas base usando el mismo builder
116
+ # ============================
117
+
118
+ registry.register_template(
119
+ key="password_reset",
120
+ subject=f"🔑 Restablecimiento de Contraseña – {Company.name}",
121
+ html_body=(
122
+ "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🎉</p>"
123
+ "<p style='font-size:16px;margin:24px 0;'>Haz clic en el botón para restablecer tu contraseña:</p>"
124
+ "<p style='text-align:center;margin:24px 0;'>"
125
+ f"<a href='{{reset_link}}' style='display:inline-block;padding:12px 24px;font-size:16px;color:{Colors.WHITE};background-color:{Colors.PRIMARY};text-decoration:none;border-radius:5px;'>🔒 Restablecer Contraseña 🎊</a>"
126
+ "</p>"
127
+ "<p style='font-size:16px;'>Si no funciona, copia este enlace:<br>"
128
+ "<span style='word-break:break-all;font-size:14px;'>{reset_link}</span></p>"
129
+ f"<p style='font-size:16px;margin-top:24px;'>{Company.footer}</p>"
130
+ ),
131
+ required_vars=["name", "reset_link"]
132
+ )
133
+
134
+ registry.register_template(
135
+ key="welcome",
136
+ subject=f"🎉 Bienvenido a {Company.name}, {{name}}",
137
+ html_body=(
138
+ "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🎈</p>"
139
+ "<p style='font-size:16px;margin:24px 0;'>Gracias por unirte a <strong>{Company.name}</strong>.</p>"
140
+ f"<p style='font-size:16px;margin-top:24px;'>{Company.footer}</p>"
141
+ ),
142
+ required_vars=["name"]
143
+ )
144
+
145
+ registry.register_template(
146
+ key="password_reset_success",
147
+ subject=f"🔑 Contraseña restablecida – {Company.name}",
148
+ html_body=(
149
+ "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🔑</p>"
150
+ "<p style='font-size:16px;margin:24px 0;'>Tu contraseña ha sido restablecida con éxito 🎉</p>"
151
+ f"<p style='font-size:16px;margin-top:24px;'>{Company.footer}</p>"
152
+ ),
153
+ required_vars=["name"]
154
+ )
155
+
156
+ registry.register_template(
157
+ key="test_app_running",
158
+ subject=f"🚀 Test OK – {Company.name}",
159
+ html_body=(
160
+ "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🚀</p>"
161
+ "<p style='font-size:16px;margin:24px 0;'>La prueba de funcionamiento pasó. Tu app está lista para rockear. 🎉</p>"
162
+ f"<p style='font-size:16px;margin-top:24px;'>{Company.footer}</p>"
163
+ ),
164
+ required_vars=["name"]
165
+ )
166
+
167
+ # ============================
168
+ # Catálogo final
169
+ # ============================
170
+
171
+ TEMPLATES: Dict[str, EmailTemplate] = {
172
+ **registry.templates,
173
+ }
@@ -4,10 +4,8 @@ from datetime import date, datetime
4
4
  from reportlab.pdfbase.ttfonts import TTFont
5
5
  from reportlab.pdfgen import canvas
6
6
  from dataclasses import dataclass
7
- from datetime import datetime
8
7
  from typing import Optional
9
8
  from PIL import Image
10
- import locale
11
9
  from uuid import uuid4, UUID
12
10
  import os
13
11
  import qrcode
@@ -15,8 +13,6 @@ from io import BytesIO
15
13
  import importlib.resources
16
14
 
17
15
 
18
- # pip install reportlab qrcode
19
-
20
16
 
21
17
  fuente_path = os.path.join(os.path.dirname(__file__), "fuentes", "Kollektif-Bold.ttf")
22
18
  pdfmetrics.registerFont(TTFont("kollektif", fuente_path))
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.4
2
+ Name: epok-toolkit
3
+ Version: 1.11.2
4
+ Summary: Una herramienta para la gestión de tareas y procesos en Django con Celery.
5
+ Author-email: Fernando Leon Franco <fernanlee2131@gmail.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Framework :: Django
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.12.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: Django>=5.0.2
15
+ Requires-Dist: djangorestframework>=3.16.0
16
+ Requires-Dist: celery[redis]>=5.5.3
17
+ Requires-Dist: django-celery-beat>=2.6.0
18
+ Requires-Dist: colorstreak>=0.1.0
19
+ Requires-Dist: PyJWT>=2.10.1
20
+ Requires-Dist: reportlab>=4.4.3
21
+ Requires-Dist: qrcode>=8.2
22
+ Dynamic: license-file
23
+
24
+
25
+
26
+ # EPOK Toolkit 'v1.11.2'
27
+
28
+ EPOK Toolkit es una librería de utilidades para proyectos Django y Python, diseñada para facilitar tareas comunes como envío de emails, mensajería WhatsApp, generación de PDFs y manejo avanzado de caché en APIs.
29
+
30
+ ---
31
+
32
+
33
+ ## ✉️ Email
34
+ Módulo para envío de correos electrónicos con plantillas HTML y texto plano, registro dinámico y configuración visual.
35
+
36
+ 👉 [Documentación completa del módulo Email](epok_toolkit/email/README.md)
37
+
38
+ ---
39
+
40
+ ## 🟢 Django
41
+ Utilidades avanzadas para proyectos Django y DRF: caché, campos personalizados, managers, respuestas, viewsets y utilidades extra.
42
+
43
+ � [Documentación completa del módulo Django](epok_toolkit/django/README.md)
44
+
45
+ ---
46
+
47
+ ## 💬 Mensajería WhatsApp
48
+ Módulo para envío de mensajes y archivos por WhatsApp, con manejo de conexión y errores.
49
+
50
+ � [Documentación completa del módulo Messaging](epok_toolkit/messaging/README.md)
51
+
52
+ ---
53
+
54
+ ## 🧾 PDF / Ticket Generator
55
+ Módulo para generación de tickets PDF personalizados usando ReportLab y plantillas gráficas.
56
+
57
+ � [Documentación completa del módulo PDF](epok_toolkit/pdf/README.md)
58
+
59
+ ---
60
+
61
+ ## ⚙️ Configuración
62
+
63
+ Toda la configuración se centraliza en `default_settings.py`, permitiendo personalizar colores, datos de empresa, y más.
64
+
65
+ ---
66
+
67
+ ## 🚀 Instalación
68
+
69
+ ```bash
70
+ pip install epok-toolkit
71
+ ```
72
+
73
+ ---
74
+
75
+ ¿Quieres agregar ejemplos avanzados o documentación de otro módulo? ¡Solicítalo!
@@ -4,3 +4,5 @@ celery[redis]>=5.5.3
4
4
  django-celery-beat>=2.6.0
5
5
  colorstreak>=0.1.0
6
6
  PyJWT>=2.10.1
7
+ reportlab>=4.4.3
8
+ qrcode>=8.2
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "epok-toolkit"
7
- version = "1.11.1"
7
+ version = "1.11.2"
8
8
  description = "Una herramienta para la gestión de tareas y procesos en Django con Celery."
9
9
  authors = [
10
10
  { name="Fernando Leon Franco", email="fernanlee2131@gmail.com" }
@@ -25,6 +25,8 @@ dependencies = [
25
25
  "django-celery-beat>=2.6.0",
26
26
  "colorstreak>=0.1.0",
27
27
  "PyJWT>=2.10.1",
28
+ "reportlab>=4.4.3",
29
+ "qrcode>=8.2",
28
30
  ]
29
31
 
30
32
  [tool.setuptools.packages.find]
@@ -1,25 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: epok-toolkit
3
- Version: 1.11.1
4
- Summary: Una herramienta para la gestión de tareas y procesos en Django con Celery.
5
- Author-email: Fernando Leon Franco <fernanlee2131@gmail.com>
6
- License: MIT
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: Framework :: Django
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.12.9
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: Django>=5.0.2
15
- Requires-Dist: djangorestframework>=3.16.0
16
- Requires-Dist: celery[redis]>=5.5.3
17
- Requires-Dist: django-celery-beat>=2.6.0
18
- Requires-Dist: colorstreak>=0.1.0
19
- Requires-Dist: PyJWT>=2.10.1
20
- Dynamic: license-file
21
-
22
- # EPOK Toolkit
23
-
24
- Esta libreria contiene utilidades
25
-
@@ -1,4 +0,0 @@
1
- # EPOK Toolkit
2
-
3
- Esta libreria contiene utilidades
4
-
@@ -1,15 +0,0 @@
1
- # Configuración de correo electrónico
2
- EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
3
- EMAIL_HOST = 'smtp.gmail.com'
4
- EMAIL_PORT = 465
5
- EMAIL_USE_SSL = True
6
- EMAIL_USE_TLS = False
7
- EMAIL_DEFAULT_FROM_EMAIL = "no-reply@epok.ai"
8
- EMAIL_HOST_USER = "no-reply@epok.ai"
9
- EMAIL_HOST_PASSWORD = "your-email-password"
10
-
11
-
12
- # Configuración de whatsApp
13
- API_KEY = "your-whatsapp-api-key"
14
- INSTANCE = "instance-id"
15
- SERVER_URL = "https://your-server-url.com/"
@@ -1,41 +0,0 @@
1
- # core/viewsets.py
2
- from rest_framework import viewsets
3
- from rest_framework.pagination import PageNumberPagination
4
-
5
- class DefaultPagination(PageNumberPagination):
6
- page_size = 10
7
- page_size_query_param = 'page_size'
8
- max_page_size = 100
9
-
10
-
11
-
12
- class BaseOptimizedViewSet(viewsets.ModelViewSet):
13
- """
14
- ViewSet base que alterna entre .full() y .simple() automáticamente
15
- y permite serializers diferentes para list y detail.
16
- """
17
- pagination_class = DefaultPagination
18
- simple_serializer_class = None
19
- full_serializer_class = None
20
-
21
- # def get_queryset(self):
22
- # qs = super().get_queryset()
23
-
24
- # if not (hasattr(qs, 'full') and hasattr(qs, 'simple')):
25
- # raise NotImplementedError(
26
- # f"❌ El modelo {qs.model.__name__} no está usando un OptimizedManager con full() y simple()."
27
- # )
28
-
29
- # if self.action == 'list':
30
- # return qs.simple()
31
- # elif self.action in ['retrieve', 'update', 'partial_update']:
32
- # return qs.full()
33
- # return qs
34
-
35
- # def get_serializer_class(self):
36
- # # Cambia el serializer según la acción
37
- # if self.action == 'list' and self.simple_serializer_class:
38
- # return self.simple_serializer_class
39
- # if self.action in ['retrieve', 'update', 'partial_update'] and self.full_serializer_class:
40
- # return self.full_serializer_class
41
- # return super().get_serializer_class()
@@ -1,185 +0,0 @@
1
- """
2
- notifications/method/email_templates.py
3
- Catálogo central de plantillas de correo con estilo corporativo “morado minimalista”.
4
- Cada plantilla declara las variables que necesita y se renderiza vía EmailTemplate.
5
- """
6
-
7
- from dataclasses import dataclass
8
- from typing import Dict, List
9
-
10
-
11
- # ---------------------------------------------------------------------------#
12
- # Shared purple‑minimalist wrapper
13
- # ---------------------------------------------------------------------------#
14
- def wrap_html(content: str) -> str:
15
- """
16
- Envuelve el bloque `content` en el layout HTML corporativo de Congrats.
17
- """
18
- return f"""
19
- <div style="font-family: Arial, Helvetica, sans-serif; background-color: #f9fafb; padding: 24px;">
20
- <table width="100%" cellpadding="0" cellspacing="0" style="max-width: 600px; margin: 0 auto; background: #ffffff; border-radius: 8px; overflow: hidden;">
21
- <tr>
22
- <td style="background: #4f46e5; padding: 20px 24px; text-align: center;">
23
- <h1 style="color: #ffffff; margin: 0; font-size: 24px;">Congrats 🎉</h1>
24
- </td>
25
- </tr>
26
-
27
- <tr>
28
- <td style="padding: 32px 24px;">
29
- {content}
30
- </td>
31
- </tr>
32
- </table>
33
- </div>
34
- """
35
-
36
-
37
- # ---------------------------------------------------------------------------#
38
- # Core dataclasses
39
- # ---------------------------------------------------------------------------#
40
- @dataclass(frozen=True)
41
- class RenderedEmail:
42
- subject: str
43
- plain: str
44
- html: str
45
-
46
-
47
- @dataclass(frozen=True)
48
- class EmailTemplate:
49
- """
50
- subject – Cadena con placeholders, e.g. 'Hola {name}'
51
- plain_body – Versión texto plano
52
- html_body – HTML completo (usa wrap_html)
53
- required_vars – Lista de variables obligatorias
54
- """
55
- subject: str
56
- plain_body: str
57
- html_body: str
58
- required_vars: List[str]
59
-
60
- def render(self, context: Dict[str, str]) -> RenderedEmail:
61
- missing = [v for v in self.required_vars if v not in context]
62
- if missing:
63
- raise ValueError(f"Faltan llaves en contexto: {missing}")
64
-
65
- return RenderedEmail(
66
- subject=self.subject.format(**context),
67
- plain=self.plain_body.format(**context),
68
- html=self.html_body.format(**context),
69
- )
70
-
71
-
72
- # ---------------------------------------------------------------------------#
73
- # Template catalogue
74
- # ---------------------------------------------------------------------------#
75
- TEMPLATES: Dict[str, EmailTemplate] = {
76
- "password_reset": EmailTemplate(
77
- subject="🎉 Restablecimiento de Contraseña – Congrats 🎉",
78
- plain_body=(
79
- "¡Hola {name}! 🎉\n\n"
80
- "Para poner tu fiesta de contraseñas en marcha, haz clic aquí:\n"
81
- "{reset_link} 🎊\n\n"
82
- "Si no fuiste tú quien pidió cambio, relájate y ignora este correo. 😉\n\n"
83
- "¡Nos vemos en la pista de baile!\nEl equipo de Congrats 🥳"
84
- ),
85
- html_body=wrap_html(
86
- "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🎉</p>"
87
- "<p style='font-size:16px;margin:24px 0;'>"
88
- "Haz clic en el botón para restablecer tu contraseña y unirte a la celebración:</p>"
89
- "<p style='text-align:center;margin:24px 0;'>"
90
- "<a href='{reset_link}' style='display:inline-block;padding:12px 24px;font-size:16px;"
91
- "color:#ffffff;background-color:#4f46e5;text-decoration:none;border-radius:5px;'>"
92
- "🔒 Restablecer Contraseña 🎊</a>"
93
- "</p>"
94
- "<p style='font-size:16px;'>"
95
- "Si eso no funciona, copia y pega este enlace en tu navegador:<br>"
96
- "<span style='word-break:break-all;font-size:14px;'>{reset_link}</span>"
97
- "</p>"
98
- "<p style='font-size:16px;margin-top:24px;'>"
99
- "Si no solicitaste esto, tranquilo, nada cambió. 😌<br><br>"
100
- "¡A celebrar pronto!<br><em>El equipo de Congrats 🥳</em>"
101
- "</p>"
102
- ),
103
- required_vars=["name", "reset_link"],
104
- ),
105
-
106
- "welcome": EmailTemplate(
107
- subject="¡Bienvenido a Congrats, {name}! 🎉🥳",
108
- plain_body=(
109
- "¡Hola {name}! 🎈\n\n"
110
- "Gracias por registrarte en Congrats. Prepárate para la mejor fiesta de eventos. 😎\n\n"
111
- "¡Nos vemos pronto!\nEl equipo de Congrats 🥳"
112
- ),
113
- html_body=wrap_html(
114
- "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🎈</p>"
115
- "<p style='font-size:16px;margin:24px 0;'>"
116
- "Gracias por unirte a <strong>Congrats 🎉</strong>. Prepárate para la mejor fiesta de eventos. 😎"
117
- "</p>"
118
- "<p style='font-size:16px;margin-top:24px;'>"
119
- "¡Nos vemos pronto!<br><em>El equipo de Congrats 🥳</em>"
120
- "</p>"
121
- ),
122
- required_vars=["name"],
123
- ),
124
-
125
-
126
- "password_reset_success": EmailTemplate(
127
- subject="🔑 Contraseña restablecida – Congrats 🥳",
128
- plain_body=(
129
- "¡Hola {name}! 🔑\n\n"
130
- "Tu contraseña ya está lista para seguir la fiesta. 🎉\n\n"
131
- "Si no fuiste tú, ponte alerta. 😉\n\n"
132
- "Saludos festivos,\nEl equipo de Congrats 🥳"
133
- ),
134
- html_body=wrap_html(
135
- "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🔑</p>"
136
- "<p style='font-size:16px;margin:24px 0;'>"
137
- "Tu contraseña ha sido restablecida con éxito. Ahora vuelve a la pista de baile. 🎉"
138
- "</p>"
139
- "<p style='font-size:16px;margin-top:24px;'>"
140
- "Si no fuiste tú, ignora o avísanos. 🤔<br><em>El equipo de Congrats 🥳</em>"
141
- "</p>"
142
- ),
143
- required_vars=["name"],
144
- ),
145
-
146
-
147
- "ticket_created": EmailTemplate(
148
- subject="🎫 ¡Tus tickets para {reunion_name} están listos! 🎉",
149
- plain_body=(
150
- "¡Hola {name}! 🎟️\n\n"
151
- "Has comprado {tickets} tickets para “{reunion_name}”. ¡A vivir la experiencia! 🎊\n\n"
152
- "¡Disfruta al máximo!\nEl equipo de Congrats 🥳"
153
- ),
154
- html_body=wrap_html(
155
- "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🎟️</p>"
156
- "<p style='font-size:16px;margin:24px 0;'>"
157
- "Tus {tickets} tickets para <strong>{reunion_name}</strong> están listos. ¡Nos vemos en la fiesta! 🎊"
158
- "</p>"
159
- "<p style='font-size:16px;margin-top:24px;'>"
160
- "¡Que lo disfrutes!<br><em>El equipo de Congrats 🥳</em>"
161
- "</p>"
162
- ),
163
- required_vars=["name", "reunion_name", "tickets"],
164
- ),
165
-
166
-
167
- "test_app_running": EmailTemplate(
168
- subject="🚀 Test OK – Congrats 🎉",
169
- plain_body=(
170
- "¡Hola {name}! 🚀\n\n"
171
- "Tu aplicación Congrats está activa y rockeando. 🤘\n\n"
172
- "Sigue brillando,\nEl equipo de Congrats 🥳"
173
- ),
174
- html_body=wrap_html(
175
- "<p style='font-size:16px;'>¡Hola <strong>{name}</strong>! 🚀</p>"
176
- "<p style='font-size:16px;margin:24px 0;'>"
177
- "La prueba de funcionamiento pasó. Tu app está lista para la fiesta. 🎉"
178
- "</p>"
179
- "<p style='font-size:16px;margin-top:24px;'>"
180
- "Sigue brillando.<br><em>El equipo de Congrats 🥳</em>"
181
- "</p>"
182
- ),
183
- required_vars=["name"],
184
- ),
185
- }
@@ -1,25 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: epok-toolkit
3
- Version: 1.11.1
4
- Summary: Una herramienta para la gestión de tareas y procesos en Django con Celery.
5
- Author-email: Fernando Leon Franco <fernanlee2131@gmail.com>
6
- License: MIT
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: Framework :: Django
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.12.9
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: Django>=5.0.2
15
- Requires-Dist: djangorestframework>=3.16.0
16
- Requires-Dist: celery[redis]>=5.5.3
17
- Requires-Dist: django-celery-beat>=2.6.0
18
- Requires-Dist: colorstreak>=0.1.0
19
- Requires-Dist: PyJWT>=2.10.1
20
- Dynamic: license-file
21
-
22
- # EPOK Toolkit
23
-
24
- Esta libreria contiene utilidades
25
-
File without changes
File without changes
File without changes