Comprehensive Invoice Module
Streamline your workflow with this automatically, organizes, invoices, receipts. Includes structured workflows, validation checks, and reusable patterns for productivity.
Comprehensive Invoice Module
A practical skill for generating professional invoices programmatically — covering invoice template design, line item calculation, tax handling, PDF generation, multi-currency support, and integration with accounting systems.
When to Use This Skill
Choose Comprehensive Invoice Module when you need to:
- Generate invoices from order data or service records
- Calculate subtotals, taxes, discounts, and totals accurately
- Create PDF invoices with professional formatting
- Handle multi-currency invoicing and exchange rates
- Build automated invoicing workflows for recurring billing
Consider alternatives when:
- You need full accounting software (use QuickBooks, Xero, etc.)
- You need payment processing (use a Stripe/PayPal skill)
- You need expense tracking (use an expense management tool)
Quick Start
# Generate a professional invoice from datetime import date, timedelta def create_invoice(client, items, tax_rate=0.0): subtotal = sum(item["qty"] * item["price"] for item in items) tax = subtotal * tax_rate total = subtotal + tax invoice = { "invoice_number": f"INV-{date.today().strftime('%Y%m%d')}-001", "date": date.today().isoformat(), "due_date": (date.today() + timedelta(days=30)).isoformat(), "client": client, "items": items, "subtotal": round(subtotal, 2), "tax_rate": tax_rate, "tax": round(tax, 2), "total": round(total, 2), "currency": "USD", } return invoice invoice = create_invoice( client={"name": "Acme Corp", "email": "[email protected]"}, items=[ {"description": "Web Development", "qty": 40, "price": 150.00}, {"description": "UI Design", "qty": 20, "price": 125.00}, {"description": "Server Setup", "qty": 1, "price": 500.00}, ], tax_rate=0.08, ) print(f"Invoice: {invoice['invoice_number']}") print(f"Total: ${invoice['total']:,.2f}")
Core Concepts
Invoice Structure
| Component | Purpose | Required |
|---|---|---|
| Invoice Number | Unique identifier | Yes |
| Issue Date | Date invoice was created | Yes |
| Due Date | Payment deadline | Yes |
| Sender Info | Your business details | Yes |
| Client Info | Bill-to details | Yes |
| Line Items | Services/products with quantities | Yes |
| Subtotal | Sum before tax/discounts | Yes |
| Tax | Applicable tax calculations | If applicable |
| Discount | Any applied discounts | If applicable |
| Total | Final amount due | Yes |
| Payment Terms | How and when to pay | Recommended |
PDF Invoice Generation
from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas from reportlab.lib.units import inch def generate_invoice_pdf(invoice, output_path): c = canvas.Canvas(output_path, pagesize=letter) width, height = letter # Header c.setFont("Helvetica-Bold", 24) c.drawString(1*inch, height - 1*inch, "INVOICE") c.setFont("Helvetica", 10) c.drawString(1*inch, height - 1.4*inch, f"#{invoice['invoice_number']}") c.drawString(1*inch, height - 1.6*inch, f"Date: {invoice['date']}") c.drawString(1*inch, height - 1.8*inch, f"Due: {invoice['due_date']}") # Client info c.drawString(4*inch, height - 1.4*inch, "Bill To:") c.setFont("Helvetica-Bold", 10) c.drawString(4*inch, height - 1.6*inch, invoice["client"]["name"]) c.setFont("Helvetica", 10) c.drawString(4*inch, height - 1.8*inch, invoice["client"]["email"]) # Line items table y = height - 2.5*inch c.setFont("Helvetica-Bold", 10) c.drawString(1*inch, y, "Description") c.drawString(4.5*inch, y, "Qty") c.drawString(5.5*inch, y, "Rate") c.drawString(6.5*inch, y, "Amount") y -= 0.3*inch c.setFont("Helvetica", 10) for item in invoice["items"]: amount = item["qty"] * item["price"] c.drawString(1*inch, y, item["description"]) c.drawString(4.5*inch, y, str(item["qty"])) c.drawString(5.5*inch, y, f"${item['price']:,.2f}") c.drawString(6.5*inch, y, f"${amount:,.2f}") y -= 0.25*inch # Totals y -= 0.3*inch c.drawString(5.5*inch, y, "Subtotal:") c.drawString(6.5*inch, y, f"${invoice['subtotal']:,.2f}") y -= 0.25*inch c.drawString(5.5*inch, y, f"Tax ({invoice['tax_rate']*100:.0f}%):") c.drawString(6.5*inch, y, f"${invoice['tax']:,.2f}") y -= 0.3*inch c.setFont("Helvetica-Bold", 12) c.drawString(5.5*inch, y, "Total:") c.drawString(6.5*inch, y, f"${invoice['total']:,.2f}") c.save() print(f"Invoice saved: {output_path}") generate_invoice_pdf(invoice, "invoice.pdf")
Invoice Numbering Systems
## Numbering Conventions ### Sequential INV-001, INV-002, INV-003... Simple but reveals business volume. ### Date-Based INV-20241215-001 (YYYYMMDD + sequence) Easy to sort and find by date. ### Client-Prefix ACME-001, BETA-001, ACME-002 Groups invoices by client for easy lookup. ### Year-Reset 2024-001, 2024-002... → 2025-001 Resets sequence each year. Common in Europe. ### Rules - Never reuse an invoice number - Never have gaps in sequential numbering (auditors notice) - Store the current counter in a database, not in code
Configuration
| Parameter | Description | Example |
|---|---|---|
currency | Invoice currency | "USD" / "EUR" |
tax_rate | Default tax rate | 0.08 (8%) |
due_days | Payment terms in days | 30 |
numbering | Invoice number format | "date-seq" |
template | PDF template style | "professional" |
logo_path | Company logo file path | "./assets/logo.png" |
Best Practices
-
Use decimal arithmetic for money, never floating point —
0.1 + 0.2 = 0.30000000000000004in floating point. Use integer cents internally (store $10.50 as 1050) or Python'sDecimaltype. Floating point errors in invoices create accounting nightmares. -
Generate sequential invoice numbers from a database counter — Never generate invoice numbers from timestamps or random values. Auditors and tax authorities require sequential, gapless numbering. Use a database sequence or atomic counter.
-
Include all legally required fields for your jurisdiction — Requirements vary by country. In the EU, invoices must include VAT numbers for both parties, sequential numbering, and specific descriptions. Research your jurisdiction's requirements before building the template.
-
Store invoice data separately from the PDF — Generate PDFs from structured data, not the other way around. Store the invoice data in JSON/database, and regenerate the PDF if the template changes. Never parse PDFs to extract invoice data.
-
Implement idempotent invoice generation — If the same order is processed twice, it should generate the same invoice, not a duplicate. Use the order ID as part of the invoice generation key to prevent duplicate invoicing.
Common Issues
Tax calculations don't match expected totals — Rounding per line item vs. rounding the total produces different results. Decide on a rounding strategy (per-item or on subtotal) and apply it consistently. Most accounting standards recommend rounding per line item.
Invoice PDFs look different on different systems — Font availability varies across operating systems. Embed fonts in the PDF or use standard PDF fonts (Helvetica, Times, Courier) that are guaranteed to be available in all PDF readers.
Multi-currency invoices have wrong exchange rates — Exchange rates change daily. Record the exchange rate used at the time of invoicing and display it on the invoice. Never calculate conversions at viewing time — the rate may have changed.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.