# 通知設計書 55-ダッシュボードインポートファイルエラー

## 概要

本ドキュメントは、ダッシュボード設定をJSONファイルからインポートした際に、ファイルのJSON解析（パース）に失敗した場合に表示されるエラー通知の設計書です。

### 本通知の処理概要

ダッシュボードのインポート操作中に、選択されたファイルがJSON形式として解析できない場合（SyntaxError発生時）に、ユーザーに対してエラーを通知します。

**業務上の目的・背景**：Actual Budget のダッシュボードインポート機能では、JSON形式のファイルを読み込んでダッシュボード設定を復元します。ユーザーが誤って非JSONファイル（テキストファイル、画像ファイル等）を選択したり、JSONファイルが破損している場合、システムはファイルを解析できません。この通知は、ファイル形式の問題をユーザーに伝え、正しいJSONファイルでの再試行を促すことを目的としています。

**通知の送信タイミング**：ダッシュボードのメニューから「Import」オプションを選択し、ファイルを選択後、`dashboard-import` API呼び出しの結果として `json-parse-error` が返された直後に通知が発行されます。

**通知の受信者**：ダッシュボードのインポート操作を実行した現在のユーザーが受信者となります。

**通知内容の概要**：「Failed parsing the imported JSON.」という固定のエラーメッセージが表示されます。

**期待されるアクション**：ユーザーはエラーメッセージを確認し、正しいJSON形式のダッシュボードエクスポートファイルを選択して再度インポートを試みることが期待されます。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| 通知タイプ | error |
| 通知ID | import |
| sticky | false（デフォルト） |

### 本文テンプレート

```
Failed parsing the imported JSON.
```

### 添付ファイル

該当なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | ダッシュボードメニューの「Import」選択 + ファイル選択 | `dashboard-import` APIが json-parse-error を返した場合 | JSON.parse()でSyntaxErrorが発生 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| API呼び出しが成功した場合 | 成功時は成功通知（No.53）が表示される |
| validation-error の場合 | 別のエラー通知（No.54）が表示される |
| internal-error の場合 | 別のエラー通知（No.54）が表示される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[dashboard-import API呼び出し] --> B[ファイル読み込み]
    B --> C[JSON.parse実行]
    C --> D{パース結果}
    D -->|成功| E[バリデーション実行]
    D -->|SyntaxError| F[json-parse-error レスポンス]
    F --> G[クライアント側でエラー処理]
    G --> H[addNotification発行]
    H --> I[JSONパースエラー通知表示]
    I --> J[終了]
    E --> K[以降の処理継続]
```

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

### 参照テーブル一覧

該当なし（JSONパース段階でエラーが発生するため、DB操作は行われない）

### 更新テーブル一覧

該当なし（エラー時はDB更新は行われない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| json-parse-error | ファイルがJSON形式として解析できない | 固定エラーメッセージを表示 |

### 発生する可能性のあるファイル問題

| 問題 | 具体例 |
|------|-------|
| 非JSONファイル | .txt, .csv, .xml, 画像ファイル等 |
| 破損したJSONファイル | 途中で切れている、文字化けしている |
| 不正なJSON構文 | 末尾のカンマ、クォートの不整合、制御文字 |
| エンコーディング問題 | BOMが含まれる、UTF-8以外のエンコーディング |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- エラーメッセージは固定文言のため、ファイル内容やパスの情報漏洩リスクはない
- 不正なファイルによる攻撃はJSON.parse段階でブロックされる
- 大容量ファイルによるDoS攻撃は別途対策が必要

## 備考

- 通知ID「import」は、他のダッシュボードインポート/リセット関連通知と共有されている
- JSON.parseはJavaScript標準のSyntaxErrorをスローするため、エラー検出は確実
- エラー通知は sticky ではないため、一定時間後に自動的に消える
- ファイル選択ダイアログでは.jsonフィルターが設定されているが、ユーザーは「すべてのファイル」を選択可能

---

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

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

### 推奨読解順序

#### Step 1: JSONパース処理を理解する

まず、サーバー側でのファイル読み込みとJSONパース処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app.ts | `packages/loot-core/src/server/dashboard/app.ts` | importDashboard関数のファイル読み込み・パース部分（264-270行目） |

**読解のコツ**:
- fs.readFile でファイル内容を文字列として読み込み
- JSON.parse でJSONオブジェクトに変換
- JSON.parse は不正な入力に対して SyntaxError をスロー

#### Step 2: エラーハンドリングを理解する

サーバー側でのエラー検出とクライアント側での通知発行を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | app.ts | `packages/loot-core/src/server/dashboard/app.ts` | catchブロック（334-346行目）でSyntaxError判定 |
| 2-2 | Overview.tsx | `packages/desktop-client/src/components/reports/Overview.tsx` | onImport関数の json-parse-error ハンドリング（321-331行目） |

**主要処理フロー**:
1. **339-341行目（サーバー）**: `err instanceof SyntaxError` で判定し、`{ error: 'json-parse-error' }` を返す
2. **321-331行目（クライアント）**: switch文で 'json-parse-error' ケースを処理

#### Step 3: 通知発行を理解する

クライアント側での通知オブジェクト構築を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Overview.tsx | `packages/desktop-client/src/components/reports/Overview.tsx` | addNotification呼び出し（323-330行目） |

**主要処理フロー**:
- **323-330行目**: `type: 'error'`, `id: 'import'`, `message: t('Failed parsing the imported JSON.')` で通知を発行

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

```
Overview.tsx (ダッシュボード画面)
    │
    ├─ onImport (285行目)
    │      │
    │      ├─ send('dashboard-import', {...}) (314行目)
    │      │      └─ dashboard/app.ts: importDashboard (257行目)
    │      │             ├─ fs.exists (265行目)
    │      │             ├─ fs.readFile (269行目)
    │      │             ├─ JSON.parse (270行目)
    │      │             │      └─ [SyntaxError発生]
    │      │             │
    │      │             └─ catch (334行目)
    │      │                    └─ instanceof SyntaxError (339行目)
    │      │                           └─ return { error: 'json-parse-error' }
    │      │
    │      └─ switch(res.error) (321行目)
    │             └─ case 'json-parse-error' (322行目)
    │                    └─ addNotification({
    │                         id: 'import',
    │                         type: 'error',
    │                         message: 'Failed parsing the imported JSON.'
    │                       })
    │
    └─ 通知表示
```

### データフロー図

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

ファイル選択
    │
    ▼
fs.readFile ───▶ content (string)
                     │
                     ▼
               JSON.parse(content)
                     │
        ┌────────────┴────────────┐
        ▼                         ▼
   [正常終了]              [SyntaxError]
        │                         │
        ▼                         ▼
   バリデーション       { error: 'json-parse-error' }
                                  │
                                  ▼
                         addNotification({
                           type: 'error',
                           message: 'Failed parsing...'
                         })
                                  │
                                  ▼
                         [エラートースト表示]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Overview.tsx | `packages/desktop-client/src/components/reports/Overview.tsx` | ソース | ダッシュボード画面コンポーネント |
| app.ts | `packages/loot-core/src/server/dashboard/app.ts` | ソース | ダッシュボードAPIハンドラー |
| notificationsSlice.ts | `packages/desktop-client/src/notifications/notificationsSlice.ts` | ソース | 通知状態管理スライス |
| fs/index.ts | `packages/loot-core/src/platform/server/fs/index.ts` | ソース | ファイルシステム操作 |
