Python Invoice Generator: Automated PDF Billing With Payment Reminders
Late invoices cause late payments. I automated my entire billing system with 150 lines of Python.
PDF Invoice Generator
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
from datetime import datetime, timedelta
def create_invoice(client_name, client_email, services, invoice_num):
filename = f"invoice_{invoice_num}.pdf"
doc = SimpleDocTemplate(filename, pagesize=letter)
styles = getSampleStyleSheet()
elements = []
elements.append(Paragraph(f"INVOICE #{invoice_num}", styles['Title']))
elements.append(Paragraph(f"Date: {datetime.now().strftime('%B %d, %Y')}", styles['Normal']))
elements.append(Paragraph(f"Due: {(datetime.now() + timedelta(days=30)).strftime('%B %d, %Y')}", styles['Normal']))
elements.append(Paragraph(f"Bill To: {client_name} ({client_email})", styles['Normal']))
rows = [['Description', 'Qty', 'Rate', 'Amount']]
total = 0
for s in services:
amount = s['qty'] * s['rate']
total += amount
rows.append([s['desc'], str(s['qty']), f"${s['rate']:.2f}", f"${amount:.2f}"])
rows.append(['', '', 'TOTAL', f"${total:.2f}"])
table = Table(rows, colWidths=[250, 50, 100, 100])
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('GRID', (0, 0), (-1, -1), 1, colors.black),
('FONTNAME', (0, -1), (-1, -1), 'Helvetica-Bold'),
]))
elements.append(table)
doc.build(elements)
return filename, total
Send Invoice by Email
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
def email_invoice(invoice_file, client_email, client_name, total, due):
msg = MIMEMultipart()
msg['From'] = 'you@gmail.com'
msg['To'] = client_email
msg['Subject'] = f"Invoice - ${total:.2f} due {due}"
msg.attach(MIMEText(f"Hi {client_name}, please find your invoice attached.", 'plain'))
with open(invoice_file, 'rb') as f:
part = MIMEBase('application', 'octet-stream')
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={invoice_file}')
msg.attach(part)
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
smtp.starttls()
smtp.login('you@gmail.com', 'app-password')
smtp.send_message(msg)
Automated Payment Reminders
from datetime import datetime, timedelta
import sqlite3
def run_reminders():
conn = sqlite3.connect('invoices.db')
c = conn.cursor()
# 3 days before due
soon = (datetime.now() + timedelta(days=3)).strftime('%Y-%m-%d')
c.execute('SELECT * FROM invoices WHERE due_date = ? AND paid = 0 AND r1_sent = 0', (soon,))
for inv in c.fetchall():
send_reminder(inv, 'upcoming')
c.execute('UPDATE invoices SET r1_sent = 1 WHERE id = ?', (inv[0],))
# 7 days overdue
overdue = (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')
c.execute('SELECT * FROM invoices WHERE due_date < ? AND paid = 0 AND r2_sent = 0', (overdue,))
for inv in c.fetchall():
send_reminder(inv, 'overdue')
c.execute('UPDATE invoices SET r2_sent = 1 WHERE id = ?', (inv[0],))
conn.commit()
Schedule
0 8 * * * /usr/bin/python3 invoice_reminders.py
Result: Went from 4 hours/week on billing to 20 minutes.
The complete version with Stripe/PayPal integration, expense tracking, and profit/loss reports is in the toolkit below.
Get 50+ Python automation scripts for $9: Python Business Automation Toolkit
Top comments (0)