Inventory & stock
One row per product — every product, including freshly imported ones — with a clear split between what you physically have, what's promised, and what's truly sellable. Plus transfers, cycle counts and the movement ledger.
🏪 The number that matters: available
FurnFlow tracks stock as available-to-promise. The moment an order reserves a unit, that unit is committed even though it's still in the building:
So a product can read out of stock and have units arriving — you'll see both. Backlog (units you owe beyond stock) and incoming (units arriving on transfers) are tracked separately.
📋 Every column, explained
| Column | Meaning |
|---|---|
| On hand | Physical units across branches. |
| Reserved | Committed to open order lines (reserved − already delivered). |
| Available | On hand − reserved. The sellable number. |
| Backlog | Open procurement quantity — units owed beyond stock. |
| Incoming | Units arriving on pending transfers. |
| Reorder point | The threshold that triggers low-stock & reorder suggestions. |
| Branches / Warehouses | Which branches hold it and which warehouses serve them. |
| Health | out_of_stock · low_stock · overstock · healthy |
🎨 Variants & the deep view
Products carry variants (colour / fabric / size / finish) with their own stock. Click a product for the deep detail: per-variant and per-branch stock, plus the full movement ledger.
📥 Getting stock in
- Filter by In / Low / Out and search by name, SKU or category.
- Import products from CSV/XLSX with column mapping and images — it handles large files and maps every column resiliently.
- Adjust stock directly with a reason, or move it with a transfer.
🔁 Transfers
Stock only moves at the edges. It leaves the source on ship (blocked if there isn't enough on hand) and only arrives at the destination on receive (which auto-reserves any waiting backlog). Pick the exact colour/size — the modal shows live source on-hand and prevents over-transfers.
🔢 Cycle counts
- Open a count session — scope it to all, low stock, or a category.
- Enter counts — record the physical numbers you find.
- Submit for review.
- Approve — the variance (counted − system) is applied to stock and an audit row records the reconciliation.
Session statuses: open → submitted → approved (or cancelled).
📒 The movement ledger
Every change to stock is a ledger row, so you can always answer "why is this number what it is?". Movement types include:
ship receive receive_damage receive_quarantine transfer_out transfer_in transfer_cancel_return pick pick_out pick_cancel_in pick_cancel_out putaway putaway_out bin_move bin_move_out return_restock adjustment count_variance
Order reservations are also tracked in the ledger but recorded against the reason order_reservation:<orderId> rather than a movement type.
✏️ Adjustments & reasons
When physical reality differs from the system outside a count or transfer — breakage, samples, found stock — record a direct adjustment with a reason. It posts an adjustment row to the ledger so the change is explained and auditable.
🔑 Who can do what
| Action | Roles |
|---|---|
| View inventory | Manager, warehouse, buyer, admin (+ executive read-only). |
| Adjust stock | Warehouse, manager, admin. |
| Request / approve transfers | Warehouse requests; manager approves. |
| Receive transfers / POs | Warehouse, manager. |
| Run / approve cycle counts | Warehouse runs; manager approves. |
❓ FAQ
A product shows 0 available but we have units — why?
They're all reserved to open orders. On hand − reserved = available, and available is 0. Fulfil or cancel an order to free them, or bring more stock in.
I shipped a transfer but the destination still shows nothing.
Stock arrives only when the destination receives it. Until then it's in_transit / incoming.