Skip to the content.

Use Cases

resource-planner の主要ユースケースを Mermaid sequence diagram で記述する。 SvelteKit form actions / +page.server.ts load の動的振る舞い (画面 → action → DB → redirect/render) を「設計仕様」として残す場所。

書き方

各ユースケースは:

  1. 見出し: ## UC-NN: 短い動詞句 (例: ## UC-01: アサインを作成する)
  2. 概要: 1-2 文
  3. アクター / 前提条件: 誰が / どんな状態で発火するか
  4. 対応コード: 該当する +page.server.ts / form action / load 関数へのリンク (実装後に追記)
  5. Mermaid sequence: 動作フロー
  6. エラーケース: 失敗パスを箇条書き

一覧

# Use case 状態
UC-01 リソース (人) を追加・編集・削除する 実装済 (PR-C)
UC-02 案件 (Project) を追加・編集・削除する 実装済 (PR-D)
UC-03 アサインを作成する 実装済 (PR-E)
UC-04 アサインの期間を変更する (ドラッグ / リサイズ) 実装済 (PR-F)
UC-05 アサインを削除する 実装済 (PR-G)
UC-06 人 / 案件を削除する (cascade) 実装済 (PR-H)

CRUD 実装の進捗に応じて UC を追記する運用 (#31, docs/adr/0001-typescript-types-as-api-spec.md 参照)。


UC-01: リソース (人) を追加・編集・削除する

概要

組織内のメンバー (Resource) を管理する。タイムラインの行に対応する人を CRUD する。

アクター / 前提条件

対応コード

Mermaid sequence (作成フロー)

sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server as +page.server.ts<br/>(Lambda)
    participant AuthJs as Auth.js (locals.auth)
    participant DDB as DynamoDB

    User->>SK: 「+ 人を追加」 → 名前入力
    SK->>Server: POST ?/createResource<br/>FormData(name)
    Server->>AuthJs: await locals.auth()
    AuthJs-->>Server: { user: { id, email } }
    alt 未認証
        Server-->>SK: error(403)
        SK-->>User: 「組織が選択されていません」
    end

    Server->>Server: resourceCreateSchema.safeParse(name)
    alt 検証失敗
        Server-->>SK: fail(400, { errors: { name } })
        SK-->>User: name フィールドの下にエラー表示
    else 検証成功
        Server->>Server: id = ulid()
        Server->>DDB: PutItem<br/>pk=TEAM#{teamId}, sk=RES#{id},<br/>ConditionExpression: attribute_not_exists(sk)
        DDB-->>Server: 200
        Server-->>SK: success
        SK->>SK: invalidate → +layout.server.ts 再 load
        SK-->>User: モーダル閉じる + リスト更新
    end

Mermaid sequence (編集 / 削除フロー)

sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server as +page.server.ts
    participant DDB as DynamoDB

    Note over User,DDB: 編集
    User->>SK: 「編集」ボタン → 名前変更
    SK->>Server: POST ?/updateResource<br/>FormData(id, name)
    Server->>Server: resourceUpdateSchema.safeParse
    Server->>DDB: UpdateItem<br/>SET name = :name<br/>ConditionExpression: attribute_exists(sk)
    DDB-->>Server: 200
    Server-->>SK: success → invalidate

    Note over User,DDB: 削除
    User->>SK: 「削除」ボタン → confirm()
    SK->>Server: POST ?/deleteResource<br/>FormData(id)
    Server->>DDB: DeleteItem<br/>pk=TEAM#{teamId}, sk=RES#{id}
    DDB-->>Server: 200
    Server-->>SK: success → invalidate

エラーケース

既知の制約 (PR-C 時点)


UC-02: 案件 (Project) を追加・編集・削除する

概要

案件 (タイムラインで帯の 色とラベル に対応する Project) を組織内で管理する。 帯の表示色をユーザーが選べるようにする。

アクター / 前提条件

対応コード

Mermaid sequence (作成フロー)

sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server as +page.server.ts<br/>(Lambda)
    participant DDB as DynamoDB

    User->>SK: 「+ 案件を追加」 → 名前 + 色入力
    SK->>Server: POST ?/createProject<br/>FormData(name, color)
    Server->>Server: requireSession(event) → session.teamId
    Server->>Server: projectCreateSchema.safeParse({ name, color })
    alt 検証失敗 (color が #RRGGBB でない、name 空)
        Server-->>SK: fail(400, { errors: { name?, color? } })
        SK-->>User: 該当フィールドにエラー
    else 検証成功
        Server->>Server: id = ulid()
        Server->>DDB: PutItem<br/>pk=TEAM#{teamId}, sk=PRJ#{id},<br/>{ id, name, color }<br/>ConditionExpression: attribute_not_exists(sk)
        DDB-->>Server: 200
        Server-->>SK: success
        SK->>SK: invalidate → load 再実行
        SK-->>User: モーダル閉じる + 一覧更新
    end

Mermaid sequence (編集 / 削除)

UC-01 と同形 (UpdateItem / DeleteItem)。差分は更新対象が name + color の 2 フィールドである点のみ。 詳細は UC-01 の編集 / 削除フロー を参照。

エラーケース

既知の制約 (PR-D 時点)


UC-03: アサインを作成する

概要

人 (Resource) を案件 (Project) に 期間 [startDate, endDateExclusive) の半開区間 でアサインする。 タイムラインに帯として表示される。フォーム UX は inclusive (「終了日 5/31」と入力)、内部は exclusive (ADR 0004)。

アクター / 前提条件

対応コード

Mermaid sequence

sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server as +page.server.ts
    participant DDB as DynamoDB

    User->>SK: 「+ アサインを追加」<br/>resource / project 選択 + 期間入力 (inclusive UX)
    SK->>Server: POST ?/createAssignment<br/>FormData(resourceId, projectId,<br/>startDate, endDate)

    Server->>Server: requireSession(event) → session.teamId
    Server->>Server: assignmentCreateSchema.safeParse<br/>(refine: startDate <= endDate)<br/>.transform(): endDateExclusive = addDays(endDate, 1)
    alt 検証失敗
        Server-->>SK: fail(400, { errors })
        SK-->>User: 該当フィールドにエラー
    else 検証成功
        Server->>Server: id = ulid()<br/>sk = ASN#{startDate}#{id}
        Server->>DDB: PutItem<br/>pk=TEAM#{teamId}, sk=ASN#...,<br/>{ id, resourceId, projectId,<br/>startDate, endDateExclusive }<br/>ConditionExpression: attribute_not_exists(sk)
        DDB-->>Server: 200
        Server-->>SK: success
        SK->>SK: invalidate → load 再実行
        SK-->>User: モーダル閉じる + timeline に新帯
    end

endDate の取り扱い (ADR 0004)

業界標準 (RFC 5545 / Google Calendar / PostgreSQL daterange / Java / Rust / Python / Bryntum) と整合する 「内部 exclusive 半開区間 + フォーム inclusive UX + Zod transform で 1 箇所変換」 構成:

エラーケース

既知の制約 (PR-E 時点)


UC-04: アサインの期間を変更する (ドラッグ / リサイズ)

概要

タイムライン上の帯をドラッグして移動 (= 開始日 / リソース変更) またはエッジをドラッグしてリサイズ (= 終了日変更) すると、DB に永続化される。Optimistic UI (即時反映 + 失敗で revert) で応答性を優先。

アクター / 前提条件

対応コード

Mermaid sequence (成功フロー)

sequenceDiagram
    actor User
    participant TL as ResourceTimeline
    participant SK as +page.svelte
    participant API as /api/assignments/[id]<br/>(+server.ts)
    participant DDB as DynamoDB

    User->>TL: 帯を mousedown<br/>→ ドラッグ → mouseup
    TL->>SK: onMove(updated: TimelineAssignment)
    SK->>SK: snapshot = dbAssignments<br/>dbAssignments = map(...)<br/>(即時画面反映)
    SK->>API: PATCH /api/assignments/{id}<br/>{ prevStartDate, resourceId, projectId,<br/>startDate, endDateExclusive }
    API->>API: await locals.auth() → session.teamId<br/>assignmentApiUpdateSchema.safeParse(body)
    API->>DDB: updateAssignment(teamId, prevStartDate, payload)
    note right of DDB: SK 変更あり (startDate 変更時) →<br/>TransactWriteItems<br/>(旧 SK Delete + 新 SK Put)
    DDB-->>API: 200
    API-->>SK: { success: true }
    SK-->>User: 帯が新位置のまま (画面変化なし)

Mermaid sequence (失敗フロー: revert)

sequenceDiagram
    actor User
    participant TL as ResourceTimeline
    participant SK as +page.svelte
    participant API as /api/assignments/[id]
    participant Toast as svelte-sonner

    User->>TL: 帯をドラッグ → mouseup
    TL->>SK: onMove(updated)
    SK->>SK: snapshot保存 + 即時反映
    SK->>API: PATCH /api/assignments/{id}
    note right of API: 認証エラー / DB エラー /<br/>ネットワーク失敗 等
    API-->>SK: 4xx / 5xx
    SK->>SK: dbAssignments = snapshot<br/>(画面が元位置に戻る)
    SK->>Toast: toast.error('保存に失敗しました')
    Toast-->>User: 通知表示<br/>(右上に 5 秒間)

設計判断 (ADR 0005)

endDate の取り扱い

エラーケース

既知の制約 (PR-F 時点)


UC-05: アサインを削除する

概要

「アサイン一覧」モーダルから個別のアサインを削除する。SK が ASN#{startDate}#{id} で構成されるため、フォームから idstartDate の両方を渡す。

アクター / 前提条件

対応コード

Mermaid sequence

sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server as +page.server.ts
    participant DDB as DynamoDB

    User->>SK: 「アサイン一覧」 → 行の「削除」クリック
    SK->>SK: confirm() で「削除しますか?」確認
    alt キャンセル
        SK-->>User: 何もしない
    else OK
        SK->>Server: POST ?/deleteAssignment<br/>FormData(id, startDate)
        Server->>Server: requireSession(event) → session.teamId
        Server->>Server: id / startDate (YYYY-MM-DD) を validate
        Server->>DDB: DeleteItem<br/>pk=TEAM#{teamId}, sk=ASN#{startDate}#{id}
        DDB-->>Server: 200 (idempotent、存在しなくても OK)
        Server-->>SK: success → invalidate
        SK->>SK: load 再実行 → AssignmentManager の dbAssignments 更新
        SK-->>User: 行が消える + timeline からも帯が消える
    end

設計判断

エラーケース

既知の制約 (PR-G 時点)


UC-06: 人 / 案件を削除する (cascade)

概要

Resource (人) または Project (案件) を削除すると、関連する Assignment も 原子的に同時削除 される (ADR 0006)。 ResourceManager / ProjectManager に「N 件のアサイン」と関連件数を表示、削除確認ダイアログでも件数を明示。

アクター / 前提条件

対応コード

Mermaid sequence (Resource 削除)

sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server as +page.server.ts
    participant Repo as repository.deleteResource
    participant DDB as DynamoDB

    Note over SK: 一覧モーダルで「N 件のアサイン」と件数表示
    User->>SK: 「削除」ボタン
    SK->>SK: confirm("「{name}」と関連 N 件のアサインを削除しますか?")
    alt キャンセル
        SK-->>User: 何もしない
    else OK
        SK->>Server: POST ?/deleteResource<br/>FormData(id)
        Server->>Repo: deleteResource(teamId, id)
        Repo->>DDB: Query<br/>pk=TEAM#X AND begins_with(sk, "ASN#")<br/>FilterExpression: resourceId == id
        DDB-->>Repo: [Assignment SK 一覧]
        alt total > 100
            Repo-->>Server: throw Error("exceeds 100 items")
            Server-->>SK: 500 → form action error
        else total ≤ 100
            Repo->>DDB: TransactWriteItems<br/>{ Delete: Resource } + N×{ Delete: Assignment }<br/>(原子的)
            DDB-->>Repo: 200
            Repo-->>Server: void
            Server-->>SK: success → invalidate
            SK->>SK: load 再実行 → resources / assignments 更新
            SK-->>User: 行が消える + timeline からも該当帯が消える
        end
    end

Project 削除も同形 (FilterExpression が projectId == id に変わるだけ)。

設計判断 (ADR 0006)

エラーケース

既知の制約 (PR-H 時点)


ユースケース追加のテンプレ

新規ユースケース追加時のコピペ用:

## UC-NN: <短い動詞句>

### 概要
1-2 文。

### アクター / 前提条件
- アクター:
- 前提条件:

### 対応コード
- 画面:
- Action / Loader:
- 検証 schema:
- DB アクセス:

### Mermaid sequence
\`\`\`mermaid
sequenceDiagram
    actor User
    participant SK as SvelteKit (browser)
    participant Server
    participant DDB as DynamoDB
    User->>SK: ...
    SK->>Server: ...
\`\`\`

### エラーケース
- ...