epok-toolkit 1.12.8__py3-none-any.whl
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.
- epok_toolkit/__init__.py +0 -0
- epok_toolkit/apps.py +14 -0
- epok_toolkit/default_settings.py +33 -0
- epok_toolkit/django/__init__.py +6 -0
- epok_toolkit/django/cache.py +130 -0
- epok_toolkit/django/fields.py +30 -0
- epok_toolkit/django/manager.py +38 -0
- epok_toolkit/django/models.py +42 -0
- epok_toolkit/django/response.py +57 -0
- epok_toolkit/django/utils/__init__.py +1 -0
- epok_toolkit/django/utils/magic_link.py +27 -0
- epok_toolkit/django/viewsets.py +98 -0
- epok_toolkit/email/__init__.py +1 -0
- epok_toolkit/email/email_async.py +40 -0
- epok_toolkit/email/engine.py +69 -0
- epok_toolkit/email/templates.py +173 -0
- epok_toolkit/messaging/__init__.py +1 -0
- epok_toolkit/messaging/whatsapp.py +367 -0
- epok_toolkit/messaging/whatsapp_instanced.py +34 -0
- epok_toolkit/pdf/__init__.py +1 -0
- epok_toolkit/pdf/fuentes/Kollektif-Bold.ttf +0 -0
- epok_toolkit/pdf/fuentes/Kollektif-BoldItalic.ttf +0 -0
- epok_toolkit/pdf/fuentes/Kollektif-Italic.ttf +0 -0
- epok_toolkit/pdf/fuentes/Kollektif.ttf +0 -0
- epok_toolkit/pdf/plantillas/Ticket_congrats.png +0 -0
- epok_toolkit/pdf/plantillas/Ticket_congrats2.png +0 -0
- epok_toolkit/pdf/ticket_pdf.py +246 -0
- epok_toolkit-1.12.8.dist-info/METADATA +75 -0
- epok_toolkit-1.12.8.dist-info/RECORD +32 -0
- epok_toolkit-1.12.8.dist-info/WHEEL +5 -0
- epok_toolkit-1.12.8.dist-info/licenses/LICENSE +5 -0
- epok_toolkit-1.12.8.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
from reportlab.lib.utils import ImageReader
|
|
2
|
+
from reportlab.pdfbase import pdfmetrics
|
|
3
|
+
from datetime import date, datetime
|
|
4
|
+
from reportlab.pdfbase.ttfonts import TTFont
|
|
5
|
+
from reportlab.pdfgen import canvas
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from PIL import Image
|
|
9
|
+
from uuid import uuid4, UUID
|
|
10
|
+
import os
|
|
11
|
+
import qrcode
|
|
12
|
+
from io import BytesIO
|
|
13
|
+
import importlib.resources
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
fuente_path = os.path.join(os.path.dirname(__file__), "fuentes", "Kollektif-Bold.ttf")
|
|
18
|
+
pdfmetrics.registerFont(TTFont("kollektif", fuente_path))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def hex_to_rgb(hex_color):
|
|
22
|
+
hex_color = hex_color.lstrip('#')
|
|
23
|
+
lv = len(hex_color)
|
|
24
|
+
return tuple(int(hex_color[i:i + lv // 3], 16) / 255.0 for i in range(0, lv, lv // 3))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Config:
|
|
28
|
+
base_path = os.path.dirname(__file__)
|
|
29
|
+
plantillas = base_path + "/plantillas/"
|
|
30
|
+
plantilla_path = importlib.resources.files("epok_toolkit.pdf.plantillas").joinpath("Ticket_congrats.png")
|
|
31
|
+
output_path = os.path.join(base_path, "ticket_final.pdf")
|
|
32
|
+
fuente = "Helvetica"
|
|
33
|
+
fuente_bold = "kollektif"
|
|
34
|
+
#bg_color = "#0082FF"
|
|
35
|
+
bg_color = "#FFFFFF"
|
|
36
|
+
font_color = "#000000"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Contenedor:
|
|
40
|
+
def __init__(self, x, y, w, h, bold: bool = False):
|
|
41
|
+
self.x = x
|
|
42
|
+
self.y = y
|
|
43
|
+
self.w = w
|
|
44
|
+
self.h = h
|
|
45
|
+
self.color = Config.bg_color
|
|
46
|
+
self.font_size = 28
|
|
47
|
+
self.font_color = Config.font_color
|
|
48
|
+
self.fuente = Config.fuente_bold if bold else Config.fuente
|
|
49
|
+
|
|
50
|
+
def dibujar(self, c):
|
|
51
|
+
c.setFillColorRGB(*hex_to_rgb(self.color))
|
|
52
|
+
c.rect(self.x, self.y, self.w, self.h, stroke=0, fill=1)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def dibujar_texto(self, c, texto):
|
|
56
|
+
c.setFillColorRGB(*hex_to_rgb(self.font_color))
|
|
57
|
+
c.setFont(self.fuente, self.font_size)
|
|
58
|
+
ascent = pdfmetrics.getAscent(self.fuente) * self.font_size / 1000
|
|
59
|
+
descent = abs(pdfmetrics.getDescent(self.fuente) * self.font_size / 1000)
|
|
60
|
+
text_h = ascent + descent
|
|
61
|
+
baseline_x = self.x + self.w / 2
|
|
62
|
+
baseline_y = self.y + (self.h - text_h) / 2 + descent
|
|
63
|
+
c.drawCentredString(baseline_x, baseline_y, texto)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ContenedorTexto(Contenedor):
|
|
67
|
+
def __init__(self, x, y, w, h, bold: bool = False, texto="Demo",
|
|
68
|
+
font_size=28,
|
|
69
|
+
font_color=None,
|
|
70
|
+
color=None,
|
|
71
|
+
fuente=None):
|
|
72
|
+
super().__init__(x, y, w, h, bold=bold)
|
|
73
|
+
self.texto = texto
|
|
74
|
+
if font_size:
|
|
75
|
+
self.font_size = font_size
|
|
76
|
+
if font_color:
|
|
77
|
+
self.font_color = font_color
|
|
78
|
+
if color:
|
|
79
|
+
self.color = color
|
|
80
|
+
if fuente:
|
|
81
|
+
self.fuente = fuente
|
|
82
|
+
|
|
83
|
+
def dibujar(self, c):
|
|
84
|
+
super().dibujar(c)
|
|
85
|
+
self.dibujar_texto(c, self.texto)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class ContenedorQR(Contenedor):
|
|
89
|
+
def __init__(self, x, y, w, h, texto="QR vacío", color=None):
|
|
90
|
+
super().__init__(x, y, w, h)
|
|
91
|
+
self.texto = texto
|
|
92
|
+
if color:
|
|
93
|
+
self.color = color
|
|
94
|
+
|
|
95
|
+
def dibujar(self, c):
|
|
96
|
+
super().dibujar(c)
|
|
97
|
+
qr = qrcode.QRCode(
|
|
98
|
+
version=3,
|
|
99
|
+
error_correction=qrcode.constants.ERROR_CORRECT_H, # type: ignore
|
|
100
|
+
box_size=10,
|
|
101
|
+
border=1,
|
|
102
|
+
)
|
|
103
|
+
qr.add_data(self.texto)
|
|
104
|
+
qr.make(fit=True)
|
|
105
|
+
qr_img = qr.make_image(fill_color="black", back_color="white").convert("RGB") # type: ignore
|
|
106
|
+
qr_img = qr_img.resize((self.w, self.h), Image.LANCZOS) # type: ignore
|
|
107
|
+
buffer = BytesIO()
|
|
108
|
+
qr_img.save(buffer, format="PNG")
|
|
109
|
+
buffer.seek(0)
|
|
110
|
+
c.drawImage(ImageReader(buffer), self.x, self.y, width=self.w, height=self.h)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass
|
|
114
|
+
class TicketPDF:
|
|
115
|
+
nombre_evento: str
|
|
116
|
+
fecha: Optional[date]
|
|
117
|
+
titulo_ticket: str
|
|
118
|
+
precio: float
|
|
119
|
+
edad_min: int
|
|
120
|
+
tipo_evento: str
|
|
121
|
+
direccion: str
|
|
122
|
+
ticket_actual: int
|
|
123
|
+
total_tickets: int
|
|
124
|
+
nombre_persona: str
|
|
125
|
+
uuid: Optional[UUID] = None
|
|
126
|
+
hora_evento: Optional[str] = None
|
|
127
|
+
qr : Optional[str] = None
|
|
128
|
+
|
|
129
|
+
def __post_init__(self):
|
|
130
|
+
if isinstance(self.fecha, str):
|
|
131
|
+
self.fecha = datetime.strptime(self.fecha, "%Y-%m-%d %H:%M")
|
|
132
|
+
elif isinstance(self.fecha, date) and not isinstance(self.fecha, datetime):
|
|
133
|
+
hora = self.hora_evento or "00:00"
|
|
134
|
+
self.fecha = datetime.combine(self.fecha, datetime.strptime(hora, "%H:%M").time())
|
|
135
|
+
if not self.uuid:
|
|
136
|
+
raise ValueError("UUID no puede ser None")
|
|
137
|
+
|
|
138
|
+
self.hora_evento = self.fecha.strftime("%H:%M") # type: ignore
|
|
139
|
+
self.width = 0
|
|
140
|
+
self.height = 0
|
|
141
|
+
self.font_size = 28
|
|
142
|
+
self.font_color = Config.font_color
|
|
143
|
+
self.color = Config.bg_color
|
|
144
|
+
self.fuente = Config.fuente
|
|
145
|
+
with Config.plantilla_path.open("rb") as f:
|
|
146
|
+
self.img = Image.open(f)
|
|
147
|
+
self.img.load()
|
|
148
|
+
self.width, self.height = self.img.size
|
|
149
|
+
self.buffer = BytesIO()
|
|
150
|
+
self.c = canvas.Canvas(self.buffer, pagesize=(self.width, self.height))
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def generate_ticket(self):
|
|
154
|
+
def y(px): return self.height - px
|
|
155
|
+
with Config.plantilla_path.open("rb") as f:
|
|
156
|
+
self.c.drawImage(ImageReader(f), 0, 0, width=self.width, height=self.height, mask='auto')
|
|
157
|
+
|
|
158
|
+
# NOMBRE EVENTO
|
|
159
|
+
nombre_evento = ContenedorTexto(x=260, y=y(210), w=1400, h=90, texto=self.nombre_evento, font_size=78, bold=True)
|
|
160
|
+
nombre_evento.dibujar(self.c)
|
|
161
|
+
|
|
162
|
+
# FECHA
|
|
163
|
+
SPANISH_DAYS = {
|
|
164
|
+
'Monday': 'Lunes', 'Tuesday': 'Martes', 'Wednesday': 'Miercoles',
|
|
165
|
+
'Thursday': 'Jueves', 'Friday': 'Viernes', 'Saturday': 'Sabado', 'Sunday': 'Domingo'
|
|
166
|
+
}
|
|
167
|
+
SPANISH_MONTHS = {
|
|
168
|
+
'January': 'Enero', 'February': 'Febrero', 'March': 'Marzo', 'April': 'Abril',
|
|
169
|
+
'May': 'Mayo', 'June': 'Junio', 'July': 'Julio', 'August': 'Agosto',
|
|
170
|
+
'September': 'Septiembre', 'October': 'Octubre', 'November': 'Noviembre', 'December': 'Diciembre'
|
|
171
|
+
}
|
|
172
|
+
fecha_obj = self.fecha # type: ignore
|
|
173
|
+
day_name = SPANISH_DAYS[fecha_obj.strftime('%A')] # type: ignore
|
|
174
|
+
month_name = SPANISH_MONTHS[fecha_obj.strftime('%B')] # type: ignore
|
|
175
|
+
fecha = f"{day_name}, {fecha_obj.day} {month_name}".upper() #type: ignore
|
|
176
|
+
fecha = ContenedorTexto(x=570, y=y(320), w=900, h=90, texto=fecha, font_size=38, bold=True)
|
|
177
|
+
fecha.dibujar(self.c)
|
|
178
|
+
|
|
179
|
+
# TICKET TITULO
|
|
180
|
+
ticket_titulo = ContenedorTexto(x=260, y=y(525), w=950, h=90, texto=self.titulo_ticket, font_size=68, bold=True)
|
|
181
|
+
ticket_titulo.dibujar(self.c)
|
|
182
|
+
|
|
183
|
+
# PRECIO
|
|
184
|
+
precio = f"{self.precio:,.2f} MXN"
|
|
185
|
+
precio = ContenedorTexto(x=450, y=y(650), w=600, h=90, texto=precio, font_size=58, bold=True)
|
|
186
|
+
precio.dibujar(self.c)
|
|
187
|
+
|
|
188
|
+
# EDAD MINIMA
|
|
189
|
+
edad_min = str(self.edad_min)
|
|
190
|
+
edad_min = ContenedorTexto(x=345, y=y(760), w=80, h=30, texto=edad_min, font_size=18, bold=True)
|
|
191
|
+
edad_min.dibujar(self.c)
|
|
192
|
+
|
|
193
|
+
# HORA DE ACCESO
|
|
194
|
+
hora_evento = ContenedorTexto(x=670, y=y(760), w=80, h=30, texto=self.hora_evento, font_size=18, bold=True) # type: ignore
|
|
195
|
+
hora_evento.dibujar(self.c)
|
|
196
|
+
|
|
197
|
+
# TIPO DE EVENTO
|
|
198
|
+
tipo_evento = ContenedorTexto(x=995, y=y(760), w=150, h=30, texto=self.tipo_evento, font_size=18, bold=True)
|
|
199
|
+
tipo_evento.dibujar(self.c)
|
|
200
|
+
|
|
201
|
+
# DIRECCION
|
|
202
|
+
direccion = ContenedorTexto(x=200, y=y(950), w=1400, h=50, texto=self.direccion, font_size=38, bold=True)
|
|
203
|
+
direccion.dibujar(self.c)
|
|
204
|
+
|
|
205
|
+
# TICKET ACTUAL
|
|
206
|
+
texto = f"Ticket {self.ticket_actual} de {self.total_tickets}"
|
|
207
|
+
ticket_actual = ContenedorTexto(x=680, y=y(1035), w=340, h=50, texto=texto, font_size=28, bold=True)
|
|
208
|
+
ticket_actual.dibujar(self.c)
|
|
209
|
+
|
|
210
|
+
# NOMBRE PERSONA
|
|
211
|
+
nombre_persona = ContenedorTexto(x=1080, y=y(1035), w=760, h=60, texto=self.nombre_persona, font_size=48, bold=True)
|
|
212
|
+
nombre_persona.dibujar(self.c)
|
|
213
|
+
|
|
214
|
+
# UUID
|
|
215
|
+
uuid_string = self.uuid
|
|
216
|
+
# UUID
|
|
217
|
+
uuid_string = str(self.uuid)
|
|
218
|
+
uuid = ContenedorTexto(x=1390, y=y(770), w=400, h=30, texto=uuid_string, font_size=18, bold=True)
|
|
219
|
+
uuid.dibujar(self.c)
|
|
220
|
+
tam = 400
|
|
221
|
+
qr = ContenedorQR(x=1390, y=y(740), w=tam, h=tam, texto=uuid_string, color=Config.bg_color)
|
|
222
|
+
qr.dibujar(self.c)
|
|
223
|
+
|
|
224
|
+
self.c.showPage()
|
|
225
|
+
self.c.save()
|
|
226
|
+
self.buffer.seek(0)
|
|
227
|
+
return self.buffer.getvalue()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
if __name__ == "__main__":
|
|
233
|
+
ticket = TicketPDF(
|
|
234
|
+
nombre_evento="14 aniversario Cerveza Libertad",
|
|
235
|
+
fecha=datetime(2025, 5, 31, 14, 30),
|
|
236
|
+
titulo_ticket="General",
|
|
237
|
+
precio=410,
|
|
238
|
+
edad_min=18,
|
|
239
|
+
tipo_evento="Aniversario",
|
|
240
|
+
direccion="Restaurante dentro de Hacienda del Conde",
|
|
241
|
+
ticket_actual=2,
|
|
242
|
+
total_tickets=5,
|
|
243
|
+
nombre_persona="Carolina Franco Medina",
|
|
244
|
+
uuid=uuid4(),
|
|
245
|
+
)
|
|
246
|
+
ticket.generate_ticket()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: epok-toolkit
|
|
3
|
+
Version: 1.12.8
|
|
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>=2.1.3
|
|
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.12.6'
|
|
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,32 @@
|
|
|
1
|
+
epok_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
epok_toolkit/apps.py,sha256=O3q3CcucJOHjlYIS0VgbKsbtim2hpng_FxpKEG_MlWs,486
|
|
3
|
+
epok_toolkit/default_settings.py,sha256=GdDpwMPzRYNDTDK0zcQKUwgiGYVVhj1Pi1NGAxTE1Io,890
|
|
4
|
+
epok_toolkit/django/__init__.py,sha256=noq8F7jlKE_9ikkOt4VnoYHspxm6zGJ-_N2qF_MvLX4,136
|
|
5
|
+
epok_toolkit/django/cache.py,sha256=gfYCF7HW2ofdJGb1tLTYNQN4f5EVS_izTpHVW3LDqZQ,4121
|
|
6
|
+
epok_toolkit/django/fields.py,sha256=-ajP5qx-4bt9Qz9yW48gTlinTxD1xWPKOEkslqx8cSM,1089
|
|
7
|
+
epok_toolkit/django/manager.py,sha256=3MZcA9wQY4E1KD8XlgZQbzf4wlF9vA8Pntl_gKDWfpA,1350
|
|
8
|
+
epok_toolkit/django/models.py,sha256=E1zj2KetRGszksQvLk3HN5kWkYkEYzJRRmAUOaLJmw8,1090
|
|
9
|
+
epok_toolkit/django/response.py,sha256=O8OHBaKgUQjBeYLLbgTTs669l_4D6swUgAOwswjc-88,1716
|
|
10
|
+
epok_toolkit/django/viewsets.py,sha256=bycP2NyzldHl0pi5vZPHo8x1DzGN7n16kJFTXt_sNZI,3650
|
|
11
|
+
epok_toolkit/django/utils/__init__.py,sha256=zDuoqm_eksZQpL-Bvd_q2KGMtSXfprBjf4TScZiwV6k,25
|
|
12
|
+
epok_toolkit/django/utils/magic_link.py,sha256=GiDuy0kAGdYohGPlBL7rwpKPMpXuB1wJa1k5LTAOm4w,889
|
|
13
|
+
epok_toolkit/email/__init__.py,sha256=pyJwysyVoq6DuYAG72fulsKFoOuAfjw3aBH7FhmYGHc,35
|
|
14
|
+
epok_toolkit/email/email_async.py,sha256=oC0WowWNUpTpXdxo6hJag5gWUaStxI6VBEArEKQxXko,1521
|
|
15
|
+
epok_toolkit/email/engine.py,sha256=IIifqRI9z76pHdrO5oSSZ25aP5txOTAgrj1JuVVPlMY,2387
|
|
16
|
+
epok_toolkit/email/templates.py,sha256=8aQ5E3A0q1Uqc7WZf7Tm_ssj6DgAGNHiLsAd6mrZff4,6136
|
|
17
|
+
epok_toolkit/messaging/__init__.py,sha256=lo0URCOr8tR62ljc0MWTtYZ_YR-tecQaAhhAbyGcOxs,53
|
|
18
|
+
epok_toolkit/messaging/whatsapp.py,sha256=TrMSiKzvnhWOotSDEGil1BGgOJ7jLK7h3MXKdW3zCJw,14114
|
|
19
|
+
epok_toolkit/messaging/whatsapp_instanced.py,sha256=4NVhxkjAi8cxDUwwLWjb6IwjJESSNoVjct8DMiW2SwI,1368
|
|
20
|
+
epok_toolkit/pdf/__init__.py,sha256=Scb1iOYnVIUEiUVHLNaPmcigyD-jOSBs3ws5RmolMKE,33
|
|
21
|
+
epok_toolkit/pdf/ticket_pdf.py,sha256=jktxxjEL4gFfnvXZW7P7y35bllOe9sJ3S-eOkgPcEQw,8913
|
|
22
|
+
epok_toolkit/pdf/fuentes/Kollektif-Bold.ttf,sha256=MiaucCL_aPGhbDl6M0xA2g2nf84MXHGciOd-XSw0XRo,78780
|
|
23
|
+
epok_toolkit/pdf/fuentes/Kollektif-BoldItalic.ttf,sha256=hPMiWYQ0fLFfOKvV_OXFCwAaHnNMYzic_DPiqWPQL5w,71912
|
|
24
|
+
epok_toolkit/pdf/fuentes/Kollektif-Italic.ttf,sha256=1CXPyw43il9u0tQ_7aRzsEaVtg3x3_oJ1vuMMvEaDp8,42048
|
|
25
|
+
epok_toolkit/pdf/fuentes/Kollektif.ttf,sha256=7wTLkVVNUm1giLjIZcWRUH5r2r3o0GjdKic4V1A-pNQ,51128
|
|
26
|
+
epok_toolkit/pdf/plantillas/Ticket_congrats.png,sha256=OSQhVR0j_nLHE6kSJ33BTR-77HM1fNAfJBe2EuX6wVk,157141
|
|
27
|
+
epok_toolkit/pdf/plantillas/Ticket_congrats2.png,sha256=1RBogBdo-8WSMpD3H73HoLgJtr5EC5oVKfOCIWOxPSo,373605
|
|
28
|
+
epok_toolkit-1.12.8.dist-info/licenses/LICENSE,sha256=iLDbGXdLSIOT5OsxzHCvtmxHtonE21GiFlS3LNkug4A,128
|
|
29
|
+
epok_toolkit-1.12.8.dist-info/METADATA,sha256=9vJv3rMmgvtbTBmIP_Pe5-I7wSQUExL4PP61nbl-Al4,2217
|
|
30
|
+
epok_toolkit-1.12.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
epok_toolkit-1.12.8.dist-info/top_level.txt,sha256=Wo72AqIFcfWwBGM5F5iGFw9PrO3WBnTSprFZIJk_pNg,13
|
|
32
|
+
epok_toolkit-1.12.8.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
epok_toolkit
|