# 通知設計書 46-ルール削除失敗（スケジュールリンク）

## 概要

本ドキュメントは、ルールがスケジュールにリンクされているために削除できなかった場合にユーザーに表示される警告通知の設計を定義します。

### 本通知の処理概要

この通知は、ユーザーがルール管理画面でルールを削除しようとした際に、そのルールがスケジュール（定期取引）にリンクされているため削除できなかった場合に表示される警告通知です。Actualでは、スケジュールは関連するルールを通じて取引に対するアクション（カテゴリ設定など）を定義しており、スケジュールにリンクされているルールは先にスケジュールから切り離す必要があります。

**業務上の目的・背景**：ルールとスケジュールは密接に関連しており、スケジュールが正常に機能するためには関連ルールが必要です。ユーザーがスケジュールにリンクされたルールを誤って削除することを防ぐため、削除を拒否し、その理由を明確に通知します。

**通知の送信タイミング**：ルール管理画面（モバイル版）でルールを削除しようとし、`rule-delete-all` APIがsomeDeletionsFailedをtrueで返した場合に即座に発行されます。

**通知の受信者**：ルール削除操作を試みた現在のユーザー（ローカル通知）

**通知内容の概要**：「This rule could not be deleted because it is linked to a schedule.」（このルールはスケジュールにリンクされているため削除できませんでした）という警告メッセージを表示します。

**期待されるアクション**：ユーザーは関連するスケジュールを確認し、ルールをスケジュールから切り離してから再度削除を試みます。または、スケジュール自体が不要であれば先にスケジュールを削除します。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Redux dispatch） |
| 優先度 | 中 |
| リトライ | 無し |

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

ルール削除操作を試みた現在のユーザーのみに対してローカル通知を表示します。

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| 通知タイプ | warning |
| タイトル | なし |
| メッセージ | This rule could not be deleted because it is linked to a schedule. |
| タイムアウト | 6.5秒（デフォルト） |

### 本文テンプレート

```
This rule could not be deleted because it is linked to a schedule.
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 固定メッセージのため変数なし | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | rule-delete-all API | someDeletionsFailed === true | モバイル版でのルール削除時にスケジュールリンクあり |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 削除が成功した場合 | someDeletionsFailedがfalseの場合は通知しない（成功通知No.48を表示） |
| デスクトップ版の場合 | デスクトップ版ではalert()を使用（別の実装） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ルール削除操作] --> B[rule-delete-all API呼び出し]
    B --> C{APIレスポンス}
    C -->|someDeletionsFailed: false| D[成功通知 No.48]
    C -->|someDeletionsFailed: true| E[addNotification dispatch]
    E --> F[警告通知表示]
    F --> G[6.5秒後自動消去]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| rules | 削除対象ルールの確認 | サーバー側で参照 |
| schedules | ルールとスケジュールの関連確認 | schedule.rule === rule.id |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | スケジュールリンクのためルールは削除されない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| スケジュールリンク | ルールがスケジュールにリンクされている | スケジュールから切り離すよう案内 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回 |
| リトライ間隔 | - |
| リトライ対象エラー | なし（ユーザーの対処が必要） |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- ルール名やスケジュール名などの詳細情報は通知メッセージに含めない
- ローカル通知のためネットワーク経由での情報漏洩リスクなし

## 備考

- モバイル版（MobileRulesPage.tsx）とデスクトップ版（ManageRules.tsx）で実装が異なる
- デスクトップ版ではalert()関数を使用してブラウザのネイティブアラートを表示
- モバイル版ではReduxの通知システムを使用
- ルール一覧は削除操作後に再読込される

---

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

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

### 推奨読解順序

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

ルールとスケジュールの関連を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ManageRules.tsx | `packages/desktop-client/src/components/ManageRules.tsx` | filteredRulesでスケジュールとルールの関連をフィルタリング（156-171行目） |

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

モバイル版での通知発行を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MobileRulesPage.tsx | `packages/desktop-client/src/components/mobile/rules/MobileRulesPage.tsx` | handleRuleDelete関数（128-167行目） |

**主要処理フロー**:
1. **131行目**: `send('rule-delete-all', [rule.id])`でサーバーにルール削除リクエスト
2. **135行目**: someDeletionsFailedをチェック
3. **136-145行目**: someDeletionsFailedがtrueの場合、warning通知をdispatch
4. **140-142行目**: メッセージ「This rule could not be deleted because it is linked to a schedule.」

#### Step 3: デスクトップ版の実装を理解する

デスクトップ版での別の実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ManageRules.tsx | `packages/desktop-client/src/components/ManageRules.tsx` | onDeleteSelected関数（223-239行目） |

**主要処理フロー**:
- **226-228行目**: `send('rule-delete-all', [...selectedInst.items])`で削除リクエスト
- **230-234行目**: someDeletionsFailedがtrueの場合、alert()でネイティブアラートを表示

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

```
MobileRulesPage.tsx
    │
    ├─ handleRuleDelete(rule)
    │      │
    │      └─ send('rule-delete-all', [rule.id])
    │             │
    │             └─ APIレスポンス
    │                    │
    │                    ├─ someDeletionsFailed: false
    │                    │      └─ showUndoNotification (成功通知 No.48)
    │                    │
    │                    └─ someDeletionsFailed: true
    │                           │
    │                           └─ dispatch(addNotification({
    │                                  type: 'warning',
    │                                  message: 'This rule could not be deleted...'
    │                              }))
    │
    └─ Notifications コンポーネント
           └─ 警告通知を画面に描画
```

### データフロー図

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

ルール削除操作 ───────▶ send('rule-delete-all') ───────▶ サーバーAPI
                              │                          │
                              ▼                          ▼
                        APIレスポンス ◀─────────── someDeletionsFailed判定
                              │                     （スケジュールリンク確認）
                              │
                              ├─ false: 成功通知 No.48
                              │
                              └─ true: addNotification dispatch
                                     │
                                     └─ type: 'warning'
                                            │
                                            ▼
                                      Notifications.tsx
                                            │
                                            ▼
                                      警告トースト表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MobileRulesPage.tsx | `packages/desktop-client/src/components/mobile/rules/MobileRulesPage.tsx` | ソース | モバイル版ルール管理画面 |
| ManageRules.tsx | `packages/desktop-client/src/components/ManageRules.tsx` | ソース | デスクトップ版ルール管理画面 |
| notificationsSlice.ts | `packages/desktop-client/src/notifications/notificationsSlice.ts` | ソース | 通知の状態管理（Redux slice） |
| Notifications.tsx | `packages/desktop-client/src/components/Notifications.tsx` | ソース | 通知表示コンポーネント |
| app.ts | `packages/loot-core/src/server/rules/app.ts` | ソース | サーバー側ルールAPI |
| app.ts | `packages/loot-core/src/server/schedules/app.ts` | ソース | サーバー側スケジュールAPI |
