# 機能設計書 9-取引追加・編集・削除

## 概要

本ドキュメントは、Actual Budget における収入・支出取引の追加、編集、削除機能の設計を記述する。予算管理の中核をなす取引データの CRUD 操作を提供する。

### 本機能の処理概要

**業務上の目的・背景**：予算管理の基礎は、すべての収入と支出を正確に記録することである。本機能は、取引の入力から編集、削除までの一連の操作を提供し、ユーザーが財務活動を追跡できるようにする。手動入力に加え、銀行連携やインポートからの取引も統一的に管理される。

**機能の利用シーン**：
- 日常の支出を手動で入力する
- 銀行連携で取り込まれた取引のカテゴリを編集する
- 誤って入力した取引を修正する
- 重複した取引を削除する
- 複数の取引を一括で編集・削除する

**主要な処理内容**：
1. 新規取引の追加（日付、金額、支払先、カテゴリ、メモ等）
2. 取引の編集（各フィールドの更新）
3. 取引の削除（論理削除）
4. バッチ操作（一括編集、一括削除、一括複製）
5. 取引の照合（Reconcile）

**関連システム・外部連携**：口座管理、カテゴリ管理、支払先管理、ルール機能

**権限による制御**：特別な権限制御なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | 口座一覧画面（デスクトップ） | 主画面 | 取引の追加・編集・削除処理 |
| 14 | 口座詳細画面（モバイル） | 主画面 | モバイルでの取引表示・操作 |
| 15 | 取引編集画面（モバイル） | 主画面 | モバイルでの取引詳細編集 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### 取引追加

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| accountId | string | Yes | 口座ID | 存在する口座ID |
| transactions | array | Yes | 取引データの配列 | 有効な取引オブジェクト |
| learnCategories | boolean | No | カテゴリ学習を有効にするか | デフォルト: false |
| runTransfers | boolean | No | 振替処理を実行するか | デフォルト: false |

#### 取引オブジェクト

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| date | string | Yes | 取引日 | YYYY-MM-DD形式 |
| amount | number | Yes | 金額（セント単位） | 整数 |
| payee | string | No | 支払先ID | 存在する支払先ID |
| payee_name | string | No | 支払先名（新規作成時） | |
| category | string | No | カテゴリID | 存在するカテゴリID |
| notes | string | No | メモ | |
| cleared | boolean | No | 確定済みフラグ | |

#### 取引更新

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 取引ID | 存在する取引ID |
| fields | object | Yes | 更新するフィールド | 有効なフィールド名 |

#### 取引削除

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 取引ID | 存在する取引ID |

### 入力データソース

- 画面入力：取引入力フォーム、インライン編集
- API経由：外部システム、インポート機能

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ids | string[] | 追加された取引のID一覧 |
| updated | object[] | 更新された取引 |

### 出力先

- データベース：transactions テーブル
- 画面表示：取引一覧

## 処理フロー

### 処理シーケンス

```
【取引追加】
1. 取引追加ボタンをクリックまたは空の行で入力開始
   └─ isAdding 状態を true に設定

2. 取引情報を入力
   └─ 日付、金額、支払先、カテゴリ等

3. Enter または Tab で確定
   └─ api/transactions-add を呼び出し

4. サーバーで処理
   └─ 取引レコードを作成
   └─ learnCategories が true なら支払先とカテゴリの関連を学習
   └─ runTransfers が true なら振替取引を処理

5. UIを更新
   └─ 取引一覧に新しい取引が表示

【取引編集】
1. 取引行をクリックして編集モード
   └─ インライン編集が有効化

2. フィールドを編集
   └─ 変更を検出

3. 確定時に api/transaction-update
   └─ 変更されたフィールドのみ更新

【取引削除】
1. 取引を選択して削除
   └─ 複数選択可能

2. api/transaction-delete
   └─ tombstone = 1 で論理削除
```

### フローチャート

```mermaid
flowchart TD
    A[取引操作] --> B{操作種別?}
    B -->|追加| C[入力フォーム表示]
    B -->|編集| D[インライン編集]
    B -->|削除| E[削除確認]
    C --> F[取引データ入力]
    F --> G[api/transactions-add]
    G --> H{learnCategories?}
    H -->|Yes| I[カテゴリ学習]
    H -->|No| J[取引作成完了]
    I --> J
    D --> K[フィールド変更]
    K --> L[api/transaction-update]
    L --> J
    E --> M{確認?}
    M -->|Yes| N[api/transaction-delete]
    M -->|No| J
    N --> O[tombstone = 1]
    O --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 必須フィールド | 日付、金額は必須 | 取引追加時 |
| BR-002 | 金額の符号 | 支出は負、収入は正 | 常時 |
| BR-003 | 論理削除 | 削除は tombstone フラグで論理削除 | 削除時 |
| BR-004 | 分割取引 | 1つの取引を複数のカテゴリに分割可能 | 分割取引作成時 |
| BR-005 | 照合済み警告 | 照合済み取引の編集時は警告 | reconciled = true の取引編集時 |

### 計算ロジック

```
// 取引金額の計算
// 支出: amount < 0
// 収入: amount > 0

// 分割取引
parentTransaction.amount = SUM(childTransactions.amount)

// 口座残高への影響
accountBalance += transaction.amount
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 追加 | transactions | INSERT | 新規取引レコード |
| 更新 | transactions | UPDATE | 取引フィールド更新 |
| 削除 | transactions | UPDATE | tombstone = 1 |

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

#### transactions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | UUID | 主キー |
| INSERT | account | 口座ID | |
| INSERT | date | 取引日 | YYYY-MM-DD |
| INSERT | amount | 金額 | 整数（セント単位） |
| INSERT | payee | 支払先ID | |
| INSERT | category | カテゴリID | |
| INSERT | notes | メモ | |
| INSERT | cleared | 0/1 | 確定フラグ |
| INSERT | reconciled | 0/1 | 照合フラグ |
| UPDATE | tombstone | 1 | 論理削除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| INVALID_DATE | バリデーション | 無効な日付形式 | 正しい形式で入力 |
| ACCOUNT_NOT_FOUND | データ不整合 | 存在しない口座ID | エラー通知を表示 |
| TRANSACTION_NOT_FOUND | データ不整合 | 存在しない取引ID | エラー通知を表示 |

### リトライ仕様

- 同期エラー時は自動リトライ

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

- 複数取引の一括操作はバッチ処理

## パフォーマンス要件

- 取引追加/編集は即座に反映（100ms以内）
- バッチ操作は取引数に応じて処理時間が増加

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

- 取引データはローカル保存
- クラウド同期時はE2E暗号化オプションあり

## 備考

- Undo/Redo 機能でトランザクションの取り消しが可能

---

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

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

### 推奨読解順序

#### Step 1: API層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | methods.ts | `packages/api/methods.ts` | addTransactions, updateTransaction, deleteTransaction 関数 |

**主要処理フロー**:
- **112-126行目**: `addTransactions` 関数（accountId, transactions, learnCategories, runTransfers）
- **157-162行目**: `updateTransaction` 関数
- **164-166行目**: `deleteTransaction` 関数

#### Step 2: 口座画面の取引管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Account.tsx | `packages/desktop-client/src/components/accounts/Account.tsx` | 取引一覧と操作 |

**主要処理フロー**:
- **747-749行目**: `onAddTransaction` で追加モード開始
- **635-648行目**: `onTransactionsChange` で変更を処理
- **1086-1106行目**: `onBatchEdit`, `onBatchDuplicate`, `onBatchDelete`

#### Step 3: バッチ操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | useTransactionBatchActions.ts | `packages/desktop-client/src/hooks/useTransactionBatchActions.ts` | バッチ操作フック |

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

```
Account.tsx
    │
    ├─ TransactionList
    │      │
    │      ├─ 取引追加
    │      │      └─ api/transactions-add
    │      │             └─ transactions INSERT
    │      │
    │      ├─ 取引編集
    │      │      └─ api/transaction-update
    │      │             └─ transactions UPDATE
    │      │
    │      └─ 取引削除
    │             └─ api/transaction-delete
    │                    └─ transactions UPDATE (tombstone = 1)
    │
    └─ バッチ操作
           │
           ├─ onBatchEdit → useTransactionBatchActions
           ├─ onBatchDuplicate
           └─ onBatchDelete
                  │
                  └─ transactions-batch-update
```

### データフロー図

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

取引データ入力     ───▶  api/transactions-add
(日付、金額等)                 │
                              ▼
                         transactions INSERT      ───▶  取引レコード
                              │
                              ▼
                         learnCategories?        ───▶  支払先-カテゴリ学習
                              │
                              ▼
                         UI更新                  ───▶  取引一覧表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| methods.ts | `packages/api/methods.ts` | ソース | 取引API関数定義 |
| Account.tsx | `packages/desktop-client/src/components/accounts/Account.tsx` | ソース | 口座画面（取引一覧） |
| TransactionList.tsx | `packages/desktop-client/src/components/transactions/TransactionList.tsx` | ソース | 取引一覧コンポーネント |
| useTransactionBatchActions.ts | `packages/desktop-client/src/hooks/useTransactionBatchActions.ts` | ソース | バッチ操作フック |
| transactions.ts | `packages/loot-core/shared/transactions.ts` | ソース | 取引ユーティリティ |
| AccountTransactions.tsx | `packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx` | ソース | モバイル取引一覧 |
