fix(machine): production hardware fixes for Douro cash-out

- Fix cassette denominations: Douro uses Q100/Q200, not Q20
- Add hal:get-inventory IPC so renderer can read HAL cassette inventory
- Add balance fetch/display to HAL+IPC init path and idle screen
- Enable/disable bill validator via watch on nested state transitions
- Pass fiatCode to state machine context (was hardcoded to USD)
- Preserve currency across state machine resetContext
- Add CANCEL handler to dispenseError state (was stuck)
- Fix remaining hardcoded $ symbols in CashInView

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-25 18:13:45 -05:00
commit 0ea9640f49
9 changed files with 102 additions and 18 deletions

View file

@ -17,7 +17,10 @@ import {
/**
* Create the ATM state machine with injected services
*/
export function createATMMachine(services: Partial<ATMServices> = {}) {
export function createATMMachine(
services: Partial<ATMServices> = {},
options?: { currency?: string }
) {
return setup({
types: {
context: {} as ATMContext,
@ -153,6 +156,7 @@ export function createATMMachine(services: Partial<ATMServices> = {}) {
actions: {
resetContext: assign(({ context }) => ({
...initialContext,
currency: context.currency,
inventory: context.inventory,
cashInSessionId: null,
})),
@ -372,7 +376,7 @@ export function createATMMachine(services: Partial<ATMServices> = {}) {
}).createMachine({
id: 'atm',
initial: 'idle',
context: initialContext,
context: { ...initialContext, ...(options?.currency ? { currency: options.currency } : {}) },
states: {
idle: {
entry: 'resetContext',
@ -637,6 +641,7 @@ export function createATMMachine(services: Partial<ATMServices> = {}) {
target: 'dispensingCash',
actions: 'incrementRetry',
},
CANCEL: '#atm.idle',
},
},
error: {