fix(cassettes): report a drained machine as drained
getInventory dropped zero-count bays, so a fully dispensed machine returned an empty map — identical to a machine with no cassettes configured. Every caller reads an empty map as "nothing known, ask the hardware": reloadPersistedInventory skipped the update entirely, so the last non-empty snapshot stuck and the public availability beacon went on advertising bills that had already gone out the slot. Zero-count bays are kept, so an empty map now means exactly one thing: no cassettes are configured. Consumers already filter for > 0 before offering a denomination. loadInventoryFromDb returns null when the DB could not be asked at all (browser dev, failed IPC) so callers can still tell "no answer" from an answer of "the bays are empty", and only the former defers to HAL. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
5b22447dae
commit
0d43c4e033
3 changed files with 92 additions and 15 deletions
|
|
@ -14,6 +14,7 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|||
import {
|
||||
closeDatabase,
|
||||
getCashbox,
|
||||
getInventory,
|
||||
initDatabase,
|
||||
loadCassettes,
|
||||
recordTransaction,
|
||||
|
|
@ -260,3 +261,64 @@ describe('state-store: recordTransaction manual_dispense inventory (#76)', () =>
|
|||
expect(countsByPosition()[2]).toBe(49)
|
||||
})
|
||||
})
|
||||
|
||||
describe('state-store: getInventory represents a drained machine', () => {
|
||||
it('keeps configured bays at zero rather than dropping them', () => {
|
||||
recordTransaction({
|
||||
...TX_BASE,
|
||||
txid: 'tx-drain-50s',
|
||||
type: 'cash_out',
|
||||
status: 'complete',
|
||||
bills: [{ denomination: 50, count: 30 }],
|
||||
cassettes: [
|
||||
{
|
||||
name: 'cassette3',
|
||||
position: 3,
|
||||
denomination: 50,
|
||||
provisioned: 30,
|
||||
dispensed: 30,
|
||||
rejected: 0,
|
||||
},
|
||||
],
|
||||
})
|
||||
// The $50 bay is empty but still configured. Dropping the key made this
|
||||
// look like "no inventory known", and callers then fell back to a stale
|
||||
// snapshot or to HAL.
|
||||
expect(getInventory()).toEqual({ 20: 100, 50: 0 })
|
||||
})
|
||||
|
||||
it('reports every bay at zero when the machine is fully drained', () => {
|
||||
for (const [txid, position, denomination, count] of [
|
||||
['d1', 1, 20, 50],
|
||||
['d2', 2, 20, 50],
|
||||
['d3', 3, 50, 30],
|
||||
] as const) {
|
||||
recordTransaction({
|
||||
...TX_BASE,
|
||||
txid,
|
||||
type: 'cash_out',
|
||||
status: 'complete',
|
||||
bills: [{ denomination, count }],
|
||||
cassettes: [
|
||||
{
|
||||
name: `cassette${position}`,
|
||||
position,
|
||||
denomination,
|
||||
provisioned: count,
|
||||
dispensed: count,
|
||||
rejected: 0,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
expect(getInventory()).toEqual({ 20: 0, 50: 0 })
|
||||
})
|
||||
|
||||
it('returns an empty map only when no cassettes are configured', () => {
|
||||
// A fresh DB with no bays at all — the one case that should read as
|
||||
// "nothing known", so callers may legitimately defer to the hardware.
|
||||
closeDatabase()
|
||||
initDatabase(':memory:')
|
||||
expect(getInventory()).toEqual({})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue