from pathlib import Path from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas from app.models.invoice import Invoice from app.models.client import Client from datetime import datetime PDF_DIR = Path("/app") / "storage" / "pdfs" PDF_DIR.mkdir(parents=True, exist_ok=True) def generate_invoice_pdf(invoice: Invoice, client: Client) -> str: """ Generate a PDF for an invoice and return the path to the PDF file. """ # Create a unique filename for the PDF filename = f"invoice_{invoice.invoice_number}_{datetime.now().strftime('%Y%m%d%H%M%S')}.pdf" pdf_path = PDF_DIR / filename # Create a PDF using ReportLab c = canvas.Canvas(str(pdf_path), pagesize=letter) # Add invoice information to the PDF c.setFont("Helvetica-Bold", 18) c.drawString(50, 750, f"Invoice #{invoice.invoice_number}") c.setFont("Helvetica", 12) c.drawString(50, 730, f"Status: {invoice.status}") c.drawString(50, 715, f"Issued Date: {invoice.issued_date}") c.drawString(50, 700, f"Due Date: {invoice.due_date}") # Add client information c.setFont("Helvetica-Bold", 14) c.drawString(50, 670, "Client Information") c.setFont("Helvetica", 12) c.drawString(50, 655, f"Name: {client.name}") c.drawString(50, 640, f"Email: {client.email}") if client.company: c.drawString(50, 625, f"Company: {client.company}") if client.address: c.drawString(50, 610, f"Address: {client.address}") if client.phone: c.drawString(50, 595, f"Phone: {client.phone}") # Add invoice items c.setFont("Helvetica-Bold", 14) c.drawString(50, 560, "Invoice Items") c.setFont("Helvetica", 12) y = 540 c.drawString(50, y, "Description") c.drawString(300, y, "Quantity") c.drawString(370, y, "Unit Price") c.drawString(450, y, "Total") y -= 20 total = 0 for item in invoice.items: item_total = item.quantity * item.unit_price total += item_total c.drawString(50, y, item.description) c.drawString(300, y, str(item.quantity)) c.drawString(370, y, f"${item.unit_price:.2f}") c.drawString(450, y, f"${item_total:.2f}") y -= 15 # Add a page break if needed if y < 50: c.showPage() c.setFont("Helvetica-Bold", 14) c.drawString(50, 750, "Invoice Items (continued)") c.setFont("Helvetica", 12) y = 730 # Add total c.setFont("Helvetica-Bold", 14) c.drawString(370, y - 20, "Total:") c.drawString(450, y - 20, f"${total:.2f}") # Add footer with notes if invoice.notes: c.setFont("Helvetica-Bold", 12) c.drawString(50, 50, "Notes:") c.setFont("Helvetica", 10) c.drawString(50, 35, invoice.notes) c.save() return str(pdf_path)