コンテンツにスキップ

設問 API

セクション配下の設問を管理するエンドポイント。選択肢・マトリクスの行列・FA 欄・サブ設問・分岐ルール・表示ロジックは、すべて設問の更新でまとめて設定します。

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

メソッド

HTTP メソッド

メソッド URI 概要
POST /api/sections/{sectionId}/questions 設問追加
PATCH /api/questions/{questionId} 設問更新
DELETE /api/questions/{questionId} 設問削除
POST /api/questions/{questionId}/duplicate 設問複製
POST /api/questions/import 設問流用

リソース定義

設問タイプ

タイプ 値 説明
SA single 単一回答
MA multi 複数回答
FA free_text 自由回答(テキスト入力)
TM matrix テキストマトリクス(行 × 列)
PD pulldown プルダウン選択
提示ステップ intro 回答欄を持たない説明文

設問スキーマ

フィールド データ型 備考
id string スナップショット行の UUID。版が変わると変化する
code string 設問コード。分岐条件・分岐先の参照キー。案件内で一意
questionType enum 設問タイプ
promptText string 設問文
noteText string 注記
isRequired boolean 回答必須かどうか
isLinkedToPrevious boolean 前の設問と同じページに表示するか
sortOrder number セクション内での並び順
options QuestionOption[] 選択肢(FA では入力欄)
matrixRows QuestionOption[] マトリクスの行
matrixColumns QuestionOption[] マトリクスの列
isSingleMatrixSelect boolean | null マトリクスの各行で 1 つだけ選ばせるか
minSelections number | null MA の最小選択数。null = 制限なし
maxSelections number | null MA の最大選択数。null = 制限なし
freeTextFields FreeTextField[] FA の入力欄(ラベル・プレースホルダ・欄ごとの必須)
subQuestions SubQuestion[] サブ設問(ラベル + 選択肢)
branchRules QuestionBranchRule[] 分岐ルール
visibilityRules QuestionVisibilityRule[] 表示ロジック

QuestionOption

フィールド データ型 備考
id string UUID
label string 選択肢ラベル。分岐条件の比較値として参照される
isExclusive boolean 排他選択肢(選ぶと他が選べなくなる)
allowOtherInput boolean 「その他」の自由入力欄を表示する
isNotApplicable boolean 「当てはまるものはない」の特殊選択肢
axis enum | null row / column(マトリクスのみ)
placeholder string | null 入力欄のプレースホルダ(FA のみ)
fieldIsRequired boolean | null 欄ごとの必須(FA のみ)

QuestionBranchRule

フィールド データ型 備考
logicalOperator enum AND / OR
conditions BranchCondition[] 条件の配列
destinationQuestionCode string 分岐先の設問コード。SO / SC / SX の特殊コードも指定できる
message string | null 条件成立時に表示するメッセージ。分岐先が自設問のときは排他設定として機能する

BranchCondition

フィールド データ型 備考
sourceQuestionCode string 参照元の設問コード
operator enum equals / includes / not_includes / only / not_only / has_other / answered
value string 比較値。選択肢ラベル、マトリクスの行ラベル、FA の照合テキスト
subValue string | null マトリクスの列ラベル、FA の対象欄ラベル。null = いずれかの欄
subQuestionIndex number | null サブ設問の位置。null = 全サブ設問をフラットに扱う

QuestionVisibilityRule

フィールド データ型 備考
logicalOperator enum AND / OR
conditions BranchCondition[] 分岐条件と同じ構造
targets VisibilityTarget[] 非表示にする対象(label / axis / subQuestionIndex)

認証要件

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

設問追加

概要

セクションの末尾に設問を追加します。

URI

POST /api/sections/{sectionId}/questions
パラメータ データ型 必須 備考
sectionId string ◯ セクションの UUID

リクエストボディ

{
  "code": "Q1",
  "questionType": "multi",
  "promptText": "以下のうち、知っているブランドをすべてお選びください。",
  "isRequired": true,
  "isLinkedToPrevious": false,
  "options": [
    { "label": "ブランド A", "isExclusive": false, "allowOtherInput": false, "isNotApplicable": false },
    { "label": "いずれも知らない", "isExclusive": true, "allowOtherInput": false, "isNotApplicable": false }
  ],
  "minSelections": 1,
  "maxSelections": 3
}

バリデーションルール

フィールド ルール
code 必須。文字列(設問コード)
questionType 必須。single / multi / free_text / matrix / intro / pulldown
promptText 必須。文字列
isRequired 任意。既定は false
isLinkedToPrevious 任意。既定は false
options 任意。label / isExclusive / allowOtherInput / isNotApplicable
matrixRows / matrixColumns 任意。マトリクスの行・列
isSingleMatrixSelect 任意。真偽値
minSelections / maxSelections 任意。1 以上の整数または null
freeTextFields 任意。label / placeholder / isRequired
subQuestions 任意。label / options

レスポンス(201 Created)

追加された設問スキーマを返します。

例外処理

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

処理フロー

  1. セクションから所属案件を特定し、edit 権限を確認する
  2. セクション内の末尾の並び順を求める
  3. 設問を挿入する
  4. 選択肢・マトリクス行列・FA 欄・サブ設問の選択肢を survey_version_question_options に挿入する

設問更新

概要

設問を更新します。設問文などの属性に加えて、選択肢・分岐ルール・表示ロジックもこの API で設定 します。

配列項目(options / matrixRows / matrixColumns / freeTextFields / subQuestions / branchRules / visibilityRules)は 指定した内容で全置換 されます。指定しなかった項目は変更されません。

URI

PATCH /api/questions/{questionId}
パラメータ データ型 必須 備考
questionId string ◯ 設問の UUID

リクエストボディ

{
  "promptText": "あなたの性別をお答えください。",
  "isRequired": true,
  "options": [
    { "label": "男性", "isExclusive": false, "allowOtherInput": false, "isNotApplicable": false },
    { "label": "女性", "isExclusive": false, "allowOtherInput": false, "isNotApplicable": false }
  ],
  "branchRules": [
    {
      "logicalOperator": "AND",
      "conditions": [
        { "sourceQuestionCode": "Q1", "operator": "equals", "value": "男性" }
      ],
      "destinationQuestionCode": "Q5"
    }
  ],
  "visibilityRules": []
}

バリデーションルール

フィールド ルール
code 任意。設問コード
questionType 任意。設問タイプ
promptText 任意。文字列
noteText 任意。文字列
isRequired / isLinkedToPrevious 任意。真偽値
sortOrder 任意。整数
options / matrixRows / matrixColumns 任意。全置換
minSelections / maxSelections 任意。1 以上の整数または null。null で制限解除。設問タイプを multi 以外に変更すると破棄される
freeTextFields / subQuestions 任意。全置換
branchRules / visibilityRules 任意。全置換。参照元に intro 設問を指定するとエラー

レスポンス(200 OK)

更新後の設問スキーマを返します。

例外処理

説明 ステータスコード ステータス名
リクエストボディが不正 400 Bad Request
分岐条件の参照元に提示ステップ(intro)を指定した 400 Bad Request
設問が存在しない、または edit 権限がない 404 Not Found

処理フロー

シーケンス図

sequenceDiagram
    participant Client
    participant API
    participant DB

    Client->>API: PATCH /api/questions/{questionId}
    API->>API: edit 権限を確認
    API->>API: 分岐・表示ロジックの条件を検証
    alt 参照元が intro 設問
        API-->>Client: 400 Bad Request
    else
        API->>DB: 設問の属性を更新
        API->>DB: 選択肢・行列・FA 欄・サブ設問を全置換
        API->>DB: 分岐ルール・表示ロジックを全置換
        API-->>Client: 200 OK
    end

選択肢の ID は保持されない

配列項目は毎回削除して作り直されるため、選択肢の id は更新のたびに変わります。分岐条件が選択肢を ラベル文字列 で参照しているのはこのためです。

設問削除

概要

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

URI

DELETE /api/questions/{questionId}

レスポンス(200 OK)

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

例外処理

説明 ステータスコード ステータス名
設問が存在しない、または edit 権限がない 404 Not Found

他の設問が参照している分岐は自動修正されない

削除した設問を分岐先に指定していたルールは、frontend 側で無効な分岐先として検出され、自動修正されます。

削除後に設問コードが振り直される

frontend は削除の直後に 設問コードの振り直し を呼び出します。欠番が生まれないよう案件全体のコードが連番に整えられ、分岐・表示ロジックの参照も付け替えられます。

設問複製

概要

設問を複製し、同じセクションの末尾に追加します。

設問コードは案件内で重複しないよう振り直され、自設問を参照していた分岐条件・分岐先は新しいコードへ付け替え られます。他の設問への参照はそのまま残ります。

URI

POST /api/questions/{questionId}/duplicate

レスポンス(201 Created)

複製された設問スキーマを返します。

例外処理

説明 ステータスコード ステータス名
設問が存在しない、または edit 権限がない 404 Not Found

処理フロー

  1. 設問から所属案件を特定し、edit 権限を確認する
  2. 設問と配下の選択肢・分岐ルール・表示ロジックを読み込む
  3. 案件内の既存設問コードを集め、衝突しない新しいコードを決める
  4. 分岐条件の参照元・分岐先のうち、複製元の設問コードを指しているものを新しいコードへ付け替える
  5. セクションの末尾に設問を挿入する

設問流用

概要

質問ライブラリ、または他案件の設問を、指定したセクションの末尾へ取り込みます。

流用元の指定方法は 2 通りあり、いずれかが必須です。

指定方法 必要なフィールド
質問ライブラリ経由 libraryItemId
案件を直接指定 sourceSurveyId + sourceSectionId + sourceQuestionId の 3 点セット

URI

POST /api/questions/import

リクエストボディ

{
  "targetSectionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "libraryItemId": "…"
}

バリデーションルール

フィールド ルール
targetSectionId 必須。取り込み先セクションの UUID
libraryItemId 質問ライブラリの UUID。3 点セットを使わない場合は必須
sourceSurveyId 流用元の案件 UUID。3 点セットで指定する場合は必須
sourceSectionId 流用元のセクション UUID。同上
sourceQuestionId 流用元の設問 UUID。同上

libraryItemId か、sourceSurveyId + sourceSectionId + sourceQuestionId のいずれかが必要です。

レスポンス(201 Created)

取り込まれた設問スキーマを返します。

例外処理

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

処理フロー

シーケンス図

sequenceDiagram
    participant Client
    participant API
    participant DB
    participant Library as 質問ライブラリ

    Client->>API: POST /api/questions/import
    API->>API: 取り込み先の edit 権限を確認
    alt libraryItemId 指定
        API->>Library: ライブラリ項目を取得
        alt 内部由来
            API->>DB: 元案件のスナップショットから構築
        else 外部由来
            API->>API: 正規化ペイロードから構築
        end
    else 3 点セット指定
        API->>DB: 元案件のスナップショットから構築
    end
    API->>API: 設問コードを一意に振り直す
    API->>DB: セクション末尾に挿入
    API-->>Client: 201 Created

流用元別の挙動:

  • 質問ライブラリ(内部由来): 元案件が存在すれば view 権限を要求する。元案件が削除済みでもスナップショット行が残っていれば流用を許可する
  • 質問ライブラリ(外部由来): 正規化ペイロードから構築する。マトリクスのサブ項目は保持先がないため注記テキストへ出力する
  • 案件を直接指定: 元案件の view 権限を確認し、スナップショットから構築する

分岐は引き継がれない

質問ライブラリ経由の流用では、分岐ルール・表示ロジックは引き継がれません。