# CreateExchangeRate

## Permission Scope

currency

## Overview

CreateExchangeRate establishes a new conversion ratio between a currency pair with a specific effective date. The rate specifies how many units of the target currency equal one unit of the source currency. Rates are date-based to support historical accuracy - transactions use the rate effective on their transaction date.

This command supports daily rate updates, period-end rate recording, and forward rate entry for future-dated transactions.

## Business Rules

- Source and target currencies must both exist and be active
- Source and target currencies must be different (no self-conversion rates)
- Rate value must be a positive decimal number (greater than zero)
- Effective date is required and determines when the rate becomes applicable
- Future effective dates are allowed (forward rates)
- Multiple rates for the same currency pair with different effective dates are allowed
- When a rate for the same currency pair and effective date already exists, the new rate supersedes (append-only semantics)
- Rate lookup uses the most recent rate with effectiveDate <= transaction date

## Process Flow

```mermaid
flowchart TD
    A[Receive create rate request] --> B{Source currency exists and active?}
    B -->|No| C[Return error: invalid source currency]
    B -->|Yes| D{Target currency exists and active?}
    D -->|No| E[Return error: invalid target currency]
    D -->|Yes| F{Source != Target?}
    F -->|No| G[Return error: same currency pair]
    F -->|Yes| H{Rate value > 0?}
    H -->|No| I[Return error: invalid rate value]
    H -->|Yes| J{Effective date provided?}
    J -->|No| K[Return error: missing effective date]
    J -->|Yes| L[Create exchange rate record]
    L --> M[Return created rate]
```

## External Dependencies

- None

## Error Scenarios

- **CURRENCY_NOT_FOUND**: Referenced currency does not exist
- **INACTIVE_CURRENCY**: Referenced source or target currency is inactive
- **SAME_CURRENCY_PAIR**: Source and target currencies are the same
- **INVALID_EXCHANGE_RATE**: Rate is zero, negative, or not a valid number

## Test Cases

- throws when source currency doesn't exist
- throws when source currency is inactive
- throws when target currency doesn't exist
- throws when target currency is inactive
- throws when source and target are the same
- throws when rate is not positive
- creates exchange rate successfully
- passes custom fields through to insert
