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.2.tar.gz (41.7 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.2-py3-none-any.whl (52.1 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for django_accounting_dminozadev-1.0.2.tar.gz
Algorithm Hash digest
SHA256 a3857486fdcd27db0c6b0d7bd461e5b6856a9792c1a9b43f6f98553930fbc48b
MD5 0c2efaf0b596c5b6667262f08ddb5821
BLAKE2b-256 53dc967ba3dcb9e8a138823fd184a044c4871f74ad78cab0cbc3fd4d292c2339

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_accounting_dminozadev-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ae6dba2969c87626640390299bd558e3374c50c8fe36e5df4b721835650c7e9e
MD5 3fa6935b3021b481eb891370d10b61b4
BLAKE2b-256 d377d5dd1c1da6b8f6a44528bf45c2a1fe345cc413babe0c010b5e4d96643d3c

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