C

Comprehensive Invoice Module

Streamline your workflow with this automatically, organizes, invoices, receipts. Includes structured workflows, validation checks, and reusable patterns for productivity.

SkillClipticsproductivityv1.0.0MIT
0 views0 copies

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

ComponentPurposeRequired
Invoice NumberUnique identifierYes
Issue DateDate invoice was createdYes
Due DatePayment deadlineYes
Sender InfoYour business detailsYes
Client InfoBill-to detailsYes
Line ItemsServices/products with quantitiesYes
SubtotalSum before tax/discountsYes
TaxApplicable tax calculationsIf applicable
DiscountAny applied discountsIf applicable
TotalFinal amount dueYes
Payment TermsHow and when to payRecommended

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

ParameterDescriptionExample
currencyInvoice currency"USD" / "EUR"
tax_rateDefault tax rate0.08 (8%)
due_daysPayment terms in days30
numberingInvoice number format"date-seq"
templatePDF template style"professional"
logo_pathCompany logo file path"./assets/logo.png"

Best Practices

  1. Use decimal arithmetic for money, never floating point0.1 + 0.2 = 0.30000000000000004 in floating point. Use integer cents internally (store $10.50 as 1050) or Python's Decimal type. Floating point errors in invoices create accounting nightmares.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates