fix(machine): seed cassettes on first boot + add atm-transactions script

Cassette inventory was never initialized in SQLite, so
recordTransaction's UPDATE decrements were no-ops against an empty
table. Now the Electron main process seeds cassettes from
VITE_LAMASSU_CASSETTES or the model preset on first boot.

Also adds an atm-transactions CLI script (with --summary, --inventory,
--type, --today, --last, --since filters) and sqlite to the NixOS
system packages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-28 11:55:00 -05:00
commit e63f8ab9f6
3 changed files with 189 additions and 0 deletions

View file

@ -230,6 +230,50 @@ ipcMain.handle('hal:cleanup', async () => {
// App lifecycle
app.whenReady().then(() => {
initDatabase()
// Seed cassettes from env/preset if DB table is empty.
// This ensures recordTransaction() can decrement cassette counts
// even before the operator explicitly sets them via the UI.
const existing = loadCassettes()
if (existing.length === 0) {
let seedCassettes: { denomination: number; count: number }[] = []
// Priority 1: explicit VITE_LAMASSU_CASSETTES env var
const cassettesJson = process.env.VITE_LAMASSU_CASSETTES
if (cassettesJson) {
try {
seedCassettes = JSON.parse(cassettesJson)
} catch (e) {
console.warn('[Electron] Failed to parse VITE_LAMASSU_CASSETTES:', e)
}
}
// Priority 2: default presets per model
if (seedCassettes.length === 0) {
const model = process.env.VITE_LAMASSU_MACHINE_MODEL || 'sintra'
const presets: Record<string, { denomination: number; count: number }[]> = {
douro: [
{ denomination: 100, count: 50 },
{ denomination: 200, count: 50 },
],
sintra: [{ denomination: 20, count: 50 }],
tejo: [
{ denomination: 5, count: 500 },
{ denomination: 20, count: 500 },
{ denomination: 50, count: 500 },
{ denomination: 100, count: 500 },
],
gaia: [{ denomination: 20, count: 50 }],
}
seedCassettes = presets[model] || []
}
if (seedCassettes.length > 0) {
setCassettes(seedCassettes)
console.log('[Electron] Seeded cassettes from config:', seedCassettes)
}
}
createWindow()
app.on('activate', () => {