# 画面設計書 20-支払先管理画面（モバイル）

## 概要

本ドキュメントは、Actual Budgetアプリケーションにおけるモバイル向け支払先管理画面の設計仕様を定義する。

### 本画面の処理概要

支払先管理画面（モバイル）は、支払先（Payee）の一覧表示と管理を行うモバイル最適化画面である。支払先の一覧表示、検索、編集、ルール管理、削除などの機能を提供する。

**業務上の目的・背景**：モバイルデバイスからでも支払先の管理ができるようにすることで、外出先でも取引入力時に使用する支払先の確認・編集が可能になる。また、支払先に関連するルールの確認・作成により、カテゴリ自動設定の管理ができる。

**画面へのアクセス方法**：サイドバーの「Payees」メニューをタップしてアクセスする。URLパターンは `/payees` である。

**主要な操作・処理内容**：
1. 支払先一覧の表示（フィルタリング対応）
2. 支払先詳細画面への遷移
3. 支払先に関連するルールの表示/作成
4. 支払先の削除（スワイプ操作）

**画面遷移**：
- 遷移元：サイドバー
- 遷移先：支払先編集画面（モバイル）、ルール一覧画面、ルール新規作成画面

**権限による表示制御**：特になし。認証済みユーザーであれば全機能を利用可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | 支払先管理 | 主機能 | モバイルでの支払先管理 |
| 60 | レスポンシブUI | 補助機能 | モバイル最適化表示 |

## 画面種別

一覧

## URL/ルーティング

`/payees`

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | 型 | 必須 | 説明 |
|--------|--------|----------|-----|------|------|
| フィルタ | filter | 入力 | string | No | 支払先検索用キーワード |

## 表示項目

| 項目名 | 説明 | データソース |
|--------|------|-------------|
| ページタイトル | 「Payees」 | i18n |
| 検索フィールド | 支払先検索用 | - |
| 支払先一覧 | 支払先のリスト | payees |

### 支払先リスト項目

| 項目名 | 説明 |
|--------|------|
| 支払先名 | 支払先の名前 |
| ルール数バッジ | 支払先に関連するルールの数（0件の場合は非表示） |

## イベント仕様

### 1-フィルタ入力

検索フィールドにキーワードを入力すると、支払先一覧がフィルタリングされる。フィルタはnormalized stringで比較される（getNormalisedString）。

### 2-支払先項目タップ

支払先項目をタップすると、支払先編集画面（`/payees/:id`）に遷移する。

### 3-ルールアクション

支払先項目のルールボタンをタップすると：
- **ルールあり**：`payees-get-rules`で関連ルールを取得し、`/rules?visible-rules=id1,id2,...`に遷移
- **ルールなし**：`/rules/new`に遷移し、支払先条件付きの新規ルール作成画面を表示

### 4-支払先削除（スワイプ）

支払先項目を左にスワイプすると削除オプションが表示され、削除を実行できる。`payees-batch-change`を呼び出して削除。削除後はUndo通知が表示される。削除失敗時はエラー通知を表示。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | payees | SELECT | 全支払先を取得 |
| 削除 | payees | DELETE | 支払先を削除 |

### テーブル別更新項目詳細

#### payees

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | id = 指定ID | スワイプ削除時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|------------|
| M001 | 情報 | Filter payees... | 検索プレースホルダー |
| M002 | 成功 | Payee "{{name}}" deleted successfully | 削除成功時（Undo通知） |
| M003 | エラー | Failed to delete payee. Please try again. | 削除失敗時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 支払先データなし | 空のリストを表示 |
| 削除エラー | エラー通知を表示 |
| ルール取得エラー | ルール一覧画面（/rules）にフォールバック |
| ローディング中 | isLoading状態で表示 |

## 備考

- usePayeesフックで支払先データを取得
- usePayeeRuleCountsフックで各支払先のルール数を取得
- getNormalisedStringでフィルタ比較（正規化された文字列）
- PayeesListコンポーネントで一覧表示
- showUndoNotificationでUndo通知を表示
- isLoading状態はpayees.isPayeesLoadingとpayees.isCommonPayeesLoadingから計算

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: PayeeEntityのid, nameフィールドに注目。RuleEntityの構造も確認。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MobilePayeesPage.tsx | `packages/desktop-client/src/components/mobile/payees/MobilePayeesPage.tsx` | メインコンポーネント |

**主要処理フロー**:
1. **行23-33**: コンポーネント初期化（usePayees, usePayeeRuleCounts, useState）
2. **行35-39**: filteredPayeesで名前フィルタリング（getNormalisedString使用）
3. **行41-43**: onSearchChangeコールバック
4. **行45-50**: handlePayeePressコールバック（navigate(`/payees/${payee.id}`)）
5. **行52-88**: handlePayeeRuleActionコールバック
   - ルールあり：payees-get-rulesでルール取得、/rules?visible-rules=に遷移
   - ルールなし：/rules/newに遷移（支払先条件付き）
6. **行90-112**: handlePayeeDeleteコールバック
   - payees-batch-changeで削除
   - 成功時：showUndoNotification
   - 失敗時：addNotification（error）

#### Step 3: リストコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PayeesList.tsx | `packages/desktop-client/src/components/mobile/payees/PayeesList.tsx` | 支払先リスト |
| 3-2 | PayeesListItem.tsx | `packages/desktop-client/src/components/mobile/payees/PayeesListItem.tsx` | リスト項目 |

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

```
MobilePayeesPage (エントリーポイント)
    |
    +-- Page
    |       +-- MobilePageHeader
    |               +-- Text (Payees)
    |
    +-- View (検索行)
    |       +-- Search (フィルタ入力)
    |               +-- value: filter
    |               +-- onChange: onSearchChange
    |
    +-- PayeesList
            +-- PayeesListItem (複数)
            |       +-- 支払先名表示
            |       +-- ルール数バッジ
            |       +-- タップ --> handlePayeePress --> navigate('/payees/:id')
            |       +-- ルールボタン --> handlePayeeRuleAction
            |       |       +-- ルールあり --> navigate('/rules?visible-rules=...')
            |       |       +-- ルールなし --> navigate('/rules/new', { state: { rule } })
            |       +-- スワイプ削除 --> handlePayeeDelete
            |               +-- 成功 --> showUndoNotification
            |               +-- 失敗 --> addNotification(error)
```

### データフロー図

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

DB payees         --->  usePayees                  --->  payees array
                        (フック)

Redux state       --->  useSelector                --->  isLoading
(payees.isPayeesLoading,   (セレクタ)
 payees.isCommonPayeesLoading)

DB rules          --->  usePayeeRuleCounts         --->  ruleCounts Map
                        (フック)                          (payeeId -> count)

User input        --->  getNormalisedString        --->  filteredPayees
(filter)                (正規化比較)

User action       --->  navigate                   --->  支払先編集画面遷移
(Item tap)              ('/payees/:id')

User action       --->  send('payees-get-rules')   --->  関連ルール取得
(Rule action -         --> navigate('/rules?visible-rules=...')
 rules exist)

User action       --->  navigate('/rules/new')     --->  ルール新規作成画面
(Rule action -         (支払先条件付き)
 no rules)

User action       --->  send('payees-batch-change')--->  支払先削除
(Swipe delete)          { deleted: [{ id }] }
                        --> showUndoNotification
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MobilePayeesPage.tsx | `packages/desktop-client/src/components/mobile/payees/MobilePayeesPage.tsx` | ソース | メインコンポーネント |
| PayeesList.tsx | `packages/desktop-client/src/components/mobile/payees/PayeesList.tsx` | ソース | 支払先リスト |
| PayeesListItem.tsx | `packages/desktop-client/src/components/mobile/payees/PayeesListItem.tsx` | ソース | リスト項目 |
| usePayees.ts | `packages/desktop-client/src/hooks/usePayees.ts` | ソース | 支払先データフック |
| usePayeeRuleCounts.ts | `packages/desktop-client/src/hooks/usePayeeRuleCounts.ts` | ソース | ルールカウントフック |
| useUndo.ts | `packages/desktop-client/src/hooks/useUndo.ts` | ソース | Undo機能フック |
| Search.tsx | `packages/desktop-client/src/components/common/Search.tsx` | ソース | 検索コンポーネント |
| notificationsSlice.ts | `packages/desktop-client/src/notifications/notificationsSlice.ts` | ソース | 通知管理 |
