On this page
Why this mattersScope of the changeRisk profileWhat to watch post-releaseNot in scope of this PRFor Stakeholders
Why this matters
Dentolize's inventory module has always answered "what does the system think we have?" It has never been able to answer "is that actually true?" Every clinic running physical inventory today either does it entirely outside the app (a spreadsheet, then a manual bulk edit of quantities with no audit trail) or doesn't do it in any structured way at all. Stock Counts closes that gap: a first-class, auditable reconciliation workflow, with the same rigor the rest of the inventory module already has (permissions, audit fields, transactional writes).
Scope of the change
This is a substantial, self-contained addition: 2 new database tables, ~15 new GraphQL operations, a full web UI (list, detail, guided counting modal, Excel upload), a full mobile UI (list, detail, barcode scan, single-line counting), and a cross-cutting safety change — every existing inventory-movement mutation (purchase, usage, transfer, distribution, return, sale, refund, disposal, adjustment, profit) now checks whether the storage it's touching is locked by an open count, and refuses the movement if so.
That last point is the main architectural risk and the main architectural win in one: it touches the shared code path that every inventory mutation runs through (handleCompleteInventoryTransactions), which means the locking guarantee is centrally enforced (good — no mutation can accidentally bypass it) but also means a bug in that shared check has clinic-wide blast radius across all inventory types, not just counts. See Opening a Count & Locking Storages for exactly where that check lives and how it's guarded against races.
Risk profile
- Data integrity, not data loss. Nothing about this feature deletes or overwrites existing inventory data outside of an explicit, permissioned "confirm and update stock" action — and that action reuses the existing, already-tested order-creation code path rather than introducing a new way to move stock.
- Operational risk is opt-in and visible. The one way this feature can disrupt a clinic's day-to-day (blocking all inventory movement clinic-wide) requires a user to explicitly choose "count every storage" and is called out with an on-screen warning before they can do it. A single-storage count — the expected common case — has a contained blast radius.
- Concurrency is handled, not assumed. Two counts racing to lock the same storage is resolved by a conditional update + row-count check inside a transaction, not by client-side coordination — see the technical detail in Opening a Count.
- Confirmed counts are immutable. Once confirmed, a count (and any adjustment it produced) can't be deleted or altered — it's designed to be trustworthy as a historical record, which matters if a clinic ever needs to explain inventory numbers to an auditor, insurer, or regulator.
What to watch post-release
- Support volume around the "storage is being counted" block — see For Support for the exact error text and resolution steps, worth having agents pre-briefed on.
- Whether clinics discover and use the Excel upload path in practice — the current implementation accepts a well-formed sheet but doesn't ship a matching "download a blank template" feature (see Counting & Recording), which may limit real-world adoption of that specific path until/unless a template generator follows.
- Permission group adoption of the narrower
View Created Stock Countrole — whether clinics actually use it to scope counting staff, or default everyone to full visibility.
Not in scope of this PR
No reporting/analytics surface for count history or variance trends over time — counts are visible individually and in a filterable list, but there's no dashboard rollup (e.g., "clinics with the highest shrinkage this quarter"). Worth flagging if that kind of reporting is expected next.