# Branch Cash-Out Feature: Product + Implementation Plan

## 1) Business Intent and User Journeys

This feature has two valid request origins that converge into one operational fulfillment flow.

1. Branch-initiated request (walk-in assisted)
- Customer walks into branch and asks for cash-out.
- Branch operator verifies customer identity and wallet balance.
- Branch operator creates a cash-out request on behalf of the customer.
- Authorized branch manager/supervisor approves.
- Branch disburses cash and marks request as disbursed.

2. Customer-initiated request (self-service)
- Customer logs in and submits a cash-out request.
- Request appears in customer history as `pending`.
- Customer walks into branch.
- Branch operator searches/sees request, validates status and identity, then approves/disburses.

## 2) Current State in Codebase (As-Is)

Implemented already:
- Domain entity and lifecycle in `WalletTransfers.CashOutRequest`.
- Commands:
  - `RequestCashOut.execute/4`
  - `AuthorizeCashOut.execute/3`
  - `DisburseCashOut.execute/3`
- ETS + write-through persistence in `CashOutRequestStore` and `wallet_cash_out_requests` table.
- Admin LiveView (`/admin/cash-out`) for authorize/disburse.
- Role permissions for `:view_cash_out_requests`, `:authorize_cash_out`, `:disburse_cash_out`.
- Unit tests for cash-out domain and commands.

Gaps:
- No customer-facing page to submit and track branch cash-out requests.
- Admin side lacks explicit branch-assisted request creation form.
- Pending tab behavior in admin page should enforce pending-only list.
- Branch-side customer lookup and balance validation is not yet explicit in UI flow.

## 3) Target Scope

### Phase A (Now - initiate implementation)
- Add customer cash-out page in portal:
  - submit request (`amount`, `currency`, optional `branch_id`)
  - list own requests with status timeline fields.
- Add route + sidebar navigation entry.
- Enhance admin cash-out page:
  - add branch-assisted request creation form (same command path)
  - ensure `/admin/cash-out/pending` always shows only pending requests.

### Phase B (Next)
- Add branch operator search by user ID / phone / customer identifier.
- Add balance visibility check in UI before creating request.
- Add duplicate/risk controls (cooldown, daily cap pre-check).
- Add cancellation by customer while status is `pending`.

### Phase C (Hardening)
- Add audit timeline UI and SLA aging indicators.
- Add reconciliation report: authorized vs disbursed vs failed/cancelled.
- Add idempotency keys for create/authorize/disburse API entrypoints.

## 4) Rules and State Model

Statuses:
- `pending` -> `authorized` -> `disbursed`
- `pending|authorized` -> `failed`
- `pending` -> `cancelled`

Operational rules:
- Only authorized branch roles can approve.
- Only disbursement-capable roles can disburse.
- Disburse allowed only from `authorized`.
- Customer can only view own requests.
- Admin can view/filter all requests.

## 5) Data and Integration Notes

Existing table `wallet_cash_out_requests` already supports:
- `cash_out_id`, `user_id`, `amount`, `currency`, `status`, `branch_id`
- authorization/disbursement actor and timestamps
- correlation and receipt fields

Known gap to enforce later:
- explicit available-balance check in branch-assisted UI before request creation.

## 6) API / UI Contract (Internal)

Customer UI action:
- `RequestCashOut.execute(user_id, amount_minor, currency, branch_id: branch_id)`

Admin UI actions:
- create: `RequestCashOut.execute(user_id, amount_minor, currency, branch_id: branch_id)`
- authorize: `AuthorizeCashOut.execute(cash_out_id, agent_id)`
- disburse: `DisburseCashOut.execute(cash_out_id, agent_id, receipt_ref: receipt_ref)`

## 7) Test Plan

1. Domain/command tests
- request valid/invalid amount/currency
- authorize/disburse transition guards

2. LiveView behavior tests
- customer create success/failure and own-list rendering
- admin create + pending tab strict filtering

3. Security tests
- unauthorized role cannot access relevant screens/actions

## 8) Delivery Plan

1. Create customer cash-out LiveView and wire route/nav.
2. Update admin cash-out LiveView for branch-assisted request creation and pending-tab behavior.
3. Run compile and targeted tests for touched modules.
4. Open follow-up ticket for branch balance check and customer lookup enrichment.

## 9) Risks and Mitigations

- Risk: branch creates request without balance check.
  - Mitigation: add pre-check adapter in Phase B before create.
- Risk: duplicate submissions from UI retries.
  - Mitigation: add idempotency key + button disable after submit.
- Risk: stale list when multiple operators act concurrently.
  - Mitigation: subscribe to PubSub updates and refresh rows incrementally.
