設問 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
| パラメータ | データ型 | 必須 | 備考 |
|---|---|---|---|
| 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 |
処理フロー
- セクションから所属案件を特定し、
edit権限を確認する - セクション内の末尾の並び順を求める
- 設問を挿入する
- 選択肢・マトリクス行列・FA 欄・サブ設問の選択肢を
survey_version_question_optionsに挿入する
設問更新
概要
設問を更新します。設問文などの属性に加えて、選択肢・分岐ルール・表示ロジックもこの API で設定 します。
配列項目(options / matrixRows / matrixColumns / freeTextFields / subQuestions / branchRules / visibilityRules)は 指定した内容で全置換 されます。指定しなかった項目は変更されません。
URI
| パラメータ | データ型 | 必須 | 備考 |
|---|---|---|---|
| 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
レスポンス(200 OK)
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
設問が存在しない、または edit 権限がない |
404 | Not Found |
他の設問が参照している分岐は自動修正されない
削除した設問を分岐先に指定していたルールは、frontend 側で無効な分岐先として検出され、自動修正されます。
削除後に設問コードが振り直される
frontend は削除の直後に 設問コードの振り直し を呼び出します。欠番が生まれないよう案件全体のコードが連番に整えられ、分岐・表示ロジックの参照も付け替えられます。
設問複製
概要
設問を複製し、同じセクションの末尾に追加します。
設問コードは案件内で重複しないよう振り直され、自設問を参照していた分岐条件・分岐先は新しいコードへ付け替え られます。他の設問への参照はそのまま残ります。
URI
レスポンス(201 Created)
複製された設問スキーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
設問が存在しない、または edit 権限がない |
404 | Not Found |
処理フロー
- 設問から所属案件を特定し、
edit権限を確認する - 設問と配下の選択肢・分岐ルール・表示ロジックを読み込む
- 案件内の既存設問コードを集め、衝突しない新しいコードを決める
- 分岐条件の参照元・分岐先のうち、複製元の設問コードを指しているものを新しいコードへ付け替える
- セクションの末尾に設問を挿入する
設問流用
概要
質問ライブラリ、または他案件の設問を、指定したセクションの末尾へ取り込みます。
流用元の指定方法は 2 通りあり、いずれかが必須です。
| 指定方法 | 必要なフィールド |
|---|---|
| 質問ライブラリ経由 | libraryItemId |
| 案件を直接指定 | sourceSurveyId + sourceSectionId + sourceQuestionId の 3 点セット |
URI
リクエストボディ
バリデーションルール
| フィールド | ルール |
|---|---|
| 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権限を確認し、スナップショットから構築する
分岐は引き継がれない
質問ライブラリ経由の流用では、分岐ルール・表示ロジックは引き継がれません。