# 機能設計書 5-口座作成・編集・削除

## 概要

本ドキュメントは、Actual Budget における銀行口座、クレジットカード等の口座を作成・編集・削除する機能の設計を記述する。予算管理の基盤となる口座情報の管理機能である。

### 本機能の処理概要

**業務上の目的・背景**：予算管理において、口座は取引を記録する基本単位である。銀行口座、クレジットカード、現金など、様々な種類の口座を登録し、それぞれの残高と取引を追跡することで、総合的な財務状況を把握できる。本機能は、口座の作成から編集、削除までのライフサイクル全体を管理する。

**機能の利用シーン**：
- 新しい銀行口座を開設した際に口座を追加する
- クレジットカードを新規発行した際に口座を追加する
- 口座名を変更する（銀行名変更など）
- 使用しなくなった口座を削除する
- 口座を予算内/予算外（オフバジェット）に設定する

**主要な処理内容**：
1. 新規口座の作成（口座名、タイプ、初期残高）
2. 口座情報の編集（名前、オフバジェット設定）
3. 口座の削除（関連取引の処理含む）
4. 口座一覧の表示と管理

**関連システム・外部連携**：銀行連携（GoCardless、SimpleFIN、PluggyAI）、同期機能

**権限による制御**：特別な権限制御なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | 口座一覧画面（デスクトップ） | 主画面 | 口座の作成・編集・削除処理 |
| 13 | 口座一覧画面（モバイル） | 主画面 | モバイルでの口座管理 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### 口座作成

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | 口座名 | 空でないこと、重複しないこと |
| offbudget | boolean | No | 予算外口座かどうか | デフォルト: false |
| closed | boolean | No | クローズ状態 | デフォルト: false |
| initialBalance | number | No | 初期残高（セント単位） | 整数 |

#### 口座更新

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 口座ID | 存在する口座ID |
| fields | object | Yes | 更新するフィールド | 有効なフィールド名 |

#### 口座削除

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 口座ID | 存在する口座ID |

### 入力データソース

- 画面入力：口座追加モーダル、口座編集画面
- API経由：外部システムからの口座作成

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | 作成された口座のID（作成時） |
| accounts | Account[] | 口座一覧 |

### 出力先

- データベース：accounts テーブル
- 画面表示：サイドバーの口座一覧

## 処理フロー

### 処理シーケンス

```
【口座作成】
1. 口座追加ボタンをクリック
   └─ add-account モーダルを表示

2. 口座情報を入力
   └─ 口座名、タイプ、初期残高を入力

3. 作成ボタンをクリック
   └─ api/account-create を呼び出し

4. サーバーで口座レコードを作成
   └─ accounts テーブルに INSERT
   └─ 初期残高がある場合は取引も作成

5. UIを更新
   └─ 口座一覧に新しい口座が表示される

【口座編集】
1. 口座名をクリックして編集
   └─ インライン編集または編集画面

2. 変更を保存
   └─ api/account-update を呼び出し

【口座削除】
1. 口座メニューから削除を選択
   └─ 確認ダイアログを表示

2. 削除を確認
   └─ api/account-delete を呼び出し
   └─ 関連取引は tombstone フラグで論理削除
```

### フローチャート

```mermaid
flowchart TD
    A[口座管理開始] --> B{操作種別?}
    B -->|作成| C[add-account モーダル表示]
    B -->|編集| D[編集画面/インライン編集]
    B -->|削除| E[削除確認ダイアログ]
    C --> F[口座情報入力]
    F --> G[api/account-create]
    G --> H[accounts INSERT]
    H --> I{初期残高あり?}
    I -->|Yes| J[初期残高取引作成]
    I -->|No| K[完了]
    J --> K
    D --> L[情報変更]
    L --> M[api/account-update]
    M --> K
    E --> N{確認?}
    N -->|Yes| O[api/account-delete]
    N -->|No| K
    O --> P[関連取引の処理]
    P --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 口座名の一意性 | 同一予算内で口座名は重複不可 | 口座作成・編集時 |
| BR-002 | 初期残高取引 | 初期残高は「Starting Balance」取引として作成 | 初期残高指定時 |
| BR-003 | 削除時の取引処理 | 削除された口座の取引は tombstone フラグで論理削除 | 口座削除時 |
| BR-004 | 振替口座の削除 | 削除時に振替取引の転送先を指定可能 | 残高がある口座の削除時 |

### 計算ロジック

```
// 口座残高
accountBalance = SUM(transactions.amount) WHERE account = accountId

// 初期残高取引
initialBalanceTransaction = {
  account: accountId,
  amount: initialBalance,
  payee: "Starting Balance" payee,
  date: currentDate
}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 口座作成 | accounts | INSERT | 新規口座レコード作成 |
| 初期残高 | transactions | INSERT | 初期残高取引作成 |
| 口座更新 | accounts | UPDATE | 口座情報更新 |
| 口座削除 | accounts | UPDATE (tombstone) | 論理削除 |

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

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | UUID | 主キー |
| INSERT | name | 口座名 | |
| INSERT | offbudget | 0/1 | 予算外フラグ |
| INSERT | closed | 0/1 | クローズフラグ |
| INSERT | sort_order | 整数 | 表示順 |
| UPDATE | tombstone | 1 | 論理削除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| DUPLICATE_NAME | バリデーション | 口座名が重複 | 別の名前を入力 |
| ACCOUNT_NOT_FOUND | データ不整合 | 存在しない口座ID | エラー通知を表示 |

### リトライ仕様

- 同期エラー時は自動リトライ

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

- 口座作成と初期残高取引はトランザクション内で実行

## パフォーマンス要件

- 口座操作は即座に反映（100ms以内）

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

- 口座情報はローカル保存
- 銀行連携時の認証情報は暗号化保存

## 備考

- 口座は物理削除ではなく論理削除（tombstone）
- 銀行連携との統合は別機能（GoCardless連携等）

---

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

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

### 推奨読解順序

#### Step 1: API層を理解する

口座操作のAPI定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | methods.ts | `packages/api/methods.ts` | createAccount, updateAccount, deleteAccount 関数 |

**主要処理フロー**:
- **168-169行目**: `getAccounts` 関数
- **172-177行目**: `createAccount` 関数（account, initialBalance パラメータ）
- **179-184行目**: `updateAccount` 関数
- **202-204行目**: `deleteAccount` 関数

#### Step 2: 口座一覧画面を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Account.tsx | `packages/desktop-client/src/components/accounts/Account.tsx` | 口座詳細画面とメニュー操作 |

**主要処理フロー**:
- **751-769行目**: `onSaveName` で口座名を保存
- **775-898行目**: `onMenuSelect` でメニュー操作（link, unlink, close, reopen等）

#### Step 3: Redux スライスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | accountsSlice.ts | `packages/desktop-client/src/accounts/accountsSlice.ts` | 口座関連のReduxアクション |

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

```
Account.tsx (口座画面)
    │
    ├─ onSaveName
    │      └─ dispatch(updateAccount({ account: { ...account, name } }))
    │
    ├─ onMenuSelect
    │      │
    │      ├─ 'link' → pushModal('add-account')
    │      ├─ 'unlink' → pushModal('confirm-unlink-account')
    │      ├─ 'close' → openAccountCloseModal({ accountId })
    │      └─ 'reopen' → dispatch(reopenAccount({ id }))
    │
    └─ Redux Actions
           │
           ├─ updateAccount → api/account-update
           ├─ reopenAccount → api/account-reopen
           ├─ unlinkAccount → api/account-unlink
           └─ deleteAccount → api/account-delete

API (methods.ts)
    │
    ├─ createAccount → send('api/account-create', { account, initialBalance })
    ├─ updateAccount → send('api/account-update', { id, fields })
    ├─ deleteAccount → send('api/account-delete', { id })
    ├─ closeAccount → send('api/account-close', { id, transferAccountId, ... })
    └─ reopenAccount → send('api/account-reopen', { id })
```

### データフロー図

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

口座情報入力       ───▶  createAccount API
(名前、初期残高等)             │
                              ▼
                         accounts INSERT         ───▶  口座レコード
                              │
                              ▼
                         initialBalance 取引作成 ───▶  取引レコード
                              │
                              ▼
                         UI更新                  ───▶  口座一覧表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| methods.ts | `packages/api/methods.ts` | ソース | 口座API関数定義 |
| Account.tsx | `packages/desktop-client/src/components/accounts/Account.tsx` | ソース | 口座詳細画面 |
| Header.tsx | `packages/desktop-client/src/components/accounts/Header.tsx` | ソース | 口座ヘッダー |
| accountsSlice.ts | `packages/desktop-client/src/accounts/accountsSlice.ts` | ソース | Redux口座スライス |
| AccountsPage.tsx | `packages/desktop-client/src/components/mobile/accounts/AccountsPage.tsx` | ソース | モバイル口座一覧 |
| useAccounts.ts | `packages/desktop-client/src/hooks/useAccounts.ts` | ソース | 口座取得フック |
