Multi-Account Filter for Account Balances Report

Goal

Change the Account Balance report's single-account filter to accept multiple accounts via comma-separated input.

Current State

  • Single <input type="number"> for account filter (id: input-account)
  • JS treats account as null (all accounts) or a single integer
  • SQL builders use AND account = ${account} equality clause
  • Subtitle shows "Account N" or "All accounts"
  • CSV filename uses single account value
  • Transaction table hides account column when single account is selected

Tasks

Task 1: Update HTML — replace single account input with comma-separated text input

File: clientreports/account-balances/index.html

  • Change <input type="number" id="input-account"> to <input type="text" id="input-accounts">
  • Update label text from "Account" to "Accounts"
  • Update placeholder: "e.g. 12345, 67890"
  • Update hint text to "(blank = all)"
  • Error element id stays as account-error

Task 2: Update JavaScript — parse multiple accounts, update SQL builders, validation, and all references

File: clientreports/account-balances/account-balances.js

Parse function

  • Add parseAccounts(raw) function that:
    • Returns null for empty string (meaning "all accounts")
    • Splits on commas, trims each value, parses as integer
    • Filters out invalid values, returns array of unique positive integers
    • Returns empty array [] if all values are invalid (treated as error)

Validation (validateInputs)

  • Update to read input-accounts instead of input-account
  • Validate each entry is a positive integer
  • Show error listing invalid entries

SQL builders (buildDailyNetSql, buildTxnsSql)

  • Change signature: account param becomes accounts (null | number[])
  • When accounts is null: no clause (all accounts)
  • When accounts is non-empty array: AND account IN (${accounts.join(', ')})
  • Keep existing behavior otherwise

Generate function

  • Parse accounts from input: const accounts = parseAccounts(document.getElementById('input-accounts').value.trim())
  • Pass accounts (array or null) to SQL builders
  • Subtitle: accounts !== null ? \Accounts ${accounts.join(', ')}` : 'All accounts'`

State

  • Update _ctx to store accounts instead of account

Report subtitle

  • Use accounts array for display

CSV download

  • Filename: use joined accounts or "all"

Transaction table

  • When multiple accounts selected: show account column (accounts === null || accounts.length > 1)

Empty state message

  • Update "Account N — no data" to use accounts display string

Verification

  • Commit after each task completes and passes review
  • SQL output in browser console should show correct IN clause
  • All accounts works when input is blank