Data Model
This page is a map, not a full reference — enough to recognise a table
name and know roughly what it's for before opening the actual entity file
in src/core/*/entities/.
Locations — the organisation hierarchy
A Location is any node in the store hierarchy: the top-level "main
store" (a country/central warehouse, isMainStore: true) down through
regional and facility-level stores. Two different parent relationships
exist on the same entity, and it's easy to conflate them:
parentId— the manual location tree (geographic/administrative hierarchy, used for browsing/reporting).parentStoreId— the business/supply-chain hierarchy (who requests stock from whom). This is what order flows actually use.
For a location created through the normal API, parentStoreId mirrors
parentId — but they are conceptually separate fields, and code that
resolves "who does this facility request orders from" always uses
parentStoreId, never parentId.
Users, Roles, and permissions
User— has oneorganization(aLocation) and onerole(nullable — a role-less user can log in but every permission-gated endpoint rejects them with a 403).Role—name+permissions: string[](capability strings) +isSystem(the 4 built-in roles — see Permissions — can't be deleted).
Products, Batches, Suppliers
Product— belongs to aProductType, optionally trackshasExpirationDate, can be linked to multipleSuppliers.Batch— a specific lot of aProductfrom a specificSupplier, with its ownbatchNumberandexpirationDate.Supplier— just contact/identity info; batches reference it.
Stock and StockMovement
Stock— the current balance of one(product, batch, organizationUnit)triple. This is the row that gets read/written on every debit or credit.StockMovement— an append-only ledger row recording why aStockbalance changed:TranType(IN/OUT),PartTranType(Arrival,Request,Return,Wastage, ...),quantity,stockBalance/currentBalance(before/after snapshot), and who posted it. Every order approval, arrival, and return creates one or more of these.
Orders
Order— has aFromOrgand aReceiverOrg(which is which depends onOrderType— see the Order Lifecycle page), anOrderType(RequestorReturn), and astatusthat drives the whole workflow.OrderDetails— one line item per product on an order:quantity(requested),quantityApproved,quantityReceived,batch,isPosted(whether its stock movement has actually happened), and — for a shortfall —shortfallResolutionDetails, a self-reference to theOrderDetailsrow created when the shortfall gets resolved as a return.OrderShortfallSubmission— created when a receiver acknowledges less than what was approved; tracks the reason, its ownstatus(Pending/Approved/Rejected), and who reviewed it.