From 328fe9f985f94bfd3ecf918864c985d55de34fa9 Mon Sep 17 00:00:00 2001 From: "Daniel (elordenador)" <54474838+dsaub@users.noreply.github.com> Date: Mon, 23 Mar 2026 08:19:14 +0000 Subject: [PATCH] feat: Implement PDF receipt generation and email sending for purchases --- tienda/pdf.py | 39 +++++++++++++++++++++++++++++++++++++++ tienda/tasks.py | 23 +++++++++++++++++++++++ tienda/views.py | 11 +++++++++++ 3 files changed, 73 insertions(+) create mode 100644 tienda/pdf.py diff --git a/tienda/pdf.py b/tienda/pdf.py new file mode 100644 index 0000000..66027dd --- /dev/null +++ b/tienda/pdf.py @@ -0,0 +1,39 @@ +from fpdf import FPDF +import string, random +class Recibo(FPDF): + def header(self): + self.set_font('Arial', 'B', 15) + self.cell(0, 10, 'RECIBO DE PAGO', ln=True, align='C') + self.ln(10) + + def footer(self): + self.set_y(-15) + self.set_font('Arial', 'I', 8) + self.cell(0, 10, f'Pagina {self.page_no()}', align='C') + +def generar_recibo(cliente: str, total: float, objetos: list, metodo_pago: str): + pdf = Recibo() + pdf.add_page() + pdf.set_font("Arial", size=12) + + pdf.cell(0, 10, f"Cliente: {cliente}", ln=True) + pdf.cell(0, 10, f"") + + DATA = [] + DATA.append( + ("Cant.", "Nombre", "Precio Unit.", "Subtotal") + ) + + pdf.cell(0, 10, "DETALLE DEL COBRO", ln=True, align='C') + pdf.ln(5) + + with pdf.table() as table: + for data_row in DATA: + row = table.row() + for datum in data_row: + row.cell(datum) + pdf.ln(5) + pdf.set_font("Arial", "B", 12) + pdf.cell(0, 10, f'TOTAL A PAGAR: {total} €', align="R") + return pdf.output(dest="S") + \ No newline at end of file diff --git a/tienda/tasks.py b/tienda/tasks.py index bdc6503..4d9f9d3 100644 --- a/tienda/tasks.py +++ b/tienda/tasks.py @@ -1,9 +1,11 @@ from celery import shared_task from django.conf import settings from django.template.loader import render_to_string +from django.core.mail import EmailMessage from .utilities import send_email, send_hemail from .vars import login_message, verify_message import random, string +from . import pdf from .models import User, VerificationCode @shared_task @@ -51,3 +53,24 @@ def enviar_correo_recuperacion(email: str): ) send_hemail(email, "Reset de Contraseña", html_content, "Estas reseteando la contraseña...") + + +# Purchased items should be a list of dictionary, the dictionary must follow this tags: amount, product name, price (each) +@shared_task +def process_purchase(user_id: int, purchased_items: list, payment_method: str): + user = User.objects.get(id=user_id) + total = 0 + for i in purchased_items: + total += i["price"]*i["amount"] + pdf_data = pdf.generar_recibo(user.get_full_name(), total, purchased_items, payment_method) + + email = EmailMessage( + subject="Tu recibo de compra", + body = "Hola, adjunto encontrarás el recibo de tu reciente transacción", + from_email = settings.DEFAULT_FROM_EMAIL, + to = [user.email] + ) + + email.attach("recibo.pdf", pdf_data, "application/pdf") + + email.send() \ No newline at end of file diff --git a/tienda/views.py b/tienda/views.py index f665639..63d29d3 100644 --- a/tienda/views.py +++ b/tienda/views.py @@ -328,6 +328,7 @@ def create_order_from_cart(request, payment_method, payment_reference="", shippi order_total = Decimal("0.00") items_with_totals = [] + purchased_items = [] for item in cart_items: product = item.product @@ -338,6 +339,13 @@ def create_order_from_cart(request, payment_method, payment_reference="", shippi ) order_total += line_total_with_vat items_with_totals.append((item, unit_price_with_vat, line_total_with_vat)) + purchased_items.append( + { + "amount": item.quantity, + "product_name": product.name, + "price": float(unit_price_with_vat), + } + ) with transaction.atomic(): order = Order.objects.create( @@ -364,6 +372,9 @@ def create_order_from_cart(request, payment_method, payment_reference="", shippi cart.items.all().delete() + if request.user.is_authenticated and purchased_items: + tasks.process_purchase.delay(request.user.id, purchased_items, payment_method) + return order