# 機能設計書 11-取引エクスポート

## 概要

本ドキュメントは、Actualアプリケーションにおける取引データのエクスポート機能について、その処理内容、入出力仕様、および実装詳細を記述した機能設計書である。

### 本機能の処理概要

取引エクスポート機能は、ユーザーが管理している取引データをCSV形式でエクスポートし、外部アプリケーションやスプレッドシートソフトウェアで利用可能にする機能である。

**業務上の目的・背景**：家計簿データの分析やバックアップ、他の会計ソフトウェアへのデータ移行、税務申告用の記録作成など、様々なシーンでActualの取引データを外部に出力するニーズがある。本機能により、ユーザーは自身の財務データを自由に活用できる。

**機能の利用シーン**：
- 月次・年次の支出分析をExcelで行いたい場合
- 会計士や税理士へデータを提供する必要がある場合
- データのバックアップとして外部保存したい場合
- 他の予算管理アプリへの移行を検討している場合

**主要な処理内容**：
1. エクスポート対象の取引データを取得（日付、口座、支払先、カテゴリ、金額、メモ等）
2. 口座名、カテゴリ名、支払先名をIDから名称に変換
3. 金額を内部の整数表現から通貨形式に変換
4. CSV形式でデータを構築
5. ユーザーにファイルダウンロードダイアログを表示

**関連システム・外部連携**：エクスポートされたCSVファイルはMicrosoft Excel、Google Sheets、Numbers等の表計算ソフトウェアで開くことができる。

**権限による制御**：本機能は予算ファイルを開いているユーザーであれば誰でも利用可能である。特別な権限制御は実装されていない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | 口座一覧画面（デスクトップ） | 補助機能 | 取引データのCSVエクスポート処理 |
| 40 | 設定画面 | 補助機能 | 予算データのエクスポート処理 |

## 機能種別

データ連携 / 帳票出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| transactions | TransactionEntity[] | Yes | エクスポート対象の取引一覧 | 空配列可 |
| accounts | AccountEntity[] | Yes | 口座一覧（名称変換用） | - |
| categoryGroups | CategoryGroupEntity[] | Yes | カテゴリグループ一覧（名称変換用） | - |
| payees | PayeeEntity[] | Yes | 支払先一覧（名称変換用） | - |
| query | QueryState | No | AQLクエリ（クエリベースエクスポート時） | 有効なAQL構文 |

### 入力データソース

- データベース（SQLite）からの取引データ取得
- 画面で選択された取引の絞り込み条件

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Account | string | 口座名 |
| Date | string | 取引日（YYYY-MM-DD形式） |
| Payee | string | 支払先名 |
| Notes | string | メモ・ノート |
| Category | string | カテゴリ名（「グループ名: カテゴリ名」形式） |
| Amount | number | 金額（通貨形式） |
| Cleared | string | 消込状態（Cleared/Not cleared/Reconciled） |
| Split_Amount | number | 分割取引の場合の元金額（クエリベースエクスポート時のみ） |

### 出力先

- ユーザーのローカルファイルシステム（CSVファイルとしてダウンロード）

## 処理フロー

### 処理シーケンス

```
1. エクスポート要求受信
   └─ ユーザーがエクスポートボタンをクリック

2. 取引データ収集
   └─ 対象となる取引データをデータベースから取得

3. マスターデータ取得
   └─ 口座、カテゴリグループ、支払先のマスターデータを取得

4. データ変換処理
   └─ IDから名称への変換、金額フォーマット変換を実行

5. CSV生成
   └─ csv-stringifyライブラリを使用してCSV形式に変換

6. ファイル保存ダイアログ表示
   └─ Electronのファイル保存APIを呼び出し

7. ファイル書き込み
   └─ ユーザーが指定した場所にCSVファイルを保存
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[エクスポートボタンクリック]
    B --> C[取引データ取得]
    C --> D{クエリベース?}
    D -->|Yes| E[AQLクエリ実行]
    D -->|No| F[渡された取引データ使用]
    E --> G[マスターデータ取得]
    F --> G
    G --> H[ID→名称変換]
    H --> I[金額フォーマット変換]
    I --> J[CSV文字列生成]
    J --> K[ファイル保存ダイアログ表示]
    K --> L{保存先選択?}
    L -->|Yes| M[CSVファイル保存]
    L -->|No| N[キャンセル]
    M --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | カテゴリ名フォーマット | カテゴリ名は「グループ名: カテゴリ名」形式で出力 | 全取引 |
| BR-02 | 金額変換 | 内部整数表現（セント）から通貨形式（ドル）に変換 | 全取引 |
| BR-03 | 分割取引表記 | 分割取引は「(SPLIT INTO n)」または「(SPLIT x OF n)」形式でNotesに追記 | 分割取引の場合 |
| BR-04 | 消込状態表記 | cleared=trueは"Cleared"、reconciled=trueは"Reconciled"、それ以外は"Not cleared" | クエリベースエクスポート時 |

### 計算ロジック

**金額変換**:
```typescript
// 整数（セント）から小数（ドル）への変換
Amount = integerToAmount(amount) // amount / 100
```

**分割取引のノート生成**:
```typescript
// 親取引の場合
Notes = `(SPLIT INTO ${childCount}) ${originalNotes}`

// 子取引の場合
Notes = `(SPLIT ${childIndex} OF ${totalChildren}) ${originalNotes}`
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 取引取得 | transactions | SELECT | エクスポート対象取引の取得 |
| 口座取得 | accounts | SELECT | 口座名変換用データ取得 |
| カテゴリ取得 | categories, category_groups | SELECT | カテゴリ名変換用データ取得 |
| 支払先取得 | payees | SELECT | 支払先名変換用データ取得 |

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

#### transactions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, account, date, payee, notes, category, amount, cleared, reconciled | クエリ条件による | AQLで取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル書き込みエラー | 保存先への書き込み権限がない場合 | エラーメッセージを表示 |
| - | データ取得エラー | データベース接続エラー | エラーメッセージを表示 |

### リトライ仕様

特になし（ユーザーが再度エクスポートを実行する）

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

エクスポート処理はデータの読み取りのみであり、トランザクション管理は不要。

## パフォーマンス要件

- 大量の取引データ（数万件）でも数秒以内にエクスポート完了すること
- メモリ使用量が過大にならないよう、ストリーミング処理を検討

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

- エクスポートされたCSVファイルには財務情報が含まれるため、ユーザーは適切に管理する必要がある
- E2E暗号化が有効な場合でも、エクスポートされるCSVは暗号化されない（設定画面に警告表示）

## 備考

- クエリベースエクスポート（exportQueryToCSV）は分割取引の詳細情報を含む拡張形式
- 通常エクスポート（exportToCSV）はシンプルな形式

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、エクスポート対象となる取引データの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | transaction.ts | `packages/loot-core/src/types/models/transaction.ts` | TransactionEntityの全フィールドを確認 |
| 1-2 | category.ts | `packages/loot-core/src/types/models/category.ts` | CategoryEntityのフィールド構成を確認 |
| 1-3 | payee.ts | `packages/loot-core/src/types/models/payee.ts` | PayeeEntityのフィールド構成を確認 |

**読解のコツ**: TypeScriptの型定義ファイルなので、各フィールドの型と用途を把握する。特に`is_parent`、`is_child`、`parent_id`は分割取引に関連する重要なフィールド。

#### Step 2: エントリーポイントを理解する

処理の起点となるUI コンポーネントを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Export.tsx | `packages/desktop-client/src/components/settings/Export.tsx` | エクスポートボタンのUIと処理開始ロジック |

**主要処理フロー**:
1. **16-44行目**: ExportBudget関数コンポーネント全体
2. **23-44行目**: onExport関数 - エクスポート処理の開始
3. **27行目**: send('export-budget')でサーバーサイド処理を呼び出し
4. **36-42行目**: 成功時のファイル保存処理

#### Step 3: サーバーサイドエクスポート処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | app.ts | `packages/loot-core/src/server/transactions/app.ts` | エクスポートハンドラの登録とルーティング |
| 3-2 | export-to-csv.ts | `packages/loot-core/src/server/transactions/export/export-to-csv.ts` | CSV変換の実装詳細 |

**主要処理フロー**:
- **app.ts 75-86行目**: exportTransactions関数の定義
- **app.ts 89-95行目**: exportTransactionsQuery関数の定義
- **export-to-csv.ts 7-57行目**: exportToCSV関数 - 基本的なCSVエクスポート
- **export-to-csv.ts 59-130行目**: exportQueryToCSV関数 - クエリベースの高度なエクスポート

#### Step 4: 金額変換ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | util.ts | `packages/loot-core/src/shared/util.ts` | integerToAmount関数の実装 |

**主要処理フロー**:
- integerToAmount: 整数（セント）から小数（ドル）への変換

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

```
Export.tsx (UI)
    │
    ├─ send('export-budget')
    │      │
    │      └─ app.ts: exportTransactions
    │             │
    │             └─ export-to-csv.ts: exportToCSV
    │                    │
    │                    ├─ accountNamesById (口座名マッピング)
    │                    ├─ categoryNamesById (カテゴリ名マッピング)
    │                    ├─ payeeNamesById (支払先名マッピング)
    │                    └─ csvStringify (CSV生成)
    │
    └─ window.Actual.saveFile (ファイル保存)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

transactions ─────┐
                  │
accounts ─────────┼──▶ exportToCSV ──▶ csvStringify ──▶ CSVファイル
                  │         │
categoryGroups ───┤         ├─▶ ID→名称変換
                  │         ├─▶ 金額フォーマット変換
payees ───────────┘         └─▶ データ整形
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Export.tsx | `packages/desktop-client/src/components/settings/Export.tsx` | ソース | エクスポートUI |
| app.ts | `packages/loot-core/src/server/transactions/app.ts` | ソース | トランザクションAPIハンドラ |
| export-to-csv.ts | `packages/loot-core/src/server/transactions/export/export-to-csv.ts` | ソース | CSV変換ロジック |
| transaction.ts | `packages/loot-core/src/types/models/transaction.ts` | 型定義 | 取引データ型 |
| util.ts | `packages/loot-core/src/shared/util.ts` | ソース | 金額変換ユーティリティ |
