- VoucherService: central voucher register with globally unique voucher numbers - CashierDepositRequestApiResource: full submit/approve/reject/list flow - Cashier submits deposit request; balance credited only on manager approval - Self-approval blocked (maker cannot be checker) - Role guard: only manager/head-cashier/ALL_FUNCTIONS can approve/reject - Race condition guard: WHERE status='PENDING' on approve/reject UPDATE - Clean JSON error responses (no 500 stack traces) via apiError() helper - Denomination total validation at submit and approve - ClerkWithdrawalRequestApiResource: refactored to use m_voucher - Voucher created at submit, linked to savings txn at approve - Same role guard and self-approval block as deposit flow - Disburse: denomination validation, null denoms for non-cash payments - Migrations 0327-0330: - 0327: add voucher_no to m_clerk_withdrawal_request - 0328: add voucher_no to m_savings_account_transaction - 0329: create m_voucher central table (globally unique voucher_no) - 0330: create m_cashier_deposit_request table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>