Skip to main content

Framework-agnostic invoice management with pluggable storage backends

Project description

py-invoices

Framework-agnostic invoice management with pluggable storage backends.

Features

  • Pluggable Storage Backends: Swap between SQLite, PostgreSQL, MySQL or in-memory storage
  • Framework-Agnostic: Designed for integration into any Python application
  • Type-Safe: Built on pydantic-invoices schemas with full type hints
  • Modern: Fully supports pydantic-invoices 1.1.0 (Enums, Computed Fields, Datetime)
  • Flexible: Optional dependencies - install only what you need

Installation

# Basic installation (schemas only)
pip install py-invoices

# With SQLite support
pip install py-invoices[sqlite]

# With PostgreSQL support
pip install py-invoices[postgres]

# With MySQL support
pip install py-invoices[mysql]

# With PDF generation
# With HTML generation only (lightweight, no WeasyPrint)
pip install py-invoices[html]

# With PDF generation (includes HTML support)
pip install py-invoices[pdf]

# Everything
pip install py-invoices[all]

PDF Generation Requirements

PDF generation uses WeasyPrint, which requires system-level libraries for rendering (Pango, GObject, Cairo).

macOS:

brew install pango libffi
# You may also need to set the library path:
export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_FALLBACK_LIBRARY_PATH

Linux/Ubuntu:

sudo apt-get install python3-pip python3-cffi python3-brotli libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0

For more details, see the WeasyPrint installation guide.

Quick Start

from datetime import datetime
from py_invoices import RepositoryFactory
from pydantic_invoices.schemas import ClientCreate, InvoiceCreate, InvoiceLineCreate, InvoiceStatus

# Initialize with memory backend
factory = RepositoryFactory(backend="memory")

# Get repositories
client_repo = factory.create_client_repository()
invoice_repo = factory.create_invoice_repository()

# Create a client
client = client_repo.create(ClientCreate(
    name="Acme Corp",
    address="123 Business St",
    tax_id="12-3456789"
))

# Create an invoice
invoice = invoice_repo.create(InvoiceCreate(
    number="INV-2025-0001",
    issue_date=datetime.now(),
    status=InvoiceStatus.UNPAID,
    client_id=client.id,
    client_name_snapshot=client.name,
    client_address_snapshot=client.address,
    client_tax_id_snapshot=client.tax_id,
    lines=[
        InvoiceLineCreate(
            description="Professional Services",
            quantity=40,
            unit_price=150.0
        )
    ]
))

print(f"Created invoice {invoice.number} for ${invoice.total_amount}")

Configuration

Environment Variables

Configure backends using environment variables or .env files:

# Set environment variables
export INVOICES_BACKEND=sqlite
export INVOICES_DATABASE_URL=sqlite:///invoices.db
export INVOICES_DATABASE_ECHO=false
from py_invoices import RepositoryFactory

# Automatically loads from environment variables and .env file
factory = RepositoryFactory.from_settings()

Using .env File

Create a .env file in your project root:

INVOICES_BACKEND=sqlite
INVOICES_DATABASE_URL=sqlite:///invoices.db
INVOICES_DATABASE_ECHO=false
# INVOICES_TEMPLATE_DIR=templates
INVOICES_OUTPUT_DIR=output
from py_invoices import RepositoryFactory

# Loads configuration from .env file automatically
factory = RepositoryFactory.from_settings()

Programmatic Configuration

from py_invoices import InvoiceSettings, RepositoryFactory

settings = InvoiceSettings(
    backend="sqlite",
    database_url="sqlite:///invoices.db",
    database_echo=False
)

factory = RepositoryFactory.from_settings(settings)

Available Settings

Setting Environment Variable Default Description
backend INVOICES_BACKEND memory Backend type: memory, sqlite, postgres, or mysql
database_url INVOICES_DATABASE_URL None Database connection URL
database_echo INVOICES_DATABASE_ECHO false Enable SQL query logging
template_dir INVOICES_TEMPLATE_DIR None Directory for invoice templates (defaults to included)
output_dir INVOICES_OUTPUT_DIR output Directory for generated files

Core Services

PDF Generation

Generate professional PDF/HTML invoices using Jinja2 templates:

from py_invoices.core import PDFService

# Company details for the invoice header
company = {
    "name": "My Company",
    "address": "123 HQ Blvd, Tech City",
    "tax_id": "US-99999"
}

pdf_service = PDFService(output_dir="output")

# Generate to file
pdf_path = pdf_service.generate_pdf(invoice=invoice, company=company)

# Generate to memory (bytes)
pdf_bytes = pdf_service.generate_pdf_bytes(invoice=invoice, company=company)

HTML Generation (Lightweight)

For scenarios where you only need HTML (e.g. emails) or don't want the heavy WeasyPrint dependency:

from py_invoices.core import HTMLService

# Uses only Jinja2 (no WeasyPrint)
html_service = HTMLService(output_dir="output")

# Generate HTML string
html_content = html_service.generate_html(invoice=invoice, company=company)

# Save to HTML file
html_path = html_service.save_html(invoice=invoice, company=company)

Industry Standard (Factur-X / UBL)

Generate enterprise-ready invoices compliant with European standards:

Factur-X (PDF/A-3 + XML): A standard PDF that includes the invoice data as a structured XML file (Factur-X/ZUGFeRD compliant).

# Requires py-invoices[pdf]
facturx_path = pdf_service.generate_facturx(invoice=invoice, company=company)

UBL (XML Only): Universal Business Language Version 2.1 XML invoices.

from py_invoices.core import UBLService

ubl_service = UBLService(output_dir="output")
ubl_path = ubl_service.save_ubl(invoice, company)

In-Memory Generation (Bytes)

Generate files directly to memory without saving to disk:

# Generate Factur-X bytes
pdf_bytes = pdf_service.generate_facturx_bytes(invoice, company)

# Generate UBL XML bytes
xml_bytes = ubl_service.generate_ubl_bytes(invoice, company)

Audit Logging

Track every change in the invoice lifecycle:

from py_invoices.core import AuditService

audit_service = AuditService(audit_repo=factory.create_audit_repository())

# Log event
audit_service.log_invoice_created(invoice, user_id="system_admin")
audit_service.log_payment_added(invoice, payment, user_id="cashier_01")

# Retrieve logs
logs = audit_service.get_logs(invoice_id=invoice.id)

Invoice Numbering

Generate sequential, formatted invoice numbers:

from py_invoices.core import NumberingService

# Default format: INV-{year}-{sequence:04d}
numbering = NumberingService(invoice_repo=invoice_repo)
next_number = numbering.generate_number()

Storage Backends

Memory (Testing)

Perfect for development and testing:

factory = RepositoryFactory(backend="memory")

SQLite (Production-Ready)

For single-file database storage:

factory = RepositoryFactory(
    backend="sqlite",
    database_url="sqlite:///invoices.db"
)

PostgreSQL (Enterprise)

For production deployments:

factory = RepositoryFactory(
    backend="postgres",
    database_url="postgresql://user:pass@localhost/invoices"
)

MySQL

For common web server setups:

factory = RepositoryFactory(
    backend="mysql",
    database_url="mysql+pymysql://user:pass@localhost/invoices"
)

Architecture

py-invoices (business logic)
    ↓ depends on
pydantic-invoices (schemas)

Development

# Clone repository
git clone https://github.com/yourorg/py-invoices
cd py-invoices

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Type checking
mypy py_invoices

# Linting
ruff check py_invoices

License

MIT License - see LICENSE file for details.

Related Packages

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_invoices-1.0.2.tar.gz (158.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_invoices-1.0.2-py3-none-any.whl (43.5 kB view details)

Uploaded Python 3

File details

Details for the file py_invoices-1.0.2.tar.gz.

File metadata

  • Download URL: py_invoices-1.0.2.tar.gz
  • Upload date:
  • Size: 158.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.9

File hashes

Hashes for py_invoices-1.0.2.tar.gz
Algorithm Hash digest
SHA256 f2a8aa1ec41a88d58adebff37b61a79a2d2bbc8ca3db8c320728a19a19f4689b
MD5 8cb6dac39333c4575d1e0fcfbbb24c9c
BLAKE2b-256 d800bf9b46ce3da30d2f79ad43d5201588a6a7d5f65b66829d4480510a524efc

See more details on using hashes here.

File details

Details for the file py_invoices-1.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for py_invoices-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 93c73c19d1cd46bdde8b9859401634b61b73573dded17945d61d1320287378b0
MD5 6de84fe889e4577100c42c493bc45ea6
BLAKE2b-256 4c60390269f21f20ed5fe4a109e33f3a4ca06a07d4c29a857e3f0adf029c8ce4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page