書類提出 — DocumentSubmission
これは何か
サークルが実際に書類を提出し、運営スタッフが審査する流れ全体を管理します。
書類定義(DocumentType)がひな形なら、書類提出(DocumentSubmission)はそのひな形に対してサークルが記入して送ってきた実体です。
提出の状態遷移
NOT_SUBMITTED → PENDING → APPROVED
↓
REJECTED
| ステータス | 意味 |
|---|---|
NOT_SUBMITTED | まだ提出されていない |
PENDING | 提出済み。承認待ち。 |
APPROVED | すべての承認ステージを通過した。 |
REJECTED | 運営に却下された。修正して再提出が必要。 |
バージョンと審査の関係
書類は「バージョン」単位で管理されます。サークルが修正して再提出するたびにバージョンが上がります。
- 審査は常に最新バージョンに対して行われます
- 過去のバージョンは履歴として保持されます
- 却下されたバージョンのファイルも削除しません
各バージョンには4種類の状態があります。
| 状態 | 意味 |
|---|---|
PENDING | 審査待ち |
APPROVED | 承認された |
REJECTED | 却下された |
REVISION_REQUESTED | 修正依頼が出た |
多段階承認の仕組み
DocumentTypeに複数の承認ステージが定義されている場合、1段階目のステージが承認されると2段階目に進みます。すべてのステージを通過して初めてステータスが APPROVED になります。
DocumentApprovalRecord は「誰が・いつ・どのバージョンに対して・どのステージで・どんな判断をしたか」を記録する監査ログです。
承認・却下の取り消し
運営スタッフが承認または却下を誤った場合は、最新の有効な提出バージョンに対する直近の審査操作を取り消せます。対象ステージの requiredRoles を満たすスタッフだけが操作できます。
POST /api/v1/document-submissions/{submission_id}/approval-records/{approval_record_id}/cancel
{
"reason": "誤って承認したため"
}
- 中間ステージの承認を取り消すと、提出状態は
PENDINGのままcurrentStageが対象ステージへ戻ります。 - 最終承認を取り消すと、提出と最新バージョンを
APPROVEDからPENDINGへ戻し、バージョンの承認者と承認日時をクリアします。 - 却下は、企画メンバーが新しい再提出バージョンを一度も作成していない場合に限り取り消せます。提出を
PENDINGに戻し、currentStageを却下した段階へ、最新バージョンのapprovalStatusをPENDINGへ復元してrejectionReasonをクリアします。 - 却下を取り消しても、先行ステージの有効な承認は維持します。
- 承認・却下記録は削除せず、
cancelledAt、cancelledById、cancellationReasonを監査履歴として保持します。元のコメントや却下理由も変更しません。 - 状態計算では
cancelledAt IS NULLの承認・却下記録だけを有効として扱います。 User.groupsのロール判定は、カンマ区切りのグループ名を分割して完全一致で行います。
管理画面では、取消条件を満たす直近の記録に対して「承認を取り消す」または「却下を取り消す」を表示します。確認モーダルで対象ステージを示し、必須の取消理由を入力して実行すると、提出詳細を再取得して復元後の審査状態と取消情報を含む履歴を表示します。
提出の取り下げと再提出の取り消し
企画メンバーは、審査が始まっていない最新バージョンを次のAPIで取り下げられます。
POST /api/v1/document-submissions/{submission_id}/withdraw
{
"reason": "誤ったファイルを再提出したため"
}
リクエストボディと reason は省略できます。
- 初回提出を取り下げた場合は
NOT_SUBMITTEDに戻ります。従来どおり提出期限後は実行できません。 - 再提出を取り消した場合は、直前の取消済みでないバージョンを再び有効にし、その内容・提出日時・審査状態を復元します。この操作は提出期限後も実行できます。
- 復元元が
APPROVEDなら提出状態もAPPROVED、REJECTEDまたはREVISION_REQUESTEDならREJECTEDに戻ります。 - ファイルとフリーテキストはどちらもバージョンとして保存されます。フリーテキストの現在値は有効バージョンと同期します。
- 取り消したバージョンには
cancelledAt、cancelledById、cancellationReasonを記録し、行とR2上のファイルは削除しません。 - 最新バージョンに
cancelledAt IS NULLの承認・却下記録がある場合は取り消せません。 - 各提出で
isActive = trueのバージョンは常に1件以下です。
誰が使うか
- サークル:書類をアップロードして提出する。却下されたら修正して再提出する。
- 運営スタッフ:提出された書類を確認して承認または却下する。
できなければならないこと
- サークルがファイルをアップロードして書類を提出できる(DocumentSubmissionVersion が作られる)
- サークルがテキストを入力して書類を提出できる(acceptsFreetext の場合。DocumentSubmissionVersion が作られる)
- 承認ステージに対応した権限を持つ運営スタッフが提出を承認または却下できる
- 運営スタッフが却下理由(rejectionReason)を記録できる
- 却下されたらサークルが修正した書類を再提出できる(バージョンが上がる)
- 運営スタッフが全サークルの提出状況を一覧で確認できる
- 承認記録(DocumentApprovalRecord)が誰がいつ何に対して判断したかを残す
できてはいけないこと
- 提出期限(deadline)を過ぎた後、
lateSubmissionPolicy = NONEの書類を初回提出すること - 提出期限を過ぎた後、
lateSubmissionPolicy = RESUBMISSION_ONLYの書類を初回提出すること(再提出は可) - 審査が始まった最新の再提出をサークルが取り消すこと
- 現在の承認ステージよりも先のステージを審査すること(ステージは順番に進む)
- 審査権限のないユーザーが書類を承認・却下すること
- アップロードされたファイルを、許可された拡張子(allowedExtensions)以外のもので提出すること
- ファイルサイズが上限(maxFileSize)を超えるファイルを提出すること
- 提出記録や承認記録を物理削除すること(すべて履歴として保持する)
- サークルが他のサークルの書類を閲覧・操作すること