# 通知設計書 51-ユーザー取得失敗（所有権移転）

## 概要

本ドキュメントは、予算ファイルの所有権移転機能において、移転先候補となるユーザー一覧の取得に失敗した場合に表示されるエラー通知の設計書です。

### 本通知の処理概要

所有権移転モーダルで、サーバーからユーザー一覧を取得する際にエラーが発生した場合に、ユーザーに対してエラーを通知します。

**業務上の目的・背景**：Actual Budget のマルチユーザー環境では、予算ファイルの所有権を他のユーザーに移転する機能があります。この機能を利用する際、システムは移転先候補となるユーザー一覧をサーバーから取得する必要があります。サーバーとの通信エラーやアクセス権限の問題によりユーザー一覧の取得に失敗した場合、ユーザーに状況を通知し、再試行を促す必要があります。

**通知の送信タイミング**：所有権移転モーダル（TransferOwnership）が開かれた際に、`users-get` API を呼び出してユーザー一覧を取得します。このAPI呼び出しの結果にエラーが含まれている場合に通知が発行されます。

**通知の受信者**：所有権移転モーダルを開いた現在のユーザー（予算ファイルの現在の所有者または管理者）が受信者となります。

**通知内容の概要**：エラー通知として「Error getting users」というタイトルと「Failed to complete ownership transfer. Please try again.」というメッセージが表示されます。

**期待されるアクション**：ユーザーは通知を確認後、モーダルを閉じて再度所有権移転を試みるか、ネットワーク接続やサーバー状態を確認することが期待されます。

## 通知種別

アプリ内通知（トースト通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（即時） |
| 優先度 | 高 |
| リトライ | 無し |

### 送信先決定ロジック

現在アプリケーションを操作しているユーザーに対して表示されます。サーバーサイドでの送信先決定は行われず、クライアントサイドで直接通知が表示されます。

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 通知タイプ | error |
| タイトル | Error getting users |
| sticky | true |

### 本文テンプレート

```
Failed to complete ownership transfer. Please try again.
```

### 添付ファイル

該当なし

## テンプレート変数

該当なし（固定メッセージ）

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | TransferOwnershipモーダルの表示 | `users-get` API呼び出しがエラーを返した場合 | useEffect内でのAPI呼び出し結果にerrorプロパティが含まれる場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| APIが正常に応答した場合 | ユーザー一覧が正常に取得できた場合は通知しない |
| APIがnullを返した場合 | ユーザー一覧が空の場合はエラー通知ではなく、空の一覧として処理 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[TransferOwnershipモーダル表示] --> B[users-get API呼び出し]
    B --> C{APIレスポンス確認}
    C -->|レスポンスがnull| D[availableUsersを空配列に設定]
    C -->|errorプロパティあり| E[addNotification発行]
    C -->|正常データ| F[ユーザー一覧を表示]
    E --> G[エラー通知表示]
    D --> H[終了]
    F --> H
    G --> H
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| users（サーバー側） | ユーザー一覧の取得 | sync-serverのユーザーテーブル |

### テーブル別参照項目詳細

#### users（サーバー側）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ユーザーID | 全ユーザー |
| userName | ユーザー名 | 全ユーザー |
| displayName | 表示名 | 全ユーザー |

### 更新テーブル一覧

該当なし（通知のみで永続化されない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| API呼び出しエラー | サーバーとの通信失敗 | エラー通知を表示し、ユーザーに再試行を促す |
| 認証エラー | ユーザーのアクセス権限不足 | エラー通知を表示 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回（自動リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（ユーザー操作に応じて即時表示）

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

- ユーザー一覧の取得には適切な権限が必要
- エラーメッセージには詳細な技術情報を含めず、一般的なメッセージを表示
- 所有権移転は不可逆な操作であり、適切な警告を表示

## 備考

- この通知は sticky: true が設定されているため、ユーザーが明示的に閉じるまで表示され続ける
- i18n対応により、ユーザーの言語設定に応じてメッセージが翻訳される

---

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

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

### 推奨読解順序

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

まず、通知のデータ構造と所有権移転に関連する型定義を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notificationsSlice.ts | `packages/desktop-client/src/notifications/notificationsSlice.ts` | Notification型（9-26行目）でsticky、type、titleプロパティの定義を確認 |

**読解のコツ**: Redux Toolkitのスライス構造を理解し、addNotificationアクションのペイロード構造を把握する。

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

処理の起点となる所有権移転モーダルコンポーネントを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TransferOwnership.tsx | `packages/desktop-client/src/components/modals/TransferOwnership.tsx` | モーダルコンポーネントの全体構造と通知発行箇所を理解 |

**主要処理フロー**:
1. **56-88行目**: useEffectでコンポーネントマウント時にusers-get APIを呼び出し
2. **61-73行目**: APIレスポンスにerrorが含まれる場合にaddNotificationをdispatch
3. **62-72行目**: エラー通知のオブジェクト構造（type: 'error', title, message, sticky: true）

#### Step 3: 通知システムを理解する

通知の追加・表示メカニズムを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | notificationsSlice.ts | `packages/desktop-client/src/notifications/notificationsSlice.ts` | addNotificationリデューサーの実装（58-68行目） |

**主要処理フロー**:
- **58-68行目**: 通知をstateに追加、同じIDの通知が既に存在する場合はスキップ

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

```
TransferOwnership.tsx (モーダルコンポーネント)
    │
    ├─ useEffect (56行目)
    │      ├─ send('users-get') (57行目)
    │      │      └─ サーバーAPIハンドラー呼び出し
    │      │
    │      └─ [エラー時] dispatch(addNotification(...)) (62行目)
    │             └─ notificationsSlice.addNotification
    │
    └─ [レンダリング] Modal / Select / Button
```

### データフロー図

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

モーダル表示 ───▶ users-get API呼び出し ───▶ [正常] ユーザー一覧表示
                        │
                        └─▶ [エラー] addNotification ───▶ エラートースト表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TransferOwnership.tsx | `packages/desktop-client/src/components/modals/TransferOwnership.tsx` | ソース | 所有権移転モーダルコンポーネント |
| notificationsSlice.ts | `packages/desktop-client/src/notifications/notificationsSlice.ts` | ソース | 通知状態管理スライス |
| errors.ts | `packages/loot-core/src/shared/errors.ts` | ソース | エラーメッセージ取得関数（getUserAccessErrors） |
| handlers.ts | `packages/loot-core/src/types/handlers.ts` | 型定義 | users-get ハンドラーの型定義 |
