# 機能設計書 18-支払先（Payee）管理

## 概要

本ドキュメントは、Actualアプリケーションにおける支払先（Payee）管理機能について、その処理内容、入出力仕様、および実装詳細を記述した機能設計書である。

### 本機能の処理概要

支払先管理機能は、取引の相手先（店舗、サービス提供者、個人など）を管理する機能である。支払先の作成、編集、削除に加え、お気に入り設定やカテゴリ学習機能も提供する。

**業務上の目的・背景**：支払先を一元管理することで、同一の取引相手を容易に識別・選択できる。また、支払先ごとのカテゴリ学習により、同じ支払先への取引には自動的に同じカテゴリが提案される。これにより、取引入力の効率が大幅に向上する。

**機能の利用シーン**：
- 新しい支払先を登録したい場合
- 支払先名を変更したい場合（例：「Amazon.co.jp」→「Amazon」）
- 使用しなくなった支払先を削除したい場合
- よく使う支払先をお気に入りに登録したい場合
- 支払先のカテゴリ学習を有効/無効にしたい場合

**主要な処理内容**：
1. 支払先の新規作成
2. 支払先名の編集
3. 支払先の削除（取引がある場合も削除可能）
4. お気に入り設定（favorite）
5. カテゴリ学習設定（learn_categories）
6. 支払先のルール数取得
7. 孤立支払先（取引のない支払先）の検出

**関連システム・外部連携**：銀行連携機能で取得した取引の支払先名と、既存の支払先をマッチングする。

**権限による制御**：特別な権限制御はなく、予算ファイルを開いているユーザーであれば利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | 支払先管理画面（デスクトップ） | 主機能 | 支払先の一覧表示・作成・編集・削除 |
| 20 | 支払先管理画面（モバイル） | 主機能 | モバイルでの支払先一覧表示 |
| 21 | 支払先編集画面（モバイル） | 主機能 | モバイルでの支払先詳細編集 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### 支払先作成

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | 支払先名 | 空文字不可 |

#### 支払先更新

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 支払先ID | 存在する支払先ID |
| name | string | No | 支払先名 | - |
| favorite | boolean | No | お気に入りフラグ | - |
| learn_categories | boolean | No | カテゴリ学習フラグ | - |

#### 支払先削除

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 削除対象支払先ID | 存在する支払先ID、振替支払先は削除不可 |

### 入力データソース

- 画面入力（支払先管理画面）
- API（外部システムからの呼び出し）
- 取引入力時の新規支払先作成

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | 支払先ID（UUID） |
| name | string | 支払先名 |
| transfer_acct | string | 振替口座ID（振替支払先の場合） |
| favorite | boolean | お気に入りフラグ |
| learn_categories | boolean | カテゴリ学習フラグ |

### 出力先

- データベース（payeesテーブル、payee_mappingテーブル）

## 処理フロー

### 処理シーケンス

```
【支払先作成】
1. 支払先名入力
2. バリデーション
3. payeesテーブルにINSERT
4. payee_mappingテーブルにINSERT（自己参照）

【支払先削除】
1. 削除対象選択
2. 振替支払先チェック
3. 振替支払先でない場合のみ削除
4. payeesテーブルでtombstone=1に更新
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|作成| C[支払先名入力]
    B -->|更新| D[支払先選択]
    B -->|削除| E[削除対象選択]

    C --> F[バリデーション]
    F --> G[INSERT payees]
    G --> H[INSERT payee_mapping]

    D --> I[フィールド更新]
    I --> J[UPDATE payees]

    E --> K{振替支払先?}
    K -->|Yes| L[削除スキップ]
    K -->|No| M[DELETE (tombstone)]

    H --> Z[終了]
    J --> Z
    L --> Z
    M --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 必須フィールド | nameは必須 | 作成時 |
| BR-02 | 振替支払先削除禁止 | transfer_acctが設定されている支払先は削除不可 | 削除時 |
| BR-03 | お気に入り | favoriteフラグで優先表示 | 一覧表示時 |
| BR-04 | カテゴリ学習 | learn_categories=trueの場合、カテゴリを学習 | 取引作成時 |
| BR-05 | 支払先マッピング | payee_mappingでマージ後の支払先を追跡 | マージ時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 支払先作成 | payees | INSERT | 新規支払先を追加 |
| 支払先作成 | payee_mapping | INSERT | マッピングエントリを追加（自己参照） |
| 支払先更新 | payees | UPDATE | 支払先情報を更新 |
| 支払先削除 | payees | UPDATE(tombstone) | 支払先を論理削除 |

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

#### payees

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | 入力値 | - |
| UPDATE | name, favorite, learn_categories | 更新値 | - |
| UPDATE | tombstone | 1 | 削除時 |
| SELECT | * | transfer_acct IS NULL または accounts存在 | 振替支払先含む |

#### payee_mapping

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id, targetId | 新規ID, 同一ID | 自己参照 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 削除スキップ | 振替支払先を削除しようとした場合 | 処理をスキップ（エラーは発生しない） |

### リトライ仕様

特になし

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

- 支払先操作はundoable（元に戻す対応）
- batchMessagesでINSERTをバッチ処理

## パフォーマンス要件

- 支払先一覧の取得は高速であること
- 孤立支払先の検出はバックグラウンドで実行可能

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

- 特別なセキュリティ要件なし
- 支払先データは予算ファイル内でのみ有効

## 備考

- API経由での支払先操作: createPayee, updatePayee, deletePayee, getPayees
- 孤立支払先: 取引に使用されておらず、ルールにも関連付けられていない支払先

---

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

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

### 推奨読解順序

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

支払先の型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | payee.ts | `packages/loot-core/src/types/models/payee.ts` | PayeeEntityの型定義 |

**読解のコツ**:
- **3-10行目**: PayeeEntityの全フィールド
- `transfer_acct`: 振替口座への参照（振替支払先の場合のみ）
- `favorite`, `learn_categories`: 便利機能のフラグ

#### Step 2: モデルとバリデーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | models.ts | `packages/loot-core/src/server/models.ts` | payeeModelの実装 |

**主要処理フロー**:
1. **169-189行目**: payeeModelの定義
2. **170-173行目**: validate関数
3. **174-180行目**: toDb関数
4. **181-188行目**: fromDb関数

#### Step 3: 支払先APIハンドラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | app.ts | `packages/loot-core/src/server/payees/app.ts` | 支払先CRUD処理 |

**主要処理フロー**:
1. **42-44行目**: createPayee関数
2. **46-49行目**: getCommonPayees関数
3. **51-54行目**: getPayees関数
4. **73-81行目**: mergePayees関数
5. **83-109行目**: batchChangePayees関数

#### Step 4: データベース操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | db/index.ts | `packages/loot-core/src/server/db/index.ts` | 支払先DB操作 |

**主要処理フロー**:
- **561-571行目**: insertPayee関数
- **573-591行目**: deletePayee関数（振替支払先チェック含む）
- **598-601行目**: updatePayee関数
- **643-650行目**: getPayees関数（振替支払先名の取得含む）

#### Step 5: 支払先管理UIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ManagePayees.tsx | `packages/desktop-client/src/components/payees/ManagePayees.tsx` | 支払先管理UI |

**主要処理フロー**:
- **77-86行目**: コンポーネントのprops定義
- **117-133行目**: onUpdate関数
- **141-148行目**: onDelete関数
- **196-201行目**: onMerge関数

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

```
UI (ManagePayees.tsx)
    │
    ├─ send('payee-create')
    │      └─ app.ts: createPayee
    │             └─ db.insertPayee
    │                    ├─ INSERT payees
    │                    └─ INSERT payee_mapping
    │
    ├─ send('payees-batch-change')
    │      └─ app.ts: batchChangePayees
    │             ├─ db.deletePayee
    │             ├─ db.insertPayee
    │             └─ db.updatePayee
    │
    └─ send('payees-get')
           └─ app.ts: getPayees
                  └─ db.getPayees
```

### データフロー図

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

name ─────────┐
              │
              ├──▶ createPayee ──▶ payees テーブル
              │         │                │
              │         └──────────▶ payee_mapping テーブル


payees[] ─────┐
              │
deleted[] ────┼──▶ batchChangePayees
              │         │
updated[] ────┤         ├──▶ deletePayee (振替チェック)
              │         ├──▶ insertPayee
added[] ──────┘         └──▶ updatePayee
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| payee.ts | `packages/loot-core/src/types/models/payee.ts` | 型定義 | 支払先データ型 |
| models.ts | `packages/loot-core/src/server/models.ts` | ソース | 支払先モデル・バリデーション |
| app.ts | `packages/loot-core/src/server/payees/app.ts` | ソース | 支払先APIハンドラ |
| db/index.ts | `packages/loot-core/src/server/db/index.ts` | ソース | データベース操作 |
| methods.ts | `packages/api/methods.ts` | ソース | 外部API |
| ManagePayees.tsx | `packages/desktop-client/src/components/payees/ManagePayees.tsx` | ソース | 支払先管理UI |
| PayeeTable.tsx | `packages/desktop-client/src/components/payees/PayeeTable.tsx` | ソース | 支払先テーブル |
