DEV Community

Brad
Brad

Posted on

Python Automation for Freelancers: Build a Complete Billing System

Running a freelance business means drowning in billing admin: creating invoices, tracking payments, sending reminders. Here's how to automate the entire pipeline with Python.

The Problem

Manual billing wastes 3-5 hours per week for most freelancers. That's 150-250 hours per year — at $75/hour billing rate, that's $11,000-$18,000 of lost revenue potential.

Step 1: Invoice Generation

from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
import datetime

def generate_invoice(client_name, items, invoice_num):
    doc = SimpleDocTemplate(f"invoice_{invoice_num}.pdf")
    styles = getSampleStyleSheet()
    story = []
    story.append(Paragraph(f"INVOICE #{invoice_num}", styles["Title"]))
    story.append(Paragraph(f"Date: {str(datetime.date.today())}", styles["Normal"]))

    data = [["Description", "Hours", "Rate", "Total"]]
    total = 0
    for item in items:
        subtotal = item["hours"] * item["rate"]
        total += subtotal
        data.append([item["desc"], item["hours"], f"${item['rate']}", f"${subtotal:.2f}"])
    data.append(["", "", "TOTAL", f"${total:.2f}"])

    table = Table(data)
    table.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), colors.grey),
        ("GRID", (0, 0), (-1, -1), 1, colors.black),
    ]))
    story.append(table)
    doc.build(story)
    return total
Enter fullscreen mode Exit fullscreen mode

Step 2: Automated Email Delivery

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 send_invoice(to_email, client_name, pdf_path, amount, invoice_num):
    msg = MIMEMultipart()
    msg["From"] = "your@email.com"
    msg["To"] = to_email
    msg["Subject"] = f"Invoice #{invoice_num} - ${amount:.2f} due"
    body = f"Hi {client_name}, please find Invoice #{invoice_num} for ${amount:.2f} attached."
    msg.attach(MIMEText(body, "plain"))

    with open(pdf_path, "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_{invoice_num}.pdf")
        msg.attach(part)

    with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
        server.login("you@gmail.com", "app-password")
        server.send_message(msg)
Enter fullscreen mode Exit fullscreen mode

Step 3: Payment Tracking

import sqlite3
import datetime

conn = sqlite3.connect("billing.db")
c = conn.cursor()
c.execute("""
    CREATE TABLE IF NOT EXISTS invoices
    (id TEXT PRIMARY KEY, client TEXT, amount REAL,
     sent_date TEXT, due_date TEXT, paid_date TEXT, status TEXT)
""")
conn.commit()

def record_invoice(invoice_num, client, amount):
    sent = str(datetime.date.today())
    due = str(datetime.date.today() + datetime.timedelta(days=30))
    c.execute("INSERT INTO invoices VALUES (?,?,?,?,?,?,?)",
              (invoice_num, client, amount, sent, due, None, "sent"))
    conn.commit()

def get_overdue():
    today = str(datetime.date.today())
    return c.execute(
        "SELECT * FROM invoices WHERE due_date < ? AND status = ?",
        (today, "sent")
    ).fetchall()
Enter fullscreen mode Exit fullscreen mode

Step 4: Automated Follow-Ups

import schedule
import time

def check_and_follow_up():
    for invoice in get_overdue():
        sent_date = datetime.date.fromisoformat(invoice[3])
        days_late = (datetime.date.today() - sent_date).days
        if days_late == 7:
            send_reminder(invoice[1], invoice[2], "gentle")
        elif days_late == 14:
            send_reminder(invoice[1], invoice[2], "firm")
        elif days_late == 30:
            send_reminder(invoice[1], invoice[2], "urgent")

schedule.every().day.at("09:00").do(check_and_follow_up)
while True:
    schedule.run_pending()
    time.sleep(60)
Enter fullscreen mode Exit fullscreen mode

The Full System

This billing pipeline — plus 40+ more automation scripts covering client onboarding, project tracking, and business reporting — is in the Python Business Automation Toolkit.

Set it up once in about 3 hours. It runs forever with zero ongoing cost.

Top comments (0)