# 機能設計書 49-通貨・為替管理

## 概要

本ドキュメントは、InvenTreeシステムにおける通貨・為替管理機能の設計仕様を定義する。この機能は、複数通貨のサポートと為替レートの管理を行い、国際的な調達・販売業務を支援する。

### 本機能の処理概要

**業務上の目的・背景**：
グローバルなサプライチェーンを持つ企業では、複数の通貨で取引を行う必要がある。本機能は、システム内で複数の通貨をサポートし、為替レートの自動更新を通じて、異なる通貨間での価格比較やコスト計算を可能にする。これにより、国際的な調達・販売業務における価格管理が効率化される。

**機能の利用シーン**：
- デフォルト通貨を設定する
- 為替レートを更新する
- サプライヤー価格を異なる通貨で登録する
- 発注・受注で通貨を選択する

**主要な処理内容**：
1. 利用可能通貨の一覧取得
2. デフォルト通貨の設定
3. 為替レートの自動更新（プラグイン経由）
4. 通貨間の金額変換

**関連システム・外部連携**：
- djmoney（Django Money）ライブラリ
- 為替レート更新プラグイン
- 外部為替レートAPI

**権限による制御**：
- 通貨設定の変更はスタッフ権限が必要
- 為替レートの閲覧は認証済みユーザーで可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 34 | 管理センター画面 | 主機能 | 通貨管理パネル |

## 機能種別

設定管理 / データ連携

## 入力仕様

### 入力パラメータ（設定）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| INVENTREE_DEFAULT_CURRENCY | string | Yes | デフォルト通貨コード | 有効な通貨コード |
| CURRENCY_UPDATE_PLUGIN | string | No | 為替レート更新プラグイン | 有効なプラグインスラッグ |
| CURRENCY_UPDATE_INTERVAL | integer | No | 更新間隔（日） | 0以上 |

### 入力データソース

- 管理画面の通貨設定パネル
- APIリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| base_currency | string | 基準通貨コード |
| updated | datetime | 最終更新日時 |
| exchange_rates | object | 通貨コードをキーとした為替レートマップ |

### 出力先

- 管理画面の通貨一覧テーブル
- APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス（為替レート更新）

```
1. 為替レート更新リクエスト
   └─ POST /api/currency/refresh/
2. プラグインの取得
   └─ CURRENCY_UPDATE_PLUGIN設定から
3. 外部APIからレート取得
   └─ プラグインが外部サービスを呼び出し
4. レートの保存
   └─ djmoneyの為替レートテーブルに保存
5. 更新日時の記録
```

### フローチャート

```mermaid
flowchart TD
    A[為替レート更新リクエスト] --> B[プラグイン取得]
    B --> C{プラグイン有効?}
    C -->|No| D[エラーレスポンス]
    C -->|Yes| E[外部APIコール]
    E --> F{取得成功?}
    F -->|No| G[エラーレスポンス]
    F -->|Yes| H[レート保存]
    H --> I[更新日時記録]
    I --> J[成功レスポンス]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-49-01 | 基準通貨 | 為替レートは基準通貨に対する相対値として保存 | 全てのレート |
| BR-49-02 | 自動更新 | CURRENCY_UPDATE_INTERVALに基づいて定期更新 | 設定有効時 |
| BR-49-03 | レート欠損時 | レートが見つからない場合はエラーまたはフォールバック | 通貨変換時 |
| BR-49-04 | デフォルト通貨必須 | デフォルト通貨は必ず設定が必要 | システム動作時 |

### 計算ロジック

通貨変換：
```python
from djmoney.contrib.exchange.models import convert_money
converted = convert_money(amount, target_currency)
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 通貨設定取得 | common_inventreesetting | SELECT | 通貨関連設定の取得 |
| 通貨設定更新 | common_inventreesetting | UPDATE | 通貨関連設定の更新 |
| 為替レート取得 | exchange_rate | SELECT | 為替レート一覧取得 |
| 為替レート更新 | exchange_rate | INSERT/UPDATE | 為替レートの保存 |

### テーブル別操作詳細

#### exchange_rate（djmoney管理）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT/UPDATE | source | 基準通貨 | |
| SELECT/UPDATE | currency | 対象通貨コード | |
| SELECT/UPDATE | rate | 為替レート | Decimal |
| SELECT/UPDATE | last_update | 更新日時 | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | ValidationError | 無効な通貨コード | 有効な通貨コードを使用 |
| 400 | MissingRate | 為替レートが見つからない | 為替レートを更新 |
| 500 | ExternalAPIError | 外部API呼び出し失敗 | 後で再試行 |

### リトライ仕様

為替レート更新失敗時は、次回の定期実行時に再試行。

## トランザクション仕様

為替レートの更新は単一トランザクションで実行。

## パフォーマンス要件

- 通貨一覧取得：100ms以内
- 為替レート更新：外部API依存

## セキュリティ考慮事項

- 通貨設定の変更はスタッフ権限が必要
- 外部API呼び出しはSSL/TLSを使用

## 備考

- djmoney（django-money）ライブラリを使用
- 為替レート更新はCURRENCY_UPDATE_PLUGINで指定したプラグインが実行

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: フロントエンドの通貨管理画面を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CurrencyManagementPanel.tsx | `src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagementPanel.tsx` | 通貨管理パネル（1-115行目） |

**読解のコツ**:
- `CurrencyTable`で為替レート一覧を表示
- `refreshCurrencies()`で為替レート更新API呼び出し
- `GlobalSettingList`で関連設定を表示

#### Step 2: バックエンドAPIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.py | `src/backend/InvenTree/common/api.py` | CurrencyExchangeList, CurrencyRefreshView |

**主要処理フロー**:
- `CurrencyExchangeList.get()`: 為替レート一覧取得
- `CurrencyRefreshView.post()`: 為替レート更新トリガー

#### Step 3: 為替レート更新プラグインを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tasks.py | `src/backend/InvenTree/common/tasks.py` | update_exchange_rates タスク |

### プログラム呼び出し階層図

```
CurrencyManagementPanel
    │
    ├─ CurrencyTable
    │      │
    │      └─ GET /api/currency/exchange/
    │             │
    │             └─ CurrencyExchangeList.get()
    │                    └─ ExchangeBackend.get_rates()
    │
    ├─ refreshCurrencies()
    │      │
    │      └─ POST /api/currency/refresh/
    │             │
    │             └─ CurrencyRefreshView.post()
    │                    │
    │                    └─ update_exchange_rates()
    │                           │
    │                           └─ プラグイン.get_exchange_rates()
    │
    └─ GlobalSettingList
           └─ INVENTREE_DEFAULT_CURRENCY
           └─ CURRENCY_UPDATE_PLUGIN
           └─ CURRENCY_UPDATE_INTERVAL
```

### データフロー図

```
[フロントエンド]         [バックエンド]              [外部API]

CurrencyTable      ───▶ GET /api/currency/     ───▶ exchange_rate
                        /exchange/                   テーブル
                              │
                              ▼
                   base_currency, updated,
                   exchange_rates

refreshCurrencies  ───▶ POST /api/currency/   ───▶ 外部為替API
                        /refresh/                   (プラグイン経由)
                              │
                              ▼
                   update_exchange_rates()
                              │
                              ▼
                   exchange_rate テーブル更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CurrencyManagementPanel.tsx | `src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagementPanel.tsx` | ソース | 通貨管理パネル |
| api.py | `src/backend/InvenTree/common/api.py` | ソース | 通貨API |
| tasks.py | `src/backend/InvenTree/common/tasks.py` | ソース | 為替レート更新タスク |
| settings.py | `src/backend/InvenTree/common/settings.py` | ソース | 通貨関連設定 |
