Database Reference
PostgreSQL, 214 live tables across 11 domains, reconstructed from the full migration history
(0001–0225). Every table, column, primary/foreign key and CHECK constraint value documented here was
read directly from the live schema’s own migration files - nothing was written from general ERP knowledge.
Where something couldn’t be verified, it was left out rather than guessed.
Dropped/renamed tables, kept out of this reference: price_list_group_prices, item_variant_attributes,
item_variant_attribute_values, item_variances, sticker_settings, pos_expenses (all dropped).
notification_templates was renamed to notification_templates_deprecated and still exists, historical only.
Read this before writing any query
These are the conventions that hold almost everywhere in the schema - the single most valuable thing on this page, and the source of most wrong queries if skipped.
business_idis the tenant key. Always filter on it. Row-Level Security exists but only binds the restrictedinfinityportal_reportsrole, not the main app connection - it will not save you.- Documents are cancelled, never deleted. A
status = 'cancelled'row still exists. Filtering onpayment_statusalone can inflate figures - e.g. a POS-cancelled A/R invoice hasstatus='cancelled'ANDpayment_status='unpaid', so exclude cancelled explicitly:AND status <> 'cancelled'. statusvocabularies differ between document types.draft/posted/closed/cancelledon sales/finance documents is not the same set asopen/closed/cancelledon requests, orinitiated/posted/cancelledon A/P invoices. Check the specific table’s ownCHECKconstraint, don’t assume.- Document numbers are unique per business only -
UNIQUE (business_id, document_no). Never join ondocument_noalone. - Line-level consumption counters track partial fulfilment. A source line carries a running counter
(
ordered_quantity,received_quantity,invoiced_quantity,returned_quantity,credited_quantity) plusrow_status(open/closed, sometimescancelled) - this is how “partially received” or “partially invoiced” is represented, not a separate flag. - Money, quantity and rate columns have consistent types: money is
numeric(14,2)(older tablesnumeric(12,2)), quantitiesnumeric(14,3), tax ratesnumeric(6,3), percentagesnumeric(5,2). net_amountvsline_totalon purchasing lines:net_amountis tax-exclusive (what G/L and costing use);line_totalis tax-inclusive. Sales lines only ever haveline_total.- Header totals are persisted, not derived. The cascade is
items_subtotal→header_discount_amount→taxable_value(post-discount, pre-tax base) →tax_total→ charges/fee amounts →grand_total. Don’t recompute from lines - the header-discount cascade won’t reproduce exactly. reference_type/reference_idpairs are polymorphic with no FK. Found onstock_movements,journal_entries,item_batches,item_serials,batch_reservations,gift_vouchers,loyalty_point_transactions, andchange_money_transactions- join by matchingreference_typeto the target table yourself.- Stock on hand has no denormalized column. It’s
SUM(stock_movements.quantity)grouped byitem_id(+warehouse_id); quantities are signed. - G/L account resolution for an item follows
items.gl_accounts_by:'item_group'→item_groups.*_account_id;'warehouse'→warehouses.*_account_id;'item_level'→items.*_account_id. These are mutually exclusive, not a cascade.gl_account_determination_defaultsis the per-business fallback used only where the chosen source leaves an account NULL. - There is no
users.namecolumn. Display name isfirst_name || ' ' || last_name. - Multi-currency amount columns are additive. Every pre-existing amount column stays in base currency;
foreign_*columns andcurrency_id/exchange_rateare NULL/0 on a base-currency document. - Two differently-purposed numbering tables exist.
document_sequencesis the legacy counter (still used forbatch_numberandpos_terminal);document_numbering_series(+_years/_periods) is the live numbering engine everything else uses.
The 11 domains
| Domain | What it covers |
|---|---|
| Core / Shared | Businesses, users, roles, settings, numbering, notifications, print, auth |
| Master Data | Items, business partners, tax, warehouses, delivery partners |
| Purchasing | Purchase Request → PO → GRN → A/P Invoice, landed costs |
| Inventory | Stock movements, batches/serials, transfers, counting |
| Production | BOMs, production orders, issue/receipt |
| Sales & A/R | Quotation → Order → A/R Invoice, returns, dunning |
| Promotions, Loyalty & Vouchers | Promotions engine, gift vouchers, loyalty, change money |
| Finance & G/L | Chart of accounts, journal entries, payments, cheques, fixed assets |
| POS | Terminals, sales, void/cancel events, register sessions |
| Approvals & Workflow | The template/graph-based approval engine |
| AI / INFI | Chat history and per-business automation toggles |
When you’re ready to write a real report, the Query Cookbook has worked, tested SQL for the questions people ask most often.