Accounting
When your workspace has the commerce ledger path enabled (typically Web & store, Invoicing, and/or Payments on the workspace and Space), the desk exposes Accounting in the shell: Chart of accounts, Journals, and Trial balance.
Routes may be Space-scoped (?host=…) or workspace-scoped (/dxp/core/accounting/…):
| Screen | Space-scoped route | Workspace route |
|---|---|---|
| Chart of accounts | /dxp/accounting/chart?host=… | /dxp/core/accounting/chart |
| Journals | /dxp/accounting/journals?host=… | /dxp/core/accounting/journals |
| Trial balance | /dxp/accounting/trial-balance?host=… | /dxp/core/accounting/trial-balance |
Legacy ledger URLs redirect to journals:
| Legacy | Redirect |
|---|---|
/dxp/core/ledger | /dxp/core/accounting/journals |
/dxp/sites/ledger?host=… | /dxp/accounting/journals?host=… |
Day-to-day use
- Chart — Maintain account codes (DXP defaults include cash, payment clearing, accounts receivable, VAT payable, sales revenue). Use Ensure default COA to seed the chart; add or edit accounts from the slide-in.
- Journals — Review entries by source (All, Sales, Invoices, Manual) or post a balanced manual entry from the slide-in.
- Trial balance — Per-account activity and balance columns aggregated from all journals in the book (not capped like the journals list). Footer totals should tie when entries balance.
- Ledger travel — Toolbar button opens the as-of panel; when you pick a UTC instant, Journals and Trial balance reload for that moment only. See Ledger travel (as-of audit).
Accounting data is not the same as Products pricing or Exchange order lists; use Products for catalogue sale windows and Exchange for operational order lookup.
Consolidation (CRM vs accounting)
Under Space settings → Modules, two independent toggles control whether a branch Space shares data with a parent:
| Toggle | Field | Effect |
|---|---|---|
| CRM consolidation | consolidation_parent_site_id | Contacts and companies read/write in the parent Space Mongo database. Visible when the CRM module is on for the Space. |
| Accounting consolidation | accounting_consolidation_parent_site_id | Chart of accounts, journals, and trial balance use the parent Space ledger book (book_id = parent Space id). Visible when Web & store, Invoicing, or Payments is on. |
Sibling Spaces without accounting consolidation each keep a separate book (their own Space id). CRM consolidation alone does not share the ledger.
API (staff, same module gates as accounting UI):
POST /dxp/api/crm/consolidation— body{ "enabled": true, "parent_site_id": "<hex>" }POST /dxp/api/accounting/consolidation— body{ "enabled": true, "parent_site_id": "<hex>" }
Automation (journals)
When the engine is connected (ES_ENGINE_ADDR on platform), these actions post balanced journals (idempotent on replay):
| Event | Source filter | Typical lines (DXP COA) |
|---|---|---|
| Order mark paid | Sales | Dr 1100 payment clearing / Cr 4000 sales revenue |
| Invoice issue | Invoices | Dr 1200 AR / Cr 4000 revenue (+ Cr 2100 VAT payable when ES_VAT_COLLECTING=1) |
| Invoice mark paid | Invoices | Dr 1100 clearing / Cr 1200 AR |
Invoice lifecycle API (staff, invoicing or ledger module):
POST /dxp/api/commerce/invoices— create draft (currency,total_minor, optionalmemo,customer_email)POST /dxp/api/commerce/invoices/{id}/issue— accrual journalPOST /dxp/api/commerce/invoices/{id}/mark-paid— payment journal
Order mark paid: POST /dxp/api/commerce/orders/{id}/mark-paid.
Manual QA checklist
Use this list before release or after accounting changes. Run with platform + engine up and engine gRPC reachable from platform.
Prerequisites
| Check | How |
|---|---|
| Engine running | gRPC reachable from platform (ES_ENGINE_ADDR) |
| Staff session | Signed into /dxp as staff |
| Modules | Workspace has commerce ledger path; enable on test Space under Space settings → Modules |
| Two Spaces (consolidation) | e.g. HQ + branch, each with ?host= |
| Mongo billing DB | Engine uses billing Mongo for accounting_* collections (not memory-only) |
1. Navigation and gating
- Commerce sidebar shows Chart of accounts, Journals, Trial balance when ledger module is effective.
- With module off, accounting routes return 403 or hidden nav.
-
/dxp/core/ledger→ 301 to/dxp/core/accounting/journals. -
/dxp/sites/ledger?host=…→ 301 to/dxp/accounting/journals?host=…(host preserved). - Open Space via
?host=; scope banner on accounting pages shows correct Space and book id.
2. Chart of accounts (/dxp/accounting/chart)
- Ensure default COA seeds DXP accounts (1000, 1100, 1200, 2100, 4000, 4900).
- Add account (e.g.
5100expense) → appears in table. - Edit account (name, type, active) persists after reload.
- Deactivate account → manual journal picker excludes or engine rejects inactive code on post.
-
GET /dxp/api/accounting/accounts?ensure=1returns accounts (browser network tab or curl as staff).
3. Journals (/dxp/accounting/journals)
- All / Sales / Invoices / Manual tabs filter correctly.
- New journal entry: two+ balanced lines, post → appears under Manual; debits = credits.
- Replay safety: repeat mark-paid / issue with same idempotency → no duplicate row.
- Line detail shows account codes and Dr/Cr amounts.
4. Trial balance (/dxp/accounting/trial-balance)
- Empty book: empty state or zero rows, no error.
- After manual journal: rows and footer totals balance (balance Dr = balance Cr when books balance).
-
GET /dxp/api/accounting/trial-balancereturns JSON withrowsand totals. - Ledger travel: travel to a past instant → trial balance and journals shrink to entries on or before that time; Return to now restores live totals.
-
GET /dxp/api/accounting/trial-balance?as_of=…matches the travelled UI.
5. Per-Space books (siblings)
Two sibling Spaces, no consolidation:
- Manual journal on Space A → visible only on A’s trial balance / journals.
- Space B unchanged.
6. CRM vs accounting consolidation
CRM consolidation only:
- Enable on branch with parent id → People uses parent CRM DB.
- Branch trial balance still uses branch book (CRM toggle does not share ledger).
Accounting consolidation:
Enable on branch with parent id → scope banner references parent; journals/trial balance use parent book.
Post on branch appears on parent trial balance when consolidation on.
Disable → branch book is separate again.
CRM and accounting API consolidation endpoints update different fields.
7. Sales → journal
- Create order,
POST …/orders/{id}/mark-paid→ Sales journal (Dr 1100 / Cr 4000). - Mark paid again → no second journal.
- Sales tab shows the entry.
8. Invoice → journal
- Create draft → issue → mark paid via commerce invoice API.
- Invoices tab shows entries; trial balance reflects AR, revenue, then clearing.
- Replay issue / mark-paid → no duplicate journals.
9. Regression
-
/dxp/core/accounting/*without active Space: clear error, not wrong book. - Non-staff → API 403.
- Engine down → service unavailable, not silent success.
- With accounting consolidation on, order mark paid and invoice issue post to parent book.
Sign-off
| Area | Pass? | Notes |
|---|---|---|
| COA CRUD | ||
| Manual journals | ||
| Trial balance | ||
| Sales journals | ||
| Invoice journals | ||
| CRM consolidation only | ||
| Accounting consolidation only | ||
| Both independent | ||
| Sibling isolation |
Related
- Ledger travel (as-of audit)
- Exchange
- Products
- People and CRM — CRM consolidation (separate from ledger)
- Observe → Webhooks —
commerce.order.paid,commerce.invoice.issued,commerce.invoice.paid