Skip to content

/admin/accounting

Path: /admin/accounting
Namespace: admin
Resource: accounting

Overview

The Accounting section provides complete double-entry accounting functionality including chart of accounts, accounting equations (transactions), and accounting entries.

ERPax implements double-entry accounting where:

  • Accounting Accounts - Chart of accounts (Assets, Liabilities, Equity, Revenue, Expenses)
  • Accounting Equations - Double-entry transactions ensuring debits = credits
  • Accounting Transactions - Individual transaction records for auditing

All accounting resources support standard REST operations (GET, POST, PATCH, DELETE).

Relationships

AccountingEquation Relationships

Model Associations

AccountingEquation connects to the following resources:

Invoice (Polymorphic)
  • Type: belongs_to polymorphic via accountable_type and accountable_id
  • Fields: accountable_type, accountable_id
  • Description: Source document that triggered this accounting equation. Typically an Invoice, but can be other accountable resources.
  • Reverse: Invoice has many accounting equations (invoice.accounting_equations)
  • API Access:
    • Direct: accounting_equation.accountable_type, accounting_equation.accountable_id
    • Filter: GET /admin/accounting_equations.json?q[accountable_type_eq]=Invoice&q[accountable_id_eq]=123
    • Nested: GET /admin/invoices/:id/accounting_equations.json (equations for an invoice)
  • Related Documentation: Invoices
  • Key Pattern: When an invoice is confirmed, accounting equations are automatically created with entries for seller, buyer, line items, and taxes.
  • Example: Get accounting equations for an invoice:
    javascript
    const equations = await fetch('/admin/invoices/123/accounting_equations.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Address
  • Type: belongs_to via address_id and partner_id (optional)
  • Fields: address_id, partner_id
  • Description: Address perspective and partner address for accounting context. Used for customer/vendor-specific accounting treatment.
  • Reverse: Address has many accounting equations (address.accounting_equations)
  • API Access:
    • Direct: accounting_equation.address_id, accounting_equation.partner_id
    • Filter: GET /admin/accounting_equations.json?q[address_id_eq]=123
  • Related Documentation: Addresses
Domain
  • Type: belongs_to via host_id
  • Field: host_id
  • Description: Tenant domain for multi-tenant scoping. All accounting equations belong to a domain.
  • Reverse: Domain has many accounting equations (domain.accounting_equations)
  • API Access:
    • Direct: Included in accounting equation response as host_id
    • Filter: GET /admin/accounting_equations.json?q[host_id_eq]=1
  • Related Documentation: Domains
AccountingEntry[]
  • Type: has_many via accounting_equation_id
  • Description: Individual account entries that make up this equation. Each equation has multiple entries (at least one debit and one credit).
  • Reverse: AccountingEntry belongs to AccountingEquation (entry.accounting_equation)
  • API Access:
    • Direct: Included in accounting equation response as entries array
    • Nested: GET /admin/accounting_equations/:id/accounting_entries.json
  • Example: Get all entries for an accounting equation:
    javascript
    const entries = await fetch('/admin/accounting_equations/123/accounting_entries.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

AccountingEntry Relationships

Model Associations

AccountingEntry connects to the following resources:

AccountingEquation
  • Type: belongs_to via accounting_equation_id
  • Field: accounting_equation_id
  • Description: Parent accounting equation. Each entry belongs to an equation that ensures debits equal credits.
  • Reverse: AccountingEquation has many accounting entries (equation.entries)
  • API Access:
    • Direct: Included in accounting entry response as accounting_equation_id
    • Filter: GET /admin/accounting_entries.json?q[accounting_equation_id_eq]=123
    • Nested: GET /admin/accounting_equations/:id/accounting_entries.json
  • Related Documentation: Accounting Equations
AccountingAccount
  • Type: belongs_to via accounting_account_id
  • Field: accounting_account_id
  • Description: Account being debited or credited. Links the entry to the chart of accounts.
  • Reverse: AccountingAccount has many accounting entries (account.entries)
  • API Access:
    • Direct: Included in accounting entry response as accounting_account_id
    • Filter: GET /admin/accounting_entries.json?q[accounting_account_id_eq]=10
  • Related Documentation: Accounting Accounts
  • Example: Get all entries for a specific account:
    javascript
    const entries = await fetch('/admin/accounting_entries.json?q[accounting_account_id_eq]=10', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Domain
  • Type: belongs_to via host_id
  • Field: host_id
  • Description: Tenant domain for multi-tenant scoping. All accounting entries belong to a domain.
  • Reverse: Domain has many accounting entries (via accounting equations)
  • API Access:
    • Direct: Included in accounting entry response as host_id
    • Filter: GET /admin/accounting_entries.json?q[host_id_eq]=1
  • Related Documentation: Domains

AccountingAccount Relationships

Model Associations

AccountingAccount connects to the following resources:

Domain
  • Type: belongs_to via host_id
  • Field: host_id
  • Description: Tenant domain for multi-tenant scoping. Each domain has its own chart of accounts.
  • Reverse: Domain has many accounting accounts (domain.accounting_accounts)
  • API Access:
    • Direct: Included in accounting account response as host_id
    • Filter: GET /admin/accounting_accounts.json?q[host_id_eq]=1
  • Related Documentation: Domains
AccountingEntry[]
  • Type: has_many via accounting_account_id
  • Description: All accounting entries using this account. Track all debits and credits to the account.
  • Reverse: AccountingEntry belongs to AccountingAccount (entry.account)
  • API Access:
    • Direct: Included in accounting account response as entries array (if present)
    • Filter: GET /admin/accounting_entries.json?q[accounting_account_id_eq]=10
  • Example: Get all entries for an account:
    javascript
    const entries = await fetch('/admin/accounting_entries.json?q[accounting_account_id_eq]=10', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Reverse Associations

The following resources can have accounting accounts assigned:

Address[]
  • Type: has_many on Address via credit_account_id and debit_account_id
  • Description: Addresses can have assigned credit and debit accounts for customer/vendor-specific accounting treatment.
  • API Access:
    • Filter: GET /admin/addresses.json?q[credit_account_id_eq]=10
    • Filter: GET /admin/addresses.json?q[debit_account_id_eq]=10
  • Related Documentation: Addresses
Invoice[]
  • Type: has_many on Invoice via credit_account_id and debit_account_id
  • Description: Invoices can have assigned credit and debit accounts for automatic accounting.
  • API Access:
    • Filter: GET /admin/invoices.json?q[credit_account_id_eq]=10
  • Related Documentation: Invoices
Item[]
  • Type: has_many on Item via credit_account_id, debit_account_id, tax_credit_account_id, tax_debit_account_id
  • Description: Items can have assigned accounts for automatic accounting when used in invoice lines.
  • API Access:
    • Filter: GET /admin/items.json?q[credit_account_id_eq]=10
  • Related Documentation: Items
InvoiceLine[] (ItemTransfer)
  • Type: has_many on InvoiceLine via same account fields as Item
  • Description: Invoice lines inherit account assignments from items or can have custom assignments.
  • API Access:
    • Filter: GET /admin/item_transfers.json?q[credit_account_id_eq]=10
  • Related Documentation: Item Transfers

Relationship Patterns

Automatic Accounting on Invoice Confirmation
  • Use Case: When an invoice is confirmed, accounting equations are automatically created
  • Example: Confirm an invoice to trigger automatic accounting:
    javascript
    const invoice = await fetch('/admin/invoices/123/confirm', {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      }
    }).then(r => r.json());
    // Accounting equations and entries are automatically created
Accessing Accounting for Invoice
  • Use Case: Get all accounting entries created from an invoice
  • Example:
    javascript
    // Get accounting equations for invoice
    const equations = await fetch('/admin/invoices/123/accounting_equations.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
    
    // Get all entries from all equations
    const allEntries = [];
    for (const equation of equations.accounting_equations) {
      const entries = await fetch(`/admin/accounting_equations/${equation.id}/accounting_entries.json`, {
        credentials: 'include',
        headers: { 'Accept': 'application/json' }
      }).then(r => r.json());
      allEntries.push(...entries.accounting_entries);
    }
Account Balance Calculation
  • Use Case: Calculate account balance by summing debit and credit entries
  • Example:
    javascript
    // Get all entries for an account
    const entries = await fetch('/admin/accounting_entries.json?q[accounting_account_id_eq]=10', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
    
    // Calculate balance
    const balance = entries.accounting_entries.reduce((sum, entry) => {
      return sum + (entry.debit_amount_cents || 0) - (entry.credit_amount_cents || 0);
    }, 0);

Key Features

  • Double-Entry Accounting: Automatic balance checking (debits = credits)
  • Automatic Integration: Accounting entries created automatically when invoices are confirmed
  • Chart of Accounts: Hierarchical account structure with standard numbering
  • Transaction Tracking: Complete audit trail of all accounting transactions

Accounting Accounts

Path: /admin/accounting_accounts

Overview

The AccountingAccount resource represents the chart of accounts for double-entry accounting. Accounts are organized hierarchically using codes and support different account types.

Account Structure

  • Hierarchical Codes: Accounts use hierarchical codes (e.g., "1000/100/10") separated by /
  • Account Types:
    • Balance accounts (Assets, Liabilities, Equity) - permanent accounts
    • Statement accounts (Revenue, Expenses) - temporary accounts, reset each period
  • Account Codes: Unique per host (multi-tenant)

Standard Account Numbering

  • 1000s - Assets: Current assets, cash, accounts receivable, inventory
  • 2000s - Liabilities: Current liabilities, accounts payable, accrued expenses
  • 3000s - Equity: Capital, retained earnings
  • 4000s - Revenue: Sales revenue, service revenue
  • 5000s - Expenses: Cost of goods sold, operating expenses

Available Operations

List Accounts (GET)

Endpoint: GET /admin/accounting_accounts.json

Request Examples:

bash
curl -X GET "https://your-company.erpax.com/admin/accounting_accounts.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/admin/accounting_accounts.json?q[code_cont]=1000" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/accounting_accounts.json?scope=root" \
  -H "Accept: application/json"

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_accounts.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "accounting_accounts": [
    {
      "id": 1,
      "code": "4000",
      "name": "Sales Revenue",
      "description": "Revenue from sales",
      "account_type": 2,
      "created_at": "2024-01-10T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 1,
    "total_count": 50
  }
}

Create Account (POST)

Endpoint: POST /admin/accounting_accounts.json

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/accounting_accounts.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "accounting_account": {
      "code": "4000",
      "name": "Sales Revenue",
      "description": "Revenue from sales",
      "account_type": 2
    }
  }'

Response (201 Created):

json
{
  "accounting_account": {
    "id": 1,
    "code": "4000",
    "name": "Sales Revenue",
    "account_type": 2,
    "created_at": "2024-01-15T14:30:00Z"
  }
}

Scopes

  • all (default) - All accounts
  • root - Root accounts (top-level accounts)
  • analytic - Analytic accounts (sub-accounts)

Filters

  • code_cont - Search by account code
  • name_cont - Search by account name
  • description_cont - Search by description
  • account_type - Filter by account type (balance, statement)

Accounting Equations

Path: /admin/accounting_equations

Overview

The AccountingEquation resource represents double-entry accounting transactions. Each equation ensures that debits equal credits, maintaining the fundamental accounting equation: Assets = Liabilities + Equity.

Key Features

  • Double-Entry Validation: Automatic balance checking (debits = credits)
  • Invoice Integration: Accounting equations can be associated with invoices
  • Address Association: Equations can be linked to addresses (seller/buyer)
  • Entry Tracking: Each equation contains multiple AccountingEntry records (debits and credits)

Accounting Equation Structure

Each AccountingEquation contains:

  • Multiple AccountingEntry records (debits and credits)
  • Association with Invoice (if created from invoice)
  • Association with Address (seller/buyer)
  • Automatic validation that debits = credits

Available Operations

List Equations (GET)

Endpoint: GET /admin/accounting_equations.json

Request Examples:

bash
curl -X GET "https://your-company.erpax.com/admin/accounting_equations.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/admin/accounting_equations.json?q[invoice_id_eq]=123" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/accounting_equations.json?scope=balanced" \
  -H "Accept: application/json"

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_equations.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "accounting_equations": [
    {
      "id": 1,
      "number": "EQ-2024-001",
      "date": "2024-01-15",
      "description": "Invoice payment",
      "invoice_id": 123,
      "currency_code": "USD",
      "created_at": "2024-01-15T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 1,
    "total_count": 10
  }
}

Create Equation (POST)

Endpoint: POST /admin/accounting_equations.json

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/accounting_equations.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "accounting_equation": {
      "date": "2024-01-15",
      "description": "Invoice payment",
      "invoice_id": 123,
      "currency_code": "USD"
    }
  }'

Note: Accounting equations are typically created automatically when invoices are accounted via invoice.account!.

Response (201 Created):

json
{
  "accounting_equation": {
    "id": 1,
    "date": "2024-01-15",
    "description": "Invoice payment",
    "invoice_id": 123,
    "currency_code": "USD",
    "created_at": "2024-01-15T14:30:00Z"
  }
}

Scopes

  • all (default) - All accounting equations
  • balanced - Equations where debits equal credits
  • unbalanced - Equations where debits do not equal credits (should be none in production)

Filters

  • number_cont - Search by equation number
  • description_cont - Search by description
  • invoice - Filter by associated invoice
  • address - Filter by associated address
  • date - Filter by equation date
  • currency_code - Filter by currency code

Nested Resources

  • Accounting Entries - /admin/accounting_equations/:id/accounting_entries - Individual debit and credit entries

Accounting Transactions

Path: /admin/accounting_transactions

Overview

The AccountingTransaction resource provides transaction-level access to accounting entries for auditing and reporting purposes.

Available Operations

List Transactions (GET)

Endpoint: GET /admin/accounting_transactions.json

Request Examples:

bash
curl -X GET "https://your-company.erpax.com/admin/accounting_transactions.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/admin/accounting_transactions.json?q[date_gteq]=2024-01-01" \
  -H "Accept: application/json"

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_transactions.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "accounting_transactions": [
    {
      "id": 1,
      "date": "2024-01-15",
      "accounting_account_id": 10,
      "debit_cents": 100000,
      "credit_cents": 0,
      "created_at": "2024-01-15T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 1,
    "total_count": 20
  }
}

Show Accounting Transaction (GET /:id)

Endpoint: GET /admin/accounting_transactions/:id.json

Request Example:

bash
curl -X GET "https://your-company.erpax.com/admin/accounting_transactions/1.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_transactions/1.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "accounting_transaction": {
    "id": 1,
    "date": "2024-01-15",
    "accounting_account_id": 10,
    "accounting_equation_id": 5,
    "debit_cents": 100000,
    "credit_cents": 0,
    "description": "Invoice payment entry",
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T12:00:00Z"
  }
}

Create Accounting Transaction (POST)

Endpoint: POST /admin/accounting_transactions.json

Note: Accounting transactions are typically created automatically as part of accounting equations when invoices are confirmed and accounted. Manual creation is usually not necessary and may require special permissions.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/accounting_transactions.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "accounting_transaction": {
      "date": "2024-01-16",
      "accounting_account_id": 10,
      "accounting_equation_id": 5,
      "debit_cents": 50000,
      "credit_cents": 0,
      "description": "Manual adjustment entry"
    }
  }'

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_transactions.json', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    accounting_transaction: {
      date: '2024-01-16',
      accounting_account_id: 10,
      accounting_equation_id: 5,
      debit_cents: 50000,
      credit_cents: 0,
      description: 'Manual adjustment entry'
    }
  })
});
const data = await response.json();

Response (201 Created):

json
{
  "accounting_transaction": {
    "id": 2,
    "date": "2024-01-16",
    "accounting_account_id": 10,
    "accounting_equation_id": 5,
    "debit_cents": 50000,
    "credit_cents": 0,
    "description": "Manual adjustment entry",
    "created_at": "2024-01-16T10:00:00Z"
  }
}

Update Accounting Transaction (PATCH /:id)

Endpoint: PATCH /admin/accounting_transactions/:id.json

Note: Accounting transactions are typically read-only once created to maintain audit integrity. Updates may be restricted or require special permissions.

Request Example:

bash
curl -X PATCH "https://your-company.erpax.com/admin/accounting_transactions/1.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "accounting_transaction": {
      "description": "Updated description"
    }
  }'

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_transactions/1.json', {
  method: 'PATCH',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    accounting_transaction: {
      description: 'Updated description'
    }
  })
});
const data = await response.json();

Response (200 OK):

json
{
  "accounting_transaction": {
    "id": 1,
    "description": "Updated description",
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Delete Accounting Transaction (DELETE /:id)

Endpoint: DELETE /admin/accounting_transactions/:id.json

Note: Accounting transactions are typically not deletable to maintain audit integrity. Deletion may be restricted or require special permissions. Consider using reversal transactions instead.

Request Example:

bash
curl -X DELETE "https://your-company.erpax.com/admin/accounting_transactions/1.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

JavaScript Example:

javascript
const response = await fetch('/admin/accounting_transactions/1.json', {
  method: 'DELETE',
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});

Response (204 No Content):

(empty response)

Business Rules

Double-Entry Accounting

All accounting resources work together to implement double-entry bookkeeping:

  • Each transaction (AccountingEquation) must have equal debits and credits
  • Debits increase assets and expenses
  • Credits increase liabilities, equity, and revenue
  • System automatically validates balance before saving
  • Accounts track balances and are used in financial reporting

Automatic Accounting

  • Invoice Confirmation: When an invoice is confirmed, accounting equations are automatically created
  • Entry Generation: Entries are automatically generated for seller, buyer, line items, and taxes
  • Balance Validation: System automatically validates that debits equal credits
  • Invoices - Invoices create accounting equations when accounted
  • Addresses - Equations can be associated with addresses
  • Items - Items can have accounting accounts assigned

Released under an open source license.