Skip to main content

Configurable double-entry accounting package for Django REST Framework

Project description

django-accounting

A configurable, installable double-entry accounting package for Django REST Framework.

Covers: Chart of Accounts · General Ledger · Accounts Receivable · Accounts Payable · Inventory with batch/expiry tracking · Multi-warehouse · Tax rates & groups.


Installation

pip install django-accounting

Add to INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "django_accounting.core.apps.CoreConfig",
    "django_accounting.ledger.apps.LedgerConfig",
    "django_accounting.tax.apps.TaxConfig",
    "django_accounting.inventory.apps.InventoryConfig",
    "django_accounting.ar.apps.ARConfig",
    "django_accounting.ap.apps.APConfig",
]

Add URLs:

# urls.py
path("api/accounting/", include("django_accounting.urls")),

Run migrations:

python manage.py makemigrations \
    accounting_core accounting_ledger accounting_tax \
    accounting_inventory accounting_ar accounting_ap
python manage.py migrate

Configuration

All settings go under a single ACCOUNTING dict in settings.py. Every key is optional — the defaults are shown below.

ACCOUNTING = {
    # ── Currency & precision ─────────────────────────────────────────────
    "DEFAULT_CURRENCY": "PHP",       # ISO 4217 code
    "MONEY_DECIMAL_PLACES": 2,       # monetary amounts (invoice totals, etc.)
    "COST_DECIMAL_PLACES": 6,        # unit costs (preserves precision)
    "QTY_DECIMAL_PLACES": 4,         # quantities
    "RATE_DECIMAL_PLACES": 4,        # tax rates

    # ── Document number prefixes ─────────────────────────────────────────
    "INVOICE_NUMBER_PREFIX": "INV",
    "BILL_NUMBER_PREFIX": "BILL",
    "JOURNAL_ENTRY_PREFIX": "JE",
    "PAYMENT_NUMBER_PREFIX": "PAY",

    # ── Feature flags ────────────────────────────────────────────────────
    "ENABLE_BATCH_TRACKING": True,   # enforce batch FK on items/movements
    "ENABLE_EXPIRY_TRACKING": True,  # enforce expiration_date on batches
    "ENABLE_MULTI_WAREHOUSE": True,  # allow multiple warehouse locations
    "ENABLE_TAX": True,
    "ENABLE_SOFT_DELETE": False,     # soft-delete instead of hard-delete
    "AUTO_POST_JOURNAL_ENTRIES": False,

    # ── Defaults ─────────────────────────────────────────────────────────
    "DEFAULT_PAYMENT_TERMS_DAYS": 30,
    "DEFAULT_CREDIT_LIMIT": "0.00",
    "EXPIRY_WARNING_DAYS": 30,       # used by /item-batches/expiring_soon/

    # ── Swappable models ─────────────────────────────────────────────────
    "CUSTOMER_MODEL": None,          # e.g. "myapp.ExtendedCustomer"
    "VENDOR_MODEL": None,

    # ── Serializer behaviour ─────────────────────────────────────────────
    # Inject extra read-only fields onto any serializer by model name:
    "SERIALIZER_EXTRA_FIELDS": {
        "Invoice": ["erp_reference"],
        "Customer": ["loyalty_tier"],
    },

    # Mark fields as write-once (read-only on updates) by model name:
    "SERIALIZER_WRITE_ONCE_FIELDS": {
        "Invoice":      ["invoice_number", "customer"],
        "Bill":         ["bill_number", "vendor"],
        "JournalEntry": ["entry_number"],
    },
}

API Endpoints

All endpoints are under /api/accounting/ (or your configured prefix).

Resource URL
Accounts (COA) /accounts/ + /accounts/tree/
Fiscal Years /fiscal-years/
Fiscal Periods /fiscal-periods/
Journal Entries /journal-entries/
Tax Authorities /tax-authorities/
Tax Rates /tax-rates/
Tax Groups /tax-groups/
Item Categories /item-categories/
Items /items/
Item Batches /item-batches/ + /item-batches/expiring_soon/
Warehouses /warehouses/
Warehouse Locations /warehouse-locations/
Inventory Balances /inventory-balances/ (read-only)
Inventory Movements /inventory-movements/
Customers /customers/
Invoices /invoices/
Payments /payments/
Invoice Payments /invoice-payments/
Vendors /vendors/
Bills /bills/
Bill Payments /bill-payments/

Serializer features

Dynamic field selection

Trim any response via query params — available on every endpoint:

GET /invoices/123/?fields=id,invoice_number,total_amount
GET /customers/456/?exclude=phone,address

Or pass via code:

InvoiceSerializer(invoice, fields=["id", "total_amount"])

Write-once fields

Fields listed in ACCOUNTING["SERIALIZER_WRITE_ONCE_FIELDS"] become read-only on updates. The defaults protect invoice_number, bill_number, and entry_number. Add your own:

ACCOUNTING = {
    "SERIALIZER_WRITE_ONCE_FIELDS": {
        "Invoice": ["invoice_number", "customer", "currency"],
    }
}

Extra fields

Inject additional read-only fields onto any serializer without subclassing:

ACCOUNTING = {
    "SERIALIZER_EXTRA_FIELDS": {
        "Customer": ["loyalty_points"],   # must exist on the model
    }
}

Extending models

Swappable Customer / Vendor

# myapp/models.py
from django_accounting.ar.models import Customer

class ExtendedCustomer(Customer):
    loyalty_points = models.IntegerField(default=0)
    assigned_rep = models.ForeignKey("auth.User", null=True, on_delete=models.SET_NULL)
# settings.py
ACCOUNTING = {"CUSTOMER_MODEL": "myapp.ExtendedCustomer"}

Lifecycle signals

Connect to any of these in your AppConfig.ready():

from django_accounting.signals import invoice_posted, batch_expiring_soon

@receiver(invoice_posted)
def on_invoice_posted(sender, invoice, journal_entry, **kwargs):
    send_invoice_email(invoice)

@receiver(batch_expiring_soon)
def on_expiry_warning(sender, batch, days_remaining, **kwargs):
    notify_warehouse_manager(batch, days_remaining)

Available signals: account_created, journal_entry_posted, invoice_created/posted/paid/voided, bill_created/posted/paid/voided, payment_received, payment_applied, disbursement_made/applied, inventory_received/issued/transferred/adjusted, batch_created, batch_expired, batch_expiring_soon, low_stock_alert.


Running tests

pip install -e ".[dev]"
pytest

Package structure

django_accounting/
├── conf.py              ← ACCOUNTING settings + helpers
├── mixins.py            ← Abstract model mixins (UUID, timestamps, soft-delete, currency)
├── serializer_mixins.py ← DynamicFields, WriteOnce, ExtraFields
├── signals.py           ← Lifecycle signals
├── admin.py             ← Django admin registrations
├── apps.py              ← AppConfig for each sub-app
├── urls.py              ← DRF router + ViewSets
├── core/                ← Account, FiscalYear, FiscalPeriod
├── ledger/              ← JournalEntry, JournalLine
├── tax/                 ← TaxAuthority, TaxRate, TaxGroup, TaxLine
├── inventory/           ← Item, ItemBatch, Warehouse, InventoryBalance, InventoryMovement
├── ar/                  ← Customer, Invoice, Payment, InvoicePayment
└── ap/                  ← Vendor, Bill, BillPayment

License

MIT

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

django_accounting_dminozadev-1.0.0.tar.gz (41.6 kB view details)

Uploaded Source

Built Distribution

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

django_accounting_dminozadev-1.0.0-py3-none-any.whl (51.9 kB view details)

Uploaded Python 3

File details

Details for the file django_accounting_dminozadev-1.0.0.tar.gz.

File metadata

File hashes

Hashes for django_accounting_dminozadev-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e04eef3a20a6baed9608ea7f4b8d65adf31f09d5f170a30387957d32b5b67e7a
MD5 fb4997ae6bc17e52a064805f08871922
BLAKE2b-256 9f578c7ccb6c3a6134e473cff3923959fd509c22d2c516a406e84c2fcc93c67c

See more details on using hashes here.

File details

Details for the file django_accounting_dminozadev-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_accounting_dminozadev-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 460727e90bebebaf4a6deacb7696991d5b34a218b6565f3d4151a7b4b265138f
MD5 2efa7c11821636522dbdf2c11e2db692
BLAKE2b-256 4f5c6809b079b65420a0ae990e20210484027a5ce04dc5baa8bbbcfd564ca7dc

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