refactor: Complete overhaul of the pdf_exporter

This commit is contained in:
Blake Ridgway 2025-04-22 11:37:00 -05:00
parent a849b79a98
commit 4b025b8517

View file

@ -1,115 +1,96 @@
# timelogix/pdf_exporter.py
import datetime
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.platypus import Table, TableStyle
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Preformatted
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.lib import colors
import datetime
class PDFExporter:
def __init__(self):
self.company_name = "Your Company Name"
self.company_address = "123 Main St, Anytown, USA"
self.client_name = "Client Name"
self.client_address = "Client Address"
self.hourly_rate = 60.00
self.invoice_number = 1
def __init__(self, company_name, company_address, client_name, client_address, hourly_rate, invoice_number):
self.company_name = company_name
self.company_address = company_address
self.client_name = client_name
self.client_address = client_address
self.hourly_rate = hourly_rate
self.invoice_number = invoice_number
def export_to_pdf(self, log_entries):
try:
filename = f"invoice_{self.invoice_number}.pdf"
c = canvas.Canvas(filename, pagesize=letter)
def export_to_pdf(self, log_entries, filename):
doc = SimpleDocTemplate(filename, pagesize=letter)
styles = getSampleStyleSheet()
# --- Header ---
c.setFont("Helvetica-Bold", 16)
c.drawString(inch, 7.5 * inch, self.company_name)
c.setFont("Helvetica", 10)
c.drawString(inch, 7.3 * inch, self.company_address)
header_table_data = [
[
Preformatted(f"BILL FROM:\n{self.company_name}\n{self.company_address}\n", styles['Normal']),
Paragraph(f"INVOICE # {self.invoice_number}", styles['Heading1']),
c.setFont("Helvetica-Bold", 12)
c.drawString(4.5 * inch, 7.5 * inch, "Invoice")
c.setFont("Helvetica", 10)
c.drawString(
4.5 * inch, 7.3 * inch, f"Invoice Number: {self.invoice_number}"
)
current_date = datetime.datetime.now().strftime("%Y-%m-%d")
c.drawString(4.5 * inch, 7.1 * inch, f"Date: {current_date}")
],
[
Preformatted(f"BILL TO:\n{self.client_name}\n{self.client_address}\n", styles['Normal']),
Paragraph(f"Invoice Date: {datetime.date.today().strftime('%m/%d/%Y')}", styles['Normal']),
],
]
# --- Client Info ---
bill_to_y = 6.5 * inch # Starting y position for "Bill To:"
line_height = 0.2 * inch # Height for each line of text
header_table_style = TableStyle([
('ALIGN', (0, 0), (0, 0), 'LEFT'),
('ALIGN', (1, 0), (1, 0), 'RIGHT'),
('ALIGN', (0, 1), (0, 1), 'LEFT'),
('ALIGN', (1, 1), (1, 1), 'LEFT'),
('VALIGN', (0, 0), (-1, -1), 'TOP'),
('TOPPADDING', (0, 0), (-1, -1), 0),
('BOTTOMPADDING', (0, 0), (-1, -1), 0),
('LEFTPADDING', (0, 0), (-1, -1), 0),
('RIGHTPADDING', (0, 0), (-1, -1), 0),
])
c.setFont("Helvetica-Bold", 12)
c.drawString(inch, bill_to_y, "Bill To:") # "Bill To:" label
header_table = Table(header_table_data, colWidths=[3*inch, 3*inch])
header_table.setStyle(header_table_style)
c.setFont("Helvetica", 10)
c.drawString(
inch, bill_to_y - line_height, self.client_name
) # Client Name
c.drawString(
inch, bill_to_y - 2 * line_height, self.client_address
) # Client Address
# --- Table ---
data = [["Task", "Project", "Hours", "Rate", "Total"]]
data = [["Date", "Project", "Hours", "Rate", "Total"]]
total_amount = 0
for entry in log_entries:
hours = entry["duration"] / 3600
line_total = hours * self.hourly_rate
total_amount += line_total
data.append(
[
entry["task"],
data.append([
entry["start_time"].split(' ')[0],
entry["project"],
f"{hours:.2f}",
f"${self.hourly_rate:.2f}",
f"${line_total:.2f}",
])
table_style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('GRID', (0, 0), (-1, -1), 1, colors.black),
])
table = Table(data)
table.setStyle(table_style)
totals_style = ParagraphStyle(name='Totals', fontSize=10, alignment=TA_RIGHT)
subtotal = Paragraph(f"Subtotal: ${total_amount:.2f}", totals_style)
tax = Paragraph(f"Tax (0%): $0.00", totals_style)
total = Paragraph(f"Total: ${total_amount:.2f}", totals_style)
notes_style = ParagraphStyle(name='Notes', fontSize=10, alignment=TA_LEFT)
notes = Paragraph("Notes:\nThank you for your business!", notes_style)
elements = [
header_table,
Spacer(1, 12),
table,
Spacer(1, 12),
subtotal,
tax,
total,
Spacer(1, 12),
notes,
]
)
table = Table(data, colWidths=[1.5 * inch, 1.5 * inch, inch, inch, inch])
style = TableStyle(
[
("BACKGROUND", (0, 0), (-1, 0), colors.grey),
("TEXTCOLOR", (0, 0), (-1, 0), colors.whitesmoke),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("BOTTOMPADDING", (0, 0), (-1, 0), 12),
("BACKGROUND", (0, 1), (-1, -1), colors.beige),
("GRID", (0, 0), (-1, -1), 1, colors.black),
]
)
table.setStyle(style)
table.wrapOn(c, letter[0] - 2 * inch, letter[1] - 2 * inch)
table.drawOn(c, inch, 4 * inch)
# --- Totals ---
c.setFont("Helvetica-Bold", 12)
c.drawString(4 * inch, 3.5 * inch, "Subtotal:")
c.setFont("Helvetica", 12)
c.drawRightString(5.5 * inch, 3.5 * inch, f"${total_amount:.2f}")
c.setFont("Helvetica-Bold", 12)
c.drawString(4 * inch, 3.3 * inch, "Tax (0%):")
c.setFont("Helvetica", 12)
c.drawRightString(5.5 * inch, 3.3 * inch, "$0.00")
c.setFont("Helvetica-Bold", 12)
c.drawString(4 * inch, 3.1 * inch, "Total:")
c.setFont("Helvetica", 12)
c.drawRightString(5.5 * inch, 3.1 * inch, f"${total_amount:.2f}")
# --- Notes ---
c.setFont("Helvetica", 10)
c.drawString(inch, 2 * inch, "Notes:")
c.drawString(inch, 1.8 * inch, "Thank you for your business!")
c.save()
print(f"Exported to PDF successfully as {filename}!")
except Exception as e:
print(f"Error exporting to PDF: {e}")
doc.build(elements)