bug(machine): manual_dispense never decrements DB cassette counts — inventory overstates after operator remediation #76
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the dev-branch architecture review, alongside the position-decrement fix (#75).
Problem
recordTransaction()'s cassette-decrement branch fires only fortype === 'cash_out'(apps/machine/electron/state-store.ts). The operator command poller records manual dispenses astype: 'manual_dispense'(apps/machine/electron/main.ts:683), so a remediation dispense:hal-service.tsdispenseCashdecrementsbays[i].count),cassettesrows instate.db.The two inventory views then disagree:
hal:get-inventory(in-memory) is correct until restart;state:get-inventory(DB) overstates. On the next boot,hal:initseeds bays from the DB, so the overstated counts become the live truth — the machine believes it has bills that were already dispensed to a customer.Typical failure path
dispensed: 0recorded, no decrement — correct).manual_dispensetransaction is recorded, but DB cassette counts are untouched.Suggested fix
Include
manual_dispensein the position-keyed decrement branch (it receivesresult.cassetteswith per-baydispensedcounts, same shape as cash-out). Add a regression test next tostate-store-transactions.test.ts.One design question to settle first: whether a remediation dispense against a
ref_txidwhose original cash-out did already decrement (partial-dispense cases) should decrement again — the answer is probably yes (decrement reflects physical bills leaving bays, and the original tx only decremented what it actually dispensed), but worth a deliberate look at theremediateflow before changing it.