コンテンツにスキップ

ReDPL 機能仕様書

このシステムが「何を、どう動かすものか」を全部書いた文書です。

目指しているのは「仕様書に載っていない挙動が存在しない」状態です。 画面・操作・メッセージ・状態の変わり方を、ひとつ残らず書き出します。

この文書の決まりごと

  • コードが唯一の正解です。思い出や過去のやりとりではなく、いまのコードと テストを読んで書いています。コードと文書が食い違っていたら、 文書の方を直す(または、おかしいのがコードなら 09 に 「バグ候補」として載せる)ことにしています。
  • 専門用語はできるだけ使いません。やむを得ず使うときは 用語集 に載せます。
  • ルールには「なぜそうなっているか」を一文添えます。 理由が分からない決まりは、後から誰かが善意で壊してしまうためです。
  • メッセージは画面に出るとおりの文言で書きます。言い換えません。

目次

章 内容
01 概要 何のためのシステムか/4 種類の利用者/用語集
02 共通ルール 法人と事業所の考え方/権限/日付と時刻/表記/入力チェック/初回パスワード変更
03 画面仕様 全画面。URL・入力項目・ボタン・メッセージ・遷移先・使う API
04 業務ルール 応募と確定/限定公開/打刻/勤怠の承認/無断欠勤/課金/招待リンク など
05 状態の移り変わり 応募・勤怠・お仕事・招待リンク・法人/事業所・アカウント
06 権限一覧 全 API・全操作 × 利用者の種類
07 メッセージ一覧 画面に出る全文言と、出る条件
08 メール 送るきっかけ・宛先・本文の要点・検証環境の送信制限
09 未対応・保留 まだ決まっていないこと、見送ったこと、バグ候補
10 業務の流れ 契約から請求までの全体図。だれが・どの順で・なぜ行うか

Web で読む

GitHub の画面でもそのまま読めます(mermaid の図も描画され、章どうしの リンクも踏めます)。検索や目次が欲しいときは、サイトとして書き出せます。

source venv/bin/activate
pip install -r requirements-docs.txt   # 初回だけ
./scripts/docs_site.sh serve           # http://127.0.0.1:8001
コマンド すること
./scripts/docs_site.sh serve 手元で見る。ファイルを直すと自動で読み込み直します
./scripts/docs_site.sh build site/ に書き出す(git 管理外)
./scripts/docs_site.sh check リンク切れと見出しアンカーだけ検査する

Markdown が正本で、サイトはそれを読む形に変えただけです。 サイト側にしか無い文章は作らないでください(二重管理になり、 必ずどちらかが腐ります)。設定は repo 直下の mkdocs.yml です。

リンク切れは検査で落とします。 strict: true にしてあるので、 存在しないファイルや見出しへのリンクがあると build / check が失敗します。 章をまたぐリンクは数が多く、手では追いきれないためです。

図は閲覧時に mermaid を CDN(unpkg)から読み込みます。 インターネットに出られない場所で見るときは、mkdocs.yml の mermaid2 に手元の mermaid.min.js を指定してください。

業務の流れとの相互リンク

10 業務の流れ は各段階から画面仕様へリンクしています。 その逆リンク(画面仕様の末尾にある「業務の流れでの位置」)は 手で書かず、10 から作り直します。手で書くと、流れを直したときに 必ず片方が古くなるためです。

python manage.py spec_backlinks --write

区画は <!-- spec-backlinks:start --> で囲んであります。 手で書き換えても、次の生成で消えます。

流れに出てこない画面(一覧・ダッシュボード・ログインなど)は そのままで構いません。業務の段階として描くものが無いためです。

画面キャプチャについて

画像は docs/spec/images/ に置き、手で撮らずスクリプトで撮り直せるように しています。手で撮ると、画面を直したときに貼り替え漏れが必ず出るためです。

./scripts/e2e_backend.sh                      # 裏側 (:8000)
cd frontend && npm run dev -- --port 3100     # 画面 (:3100)
cd frontend && npm run docs:capture           # 撮影

撮影の条件は固定してあります。条件が揺れると、画面を直していないのに 画像だけ変わって差分が読めなくなるためです。

項目 値 なぜ
PC 画面の大きさ 1440 × 900 一般的なノート PC の作業領域
スタッフ画面の大きさ 390 × 844 スタッフはスマートフォンで使う前提
時刻 2026-10-06 10:15 (日本時間) に固定 「現在時刻」の表示が毎回変わらないようにする
表示するデータ manage.py seed_docs が作るもの 一覧が空の画像では何も伝わらないため

画像のファイル名は 画面ID_内容_状態.png です (例 C-05_job-detail_normal.png)。状態は normal / empty / error / dialog / loading を使います。

撮影用のデータについて

manage.py seed_docs が作ります。氏名は実在しない一般的な組み合わせ、 メールアドレスは @example.test(テスト用に予約されたドメイン)、 電話番号は 090-0000-xxxx で、実在の個人情報は使っていません。

このコマンドは、パスワードがこのリポジトリに書いてある管理者アカウントを 作るため、次の 3 つがすべて揃わないと動きません。検証環境や本番で うっかり実行されると、誰でも入れる管理者ができてしまうためです。

  1. ALLOW_SEED_E2E=true
  2. DEBUG=True
  3. データベースの接続先が手元のもの

書き漏らしの検査

docs/spec/ に載っていない項目があると、テストが失敗します。

python manage.py spec_inventory                        # いま何件あるか
python manage.py test core.common.tests.test_spec_coverage   # 漏れを検査
SPEC_COVERAGE_REPORT_ONLY=1 python manage.py test core.common.tests.test_spec_coverage
                                                       # 失敗させず残り件数だけ見る

検査する対象は 4 つです。

対象 仕様書に何があれば「載っている」とみなすか
画面の URL その URL の文字列
API と追加操作 その URL、または ViewSet名.操作名
状態の選択肢 モデル.項目 の見出しと、全選択肢の値が同じファイルにある
画面の文言 その文言そのまま

意図的に載せないものは tools/coverage_allowlist.json に 理由付きで書きます。理由の無い除外は認めません (「とりあえず黙らせた」が積み上がると検査の意味が無くなるためです)。

検査は 有効(_enforce: true) です。画面・API・状態・文言を足したら、 仕様書にも書くまでテストが落ちます。

文言の検査が見ている範囲

文言は置き場所を 2 つに決めてあり、検査はその中身を全部見ます。

置き場所 何が入るか
frontend/lib/constants/messages.ts 画面が出すメッセージ
frontend/lib/constants/、frontend/lib/forms/ ボタン名・状態名・入力チェックの文言
core/common/messages.py サーバが返すメッセージ

画面のファイルやサーバの view に直接書くことは禁止で、 書くと専用の検査が落ちます (frontend/lib/utils/uiText.test.ts、core/common/tests/test_message_sources.py)。

何を「メッセージ」と見なすか

ここが線引きです。操作に対する返事だけを集めます。 見出しやラベルは「その画面の一部」なので対象外です。

定数にする(メッセージ) そのまま書いてよい(画面の一部)
通知(トースト) 画面の見出しと説明(PageHeader)
確認ダイアログの見出し・本文・実行ボタン 入力項目のラベル
操作の成功・失敗の文言 表の列名、メニュー名、タブ名
入力欄の下に出すエラー 入力例(プレースホルダー)
通信に失敗したときの控えの文言 空状態の文言(lib/constants/ui.ts にあります)
サーバが返す message と検証エラー モデルの項目名・説明、ログ出力

迷ったときの目安は「その文字を消しても画面が成り立つか」です。 成り立つなら見出し・ラベル(対象外)、成り立たない=操作の結果が 分からなくなるならメッセージ(定数にする)。