@devx-retailos/inventory
v0.1.0
Published
POS-side inventory movement log for retailOS: receive/issue/adjustment entries with quality and 1:1 reconciliation against an external system of record.
Keywords
Readme
@devx-retailos/inventory
POS-side inventory movement log for retailOS: an append-only ledger of physical stock movements (receive / issue / adjustment) per store, with a quality flag and one-to-one reconciliation against an external system of record.
Part of retailOS, a Medusa v2 SDK for offline-store POS systems. Each @devx-retailos/* package is an independently installable Medusa plugin; a brand backend composes the ones it needs in medusa-config.ts.
Overview
Install this module only when POS is the source of truth for physical stock — either by choice, or as a fallback when the external system of record (a WMS, ERP, or storefront) doesn't own stock. It records exactly one log entry per physical movement of a unit, with a direction that matches the goods: a sale issues stock, a return receives it, an exchange does both. When it is not installed, retailOS assumes the external system owns physical stock and records nothing locally.
This module does not compute on-hand balances or reserve stock; it is a movement ledger plus a reconciliation helper. Physical availability still lives in the external system of record.
Installation
npm install @devx-retailos/inventory// medusa-config.ts
module.exports = defineConfig({
plugins: [
{ resolve: "@devx-retailos/rbac", options: {} },
{ resolve: "@devx-retailos/inventory", options: { stockSourceOfTruth: "POS" } },
],
})The module registers under the key retailos_inventory (exported as INVENTORY_MODULE) and registers its permission keys with @devx-retailos/rbac at boot. @devx-retailos/order resolves this module lazily — when present, sales, returns, and exchanges automatically write movements; when absent, they no-op.
Configuration
| Option | Type | Default | Purpose |
| --- | --- | --- | --- |
| stockSourceOfTruth | "POS" \| "EXTERNAL" | "EXTERNAL" | Which system is authoritative. Whichever is source of truth writes first; the other mirrors. The flag informs reconciliation, not whether a movement is recorded. |
Usage
import { INVENTORY_MODULE, type InventoryModuleService } from "@devx-retailos/inventory"
const inventory: InventoryModuleService = container.resolve(INVENTORY_MODULE)
// Record a physical movement. Direction defaults from `reason`
// (SALE→ISSUE, RETURN/EXCHANGE→RECEIVE); only an explicit GOOD receive is sellable.
await inventory.recordMovement({
organization_id: "org_...",
store_id: "store_...", // where the unit physically landed / left
reason: "RETURN",
quantity: 1,
sku: "TEE-BLK-M",
quality_result: "GOOD", // DAMAGED / unchecked is still logged, held aside
source_document_type: "RETURN",
source_document_id: "ret_...",
external_reference: "ret_...", // lets this entry match the external movement 1:1
})
// Reconcile POS movements against the external system — matched 1:1, never summed.
const { matched, quantity_mismatches, unmatched_pos, unmatched_external } =
await inventory.reconcile(
{ store_id: "store_...", since: new Date("2026-07-01") },
[{ reference: "ret_...", quantity: 1 }],
)The pure helpers movementTypeForReason, isSellable, and reconcileOneToOne are exported for use without a container.
Permissions
Registered via @devx-retailos/rbac (also exported as INVENTORY_PERMISSIONS from @devx-retailos/inventory/permissions):
| Key | Description |
| --- | --- |
| inventory.movement.read | View stock movement log entries |
| inventory.movement.record | Record a stock movement (receive / issue / adjustment) |
| inventory.reconcile | Reconcile the POS stock log against the external system of record |
Extension points
This module has no pluggable adapters — it is configured, not extended. Behaviour is controlled by the stockSourceOfTruth option (see Configuration); the external system it reconciles against is supplied per call to reconcile(...) as plain { reference, quantity } rows, so it is agnostic to which WMS/ERP/storefront produced them.
Related packages
@devx-retailos/order— records sale / return / exchange movements against this log when installed.@devx-retailos/unicommerce— one possible external system of record this log can reconcile against.
License
MIT
