# WalletJourney

End-to-end transfer journey orchestration for the MomentPay wallet platform.

## Responsibilities

Coordinates the full lifecycle of a transfer across dependent bounded contexts:
limits checking, fee calculation, transfer initiation, fund reservation, and
transfer completion. Emits domain events and structured audit events at each
lifecycle transition. Supports compensation (transfer cancellation) when a
failure occurs after the transfer has been initiated.

## Architecture

`WalletJourney` is a plain OTP application with no database dependency. Journey
state is held in an ETS-backed GenServer (`JourneyStore`) for Phase 1-3 CI. The
coordinator is a plain module (not a GenServer); it runs synchronously and
returns `{:ok, journey}` or `{:error, reason, journey}`.

## Journey Steps (in order)

| Step | Description |
|---|---|
| `:limits_check` | Verify transfer amount is within configured limits |
| `:fee_calculation` | Compute applicable fees for the tier/currency/type |
| `:initiate_transfer` | Create the transfer record via `wallet_transfers` |
| `:reserve_funds` | Reserve funds on the initiated transfer |
| `:complete_transfer` | Complete the reserved transfer |

## Journey Statuses

| Status | Description |
|---|---|
| `:started` | Journey created, first step not yet run |
| `:in_progress` | A step is currently executing |
| `:completed` | All steps completed successfully |
| `:failed` | A step failed before transfer was initiated |
| `:compensating` | Compensation in progress (transfer cancel in flight) |
| `:compensated` | Transfer was cancelled; journey rolled back |

## Commands

| Command | Function |
|---|---|
| `WalletJourney.start_journey/1` | Execute a full transfer journey |
| `WalletJourney.advance_step/3` | Record a step as completed (manual/external) |
| `WalletJourney.compensate/2` | Compensate a journey (cancel its transfer) |

## Queries

| Query | Function |
|---|---|
| `WalletJourney.get_journey/1` | Retrieve journey state by journey_id |

## Events

All events are broadcast to the `"wallet_journey:events"` Phoenix.PubSub topic
as `{:domain_event, event_map}` tuples.

| Event | Description |
|---|---|
| `JourneyStarted.v1` | Journey created and first step queued |
| `JourneyStepAdvanced.v1` | A step completed and the next step entered |
| `JourneyCompleted.v1` | All steps completed; transfer is done |
| `JourneyCompensated.v1` | Journey compensated; transfer was cancelled |

## Boundary Constraints

- No direct ledger writes; that is the responsibility of `wallet_ledger`.
- No auth logic; that is the responsibility of `wallet_auth`.
- No circular dependencies on `wallet_ledger` or `wallet_accounts`.
- Transfer state transitions are always delegated to `wallet_transfers`.
- Limits and fee logic are always delegated to `wallet_limits_fees`.

## Dependency Injection (Testing)

The coordinator resolves `WalletTransfers` and `WalletLimitsFees` at runtime via
`Application.get_env`, allowing test-time overrides without recompilation:

```elixir
# test/test_helper.exs
Application.put_env(:wallet_journey, :transfers_module, WalletJourney.StubTransfers)
Application.put_env(:wallet_journey, :limits_fees_module, WalletJourney.StubLimitsFees)
```

## Usage Example

```elixir
{:ok, journey} = WalletJourney.start_journey(%{
  user_id: "usr_abc123",
  from_account_id: "acc_sender",
  to_account_id: "acc_receiver",
  amount: 5000,
  currency: "USD",
  tier: :standard,
  transfer_type: :internal
})

journey.status         # => :completed
journey.transfer_id    # => "trf_..."
journey.completed_steps # => [:limits_check, :fee_calculation, :initiate_transfer, :reserve_funds, :complete_transfer]
```
