コンテンツにスキップ

セクション API

調査票のセクション(大問)を管理するエンドポイント。

セクションは案件そのものではなく 最新版のスナップショット に属します。追加・更新・削除はすべて最新版に対して行われ、過去の版は変更されません。

認証・レスポンス形式・エラーの扱いは API 定義 を参照。

メソッド

HTTP メソッド

メソッド URI 概要
POST /api/surveys/{surveyId}/sections セクション追加と初期案生成
PATCH /api/sections/{sectionId} セクション更新
DELETE /api/sections/{sectionId} セクション削除
POST /api/sections/{sectionId}/duplicate セクション複製
POST /api/sections/import セクション流用
POST /api/sections/import-from-external 外部由来から 1 セクション一括挿入

リソース定義

セクションスキーマ

フィールド データ型 備考
id string スナップショット行の UUID。版が変わると変化する
title string セクションタイトル
description string 説明
sortOrder number 版の中での並び順
generatedBy string 生成元。manual / 類似セクション生成 など
questionCount number 設問数
pageCount number ページ数(前の設問と結合された設問を束ねた数)
questions Question[] 設問一覧
updatedAt string ISO 8601

認証要件

x-user-email / x-user-name ヘッダによるユーザー認証が必要です。すべての操作に対象案件の edit 権限が必要で、流用時は流用元案件の view 権限も必要です。権限がない場合は 404 Not Found を返します。

セクション追加と初期案生成

概要

案件の最新版にセクションを追加します。追加時にタイトルから 設問案が自動生成 され、生成された設問コードは案件内で重複しないよう振り直されます。

URI

POST /api/surveys/{surveyId}/sections
パラメータ データ型 必須 備考
surveyId string ◯ 案件の UUID

リクエストボディ

{
  "title": "スクリーニング",
  "description": ""
}

バリデーションルール

フィールド ルール
title 必須。文字列
description 任意。省略時は「新規追加セクション」

レスポンス(201 Created)

追加されたセクションスキーマを返します。

例外処理

説明 ステータスコード ステータス名
リクエストボディが不正 400 Bad Request
案件が存在しない、または edit 権限がない 404 Not Found

処理フロー

シーケンス図

sequenceDiagram
    participant Client
    participant API
    participant DB

    Client->>API: POST /api/surveys/{surveyId}/sections
    API->>API: edit 権限を確認
    API->>DB: 最新版 ID と既存セクションを取得
    API->>API: タイトルから設問案を生成
    API->>API: 既存の設問コードと衝突しないよう振り直す
    API->>DB: 末尾の並び順でセクションを挿入
    API-->>Client: 201 Created

セクション更新

概要

セクションのタイトル・説明・並び順を更新します。

sortOrder を変更すると、その位置にいたセクションと入れ替え られます。(版 ID, 並び順) の一意制約に違反しないよう、一時的な並び順を経由して入れ替えます。

URI

PATCH /api/sections/{sectionId}
パラメータ データ型 必須 備考
sectionId string ◯ セクション(スナップショット行)の UUID

リクエストボディ

{
  "title": "スクリーニング",
  "description": "",
  "sortOrder": 2
}

バリデーションルール

フィールド ルール
title 任意。文字列
description 任意。文字列
sortOrder 任意。整数。移動先の並び順

レスポンス(200 OK)

更新後のセクションスキーマを返します。

例外処理

説明 ステータスコード ステータス名
リクエストボディが不正 400 Bad Request
セクションが存在しない、または edit 権限がない 404 Not Found

処理フロー

  1. セクションから所属案件を特定し、edit 権限を確認する
  2. sortOrder が指定され、かつ現在値と異なる場合:
    1. 移動先の並び順にいるセクションを検索する
    2. 対象セクションを一時的な並び順に退避する
    3. 移動先にいたセクションを元の並び順へ移す
    4. 対象セクションを移動先の並び順に設定する
  3. title / description を更新する

セクション削除

概要

セクションを削除します。配下の設問・選択肢・分岐ルール・表示ロジックも連鎖的に削除されます(物理削除)。

URI

DELETE /api/sections/{sectionId}

レスポンス(200 OK)

{ "ok": true, "data": { "deleted": true } }

例外処理

説明 ステータスコード ステータス名
セクションが存在しない、または edit 権限がない 404 Not Found

案件の削除とは異なる

案件は論理削除ですが、セクション・設問は最新版のスナップショットに対する物理削除です。過去の版のスナップショットは残っているため、ロールバックで復元できます。

セクション複製

概要

セクションを設問ごと複製し、最新版の末尾に追加します。設問コードは案件内で重複しないよう振り直されます。

URI

POST /api/sections/{sectionId}/duplicate

レスポンス(201 Created)

複製されたセクションスキーマを返します。

例外処理

説明 ステータスコード ステータス名
セクションが存在しない、または edit 権限がない 404 Not Found

処理フロー

  1. セクションから所属案件を特定し、edit 権限を確認する
  2. セクションと配下の設問・選択肢・分岐ルール・表示ロジックを読み込む
  3. 設問コードを既存コードと衝突しないよう振り直す
  4. 末尾の並び順で新しいセクションとして挿入する

自設問への参照は付け替えられる

複製元の設問を指していた排他設定などの参照は、複製後の設問コードへ付け替えられます。

セクション流用

概要

他案件のセクション を設問ごと自案件へ取り込みます。

URI

POST /api/sections/import

リクエストボディ

{
  "sourceSurveyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sourceSectionId": "…",
  "targetSurveyId": "…"
}

バリデーションルール

フィールド ルール
sourceSurveyId 必須。流用元の案件 UUID
sourceSectionId 必須。流用元のセクション UUID
targetSurveyId 必須。流用先の案件 UUID

レスポンス(201 Created)

流用先に作成されたセクションスキーマを返します。

例外処理

説明 ステータスコード ステータス名
リクエストボディが不正 400 Bad Request
流用元または流用先が存在しない、権限がない 404 Not Found

処理フロー

流用元のセクションは次の順で探索されます。版をまたいで ID が変化するため、複数の経路を用意しています。

  1. 流用先案件の edit 権限、流用元案件の view 権限を確認する
  2. 流用元の最新版から sourceSectionId を検索する(通常の経路)
  3. 見つからない場合、安定 ID(stableSectionId)を使って最新版から検索する
  4. それでも見つからない場合、スナップショット行を直接読み込む
  5. 設問コードを流用先で一意になるよう振り直す
  6. 流用先の最新版の末尾にセクションを挿入する

シーケンス図

sequenceDiagram
    participant Client
    participant API
    participant DB

    Client->>API: POST /api/sections/import
    API->>API: 権限を確認 (流用先 edit / 流用元 view)
    API->>DB: A. 最新版から sectionId を検索
    alt 見つからない
        API->>DB: B. 安定 ID で最新版を検索
        alt 見つからない
            API->>DB: C. スナップショット行を直接読み込む
        end
    end
    API->>API: 設問コードを一意に振り直す
    API->>DB: 流用先の末尾に挿入
    API-->>Client: 201 Created

権限チェックの迂回

経路 C(スナップショット直読み)は権限チェックを通らない既知の問題があります(インフラストラクチャ)。

外部由来から 1 セクション一括挿入

概要

CS から取り込んだ調査票の設問(質問ライブラリの外部由来データ)を複数選び、1 つの新しいセクションとしてまとめて挿入します。

セクション候補は 取り込み API のセクション候補プレビューで取得します。

URI

POST /api/sections/import-from-external

リクエストボディ

{
  "targetSurveyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "libraryItemIds": ["…", "…"],
  "sectionTitle": "スクリーニング",
  "sectionDescription": ""
}

バリデーションルール

フィールド ルール
targetSurveyId 必須。UUID 形式
libraryItemIds 必須。UUID の配列、1 件以上。配列の順序が設問の並び順になる
sectionTitle 必須。1〜255 文字
sectionDescription 任意。省略時は空文字

レスポンス(201 Created)

作成されたセクションスキーマを返します。

例外処理

説明 ステータスコード ステータス名
リクエストボディが不正 400 Bad Request
挿入先の案件またはライブラリ項目が存在しない、権限がない 404 Not Found

処理フロー

  1. 挿入先案件の edit 権限を確認する
  2. libraryItemIds の質問ライブラリ項目を取得し、リクエストの順序を保持 して並べる
  3. 各項目から設問のペイロードを組み立てる
    • 外部由来: 正規化ペイロード(設問文・選択肢・サブ項目・サブ設問)から構築する
    • 内部由来: 元案件のスナップショットから構築する
  4. 設問コードを挿入先で一意になるよう振り直す
  5. 新しいセクションを作成し、設問をまとめて挿入する

分岐は引き継がれない

質問ライブラリには分岐ルール・表示ロジックが保存されていないため、流用後にあらためて設定する必要があります。