feat: Create PDFExporter class for invoice generation
This commit introduces a `PDFExporter` class to handle PDF invoice generation logic. This separates PDF creation from the main application logic, improving modularity. - Created PDFExporter class with methods for generating PDF invoices. - Moved PDF generation code from MainWindow to PDFExporter. - Added attributes for company and client information.
This commit is contained in:
parent
0aeff69da8
commit
0df9e879d0
1 changed files with 115 additions and 0 deletions
115
pdf_exporter.py
Normal file
115
pdf_exporter.py
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# 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
|
||||
|
||||
|
||||
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 export_to_pdf(self, log_entries):
|
||||
try:
|
||||
filename = f"invoice_{self.invoice_number}.pdf"
|
||||
c = canvas.Canvas(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)
|
||||
|
||||
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}")
|
||||
|
||||
# --- 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
|
||||
|
||||
c.setFont("Helvetica-Bold", 12)
|
||||
c.drawString(inch, bill_to_y, "Bill To:") # "Bill To:" label
|
||||
|
||||
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"]]
|
||||
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"],
|
||||
entry["project"],
|
||||
f"{hours:.2f}",
|
||||
f"${self.hourly_rate:.2f}",
|
||||
f"${line_total:.2f}",
|
||||
]
|
||||
)
|
||||
|
||||
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}")
|
||||
Loading…
Add table
Add a link
Reference in a new issue