Files
keinasystem/改善案/TODO管理機能仕様書案.md
2026-04-09 16:36:19 +09:00

19 KiB

TODO管理機能仕様書案

作成日: 2026-04-09 最終更新: 2026-04-09 対象プロジェクト: keinasystem 対象 Issue: akira/keinasystem#17 位置づけ: 実装前ドラフト(レビュー反映版)


1. 概要

繁忙期の作業を「どれから手を付けるか」の観点で整理するため、Redmine チケットライクな TODO 管理機能を追加する。

本機能は単なるメモではなく、以下の中間レイヤーとして位置付ける。

  • 計画
  • TODO
  • 実績

将来的には、作付け計画を除く各種計画について、計画 -> TODO -> 実績 の流れに挟める構造を目指す。 ただし MVP では、まず TODO 管理の基本機能、対象圃場の管理、計画との紐づけ、完了時の実績連携導線を整備する。


2. 背景

現状は施肥計画、田植え計画、運搬計画などの個別機能はあるが、「今日やること」「今週先に処理すべきこと」を横断的に管理する仕組みがない。

そのため、繁忙期には以下の問題が起こりやすい。

  • 作業の優先順位が頭の中や紙メモに依存する
  • 計画の一部だけを先に実行したい場合に管理しづらい
  • 実績入力までの間に「作業待ち」「着手中」の状態を置けない
  • 将来追加される作業系機能を共通の入口で扱えない

TODO 管理を導入し、計画単位ではなく「実際に動く作業単位」で優先順位と進行状態を管理できるようにする。


3. 目的

3.1 目指す状態

  • 未着手・進行中の作業を優先順で一覧できる
  • TODO は計画に紐づくものと、独立したものの両方を扱える
  • 計画に紐づく TODO では、計画全体ではなく一部圃場だけを対象にできる
  • 完了時に、必要なものは実績系アプリへ連携できる
  • 将来増える作業系アプリでも同じ TODO 基盤を使える

3.2 今回の対象

  • Django 新規アプリ apps/todos
  • Next.js 画面 frontend/src/app/todos
  • REST API /api/todos/
  • 計画画面からの TODO 生成導線

3.3 今回やらないこと

  • 期日通知、リマインダー、メール通知
  • 複数ユーザー割り当て
  • コメント、添付ファイル
  • 工数見積、実績時間記録
  • 完全な汎用ワークフローエンジン化

4. 基本方針

4.1 TODO の位置づけ

TODO は「作業指示」兼「実行待ちキュー」として扱う。

  • 計画は年間またはまとまり単位の設計情報
  • TODO は実際に動く単位の作業
  • 実績は実際に完了した事実

4.2 計画との関係

  • 1 計画に対して複数 TODO を紐づけられる
  • 1 TODO は複数計画を参照できる
  • ただし TODO の実際の対象圃場は TODO 側で明示管理する
  • 計画に含まれる圃場の一部だけを TODO 対象にすることを許可する

4.3 実績との関係

  • TODO 完了時に、実績アプリを持つ作業は実績生成の入口にする
  • ただし、すべての TODO が実績アプリを持つとは限らない
  • 計画なし TODO、実績なし TODO も許容する

4.4 圃場グループの扱い

圃場グループは独立モデル化しない。 既存の Field.group_name を参照用の属性として扱うにとどめ、TODO の正式な対象管理は圃場単位で保持する。

理由:

  • 現状のデータモデルに独立したグループモデルが存在しない
  • TODO 完了後に履歴の再現性を保つには、最終的に対象圃場を確定保持した方が安全

5. 機能スコープ

5.1 IN

  • TODO の作成、編集、削除
  • ステータス管理
  • 優先順位管理
  • 圃場単位の対象紐づけ
  • 作物、品種の補助的な分類紐づけ
  • 計画との紐づけ
  • 計画画面から TODO を生成
  • 完了済み、キャンセル済みの表示切り替え
  • 期日の強調表示
  • 並び替え API

5.2 OUT

  • 通知
  • 担当者管理
  • 承認フロー
  • 複数段階ステータス
  • 実績アプリ未実装領域の詳細実績入力 UI

6. 用語整理

用語 意味
TODO 実際に着手・進行・完了する作業単位
計画リンク TODO が参照する施肥計画、田植え計画など
対象圃場 その TODO で実際に作業対象となる圃場
実績連携 TODO 完了時に各実績アプリへ情報を渡すこと

7. データモデル方針

7.1 Todo

TODO 本体。

フィールド 必須 説明
id bigint PK
year integer 年度
title varchar(200) タイトル
description text 説明
status enum todo / doing / done / canceled
priority integer 小さいほど上位
due_date date 期日
work_type enum 作業種別
should_link_record boolean 完了時に実績連携導線を有効にするか
completed_at datetime 完了日時
canceled_at datetime キャンセル日時
created_at datetime
updated_at datetime

7.1.1 ステータス

  • todo: 未着手
  • doing: 進行中
  • done: 完了
  • canceled: キャンセル

7.1.2 並び順

  • 基本は FILO とする
  • 新規作成時は最上位へ入る
  • priority は 1000 刻みの整数で保存する
  • 初回作成時は最上位 TODO の priority - 1000 を新規 TODO に割り当てる
  • 一覧では priority 昇順で表示する
  • ユーザーが並び替えた後は、表示順に 1000, 2000, 3000... と振り直して保存する
  • 既存レコードの一括インクリメントや小数 priority は採用しない
  • 完了、キャンセル済みも priority は保持する
  • 一覧のデフォルト表示は todo / doing のみを priority 昇順で表示する

補足:

  • 1000 刻みは API の中間挿入余地ではなく、再採番時の可読性のために採用する
  • 並び順変更は常に表示対象全体を受け取って再採番する前提とする

7.1.3 作業種別

作業種別は「計画に対応するもの」と「計画に対応しないもの」の両方を含める。

初期案:

  • general: 一般
  • fertilization: 施肥
  • rice_transplant: 田植え
  • delivery: 運搬
  • levee_work: 畔塗
  • pesticide: 防除
  • other_recorded: 計画非紐づき実績系

補足:

  • 実装時点で将来の全計画種別を確定できない場合は、MVP では現行アプリに対応する種別を先行定義する
  • general はどれにも当てはまらない作業用に必須

7.2 TodoTargetField

TODO が実際に対象とする圃場。

フィールド 必須 説明
id bigint PK
todo FK(Todo) CASCADE
field FK(fields.Field) PROTECT
field_name_snapshot varchar(100) 保存時点の圃場名
group_name_snapshot varchar(50) 保存時点の group_name
created_at datetime
  • unique_together = ['todo', 'field']

方針:

  • TODO の対象管理は最終的に圃場単位で保持する
  • グループ、作物、品種から一括選択する UI は許可する
  • ただし保存時は対象圃場へ展開して保持する

7.3 TodoCrop / TodoVariety

TODO の分類補助用。

TodoCrop

フィールド 必須 説明
id bigint PK
todo FK(Todo) CASCADE
crop FK(plans.Crop) PROTECT
created_at datetime
  • unique_together = ['todo', 'crop']

TodoVariety

フィールド 必須 説明
id bigint PK
todo FK(Todo) CASCADE
variety FK(plans.Variety) PROTECT
created_at datetime
  • unique_together = ['todo', 'variety']

注意:

  • 対象圃場の実体は TodoTargetField を正とする
  • CropVariety だけ紐づいていて圃場が 0 件の TODO は許可する
  • これにより、圃場未確定の準備作業も登録できる

TODO と既存計画との紐づけ。

フィールド 必須 説明
id bigint PK
todo FK(Todo) CASCADE
plan_type enum 計画種別
fertilization_plan FK 施肥計画
rice_transplant_plan FK 田植え計画
delivery_plan FK 運搬計画
created_at datetime

方針:

  • 1 行に 1 種別のリンクだけを保持する
  • plan_type に応じて対応する FK だけを埋める
  • MVP は汎用 GenericForeignKey を使わず、明示 FK を優先する
  • 理由は API と serializer を単純に保ちやすいため

初期対象:

  • 施肥計画 FertilizationPlan
  • 田植え計画 RiceTransplantPlan
  • 運搬計画 DeliveryPlan
  • 畔塗 levee_work は MVP では「計画リンクなしで持てる work_type」として扱う
  • 将来、畔塗に計画モデルが導入された時点で TodoPlanLink に追加する

補足:

  • 作付け計画 Plan は「年内の計画情報」であり、TODO 生成元としては必須ではない
  • 当面は Issue 回答に合わせ、作付け計画以外のすべての計画 を TODO の対象候補とする

完了時の実績連携先を記録する索引。

フィールド 必須 説明
id bigint PK
todo FK(Todo) TODO
record_type enum 実績種別
work_record FK(workrecords.WorkRecord) 共通索引
spreading_session FK(fertilizer.SpreadingSession) 施肥実績
rice_transplant_record_id 将来 田植え実績
created_at datetime

方針:

  • 完了時に何へ連携したかを TODO 側から追えるようにする
  • todo は OneToOne に固定せず FK とする
  • 理由は 1 TODO から複数実績へ分割される可能性を残すため
  • 実績アプリが未実装の種別は空でよい
  • 将来の田植え実績導入時に拡張できる形にする

8. API 仕様案

8.1 一覧

  • GET /api/todos/

主な query:

  • status=todo,doing
  • include_closed=true|false
  • work_type=...
  • due=overdue|today|upcoming
  • year=2026

デフォルト:

  • include_closed=false
  • status=todo,doing
  • priority 昇順

8.2 詳細取得

  • GET /api/todos/{id}/

返却内容:

  • TODO 本体
  • 対象圃場
  • 作物、品種
  • 計画リンク
  • 完了連携状況

8.3 作成

  • POST /api/todos/

作成 payload 例:

{
  "title": "西田エリアの追肥",
  "description": "週内に先行実施",
  "status": "todo",
  "year": 2026,
  "due_date": "2026-04-12",
  "work_type": "fertilization",
  "should_link_record": true,
  "field_ids": [12, 18, 21],
  "crop_ids": [1],
  "variety_ids": [4],
  "plan_links": [
    {"plan_type": "fertilization", "plan_id": 8}
  ]
}

plan_links の吸収方針:

  • API 入力は plan_type + plan_id の組で受ける
  • Serializer で plan_type を見て対応 FK へ変換する
  • 例:
    • fertilization -> fertilization_plan_id
    • rice_transplant -> rice_transplant_plan_id
    • delivery -> delivery_plan_id
  • DB 返却時は、フロントエンド向けに再び plan_type + plan_id + plan_label の形へ正規化して返す

8.4 更新

  • PATCH /api/todos/{id}/

更新可能項目:

  • タイトル
  • 説明
  • ステータス
  • 期日
  • 作業種別
  • 実績連携フラグ
  • 対象圃場
  • 分類
  • 計画リンク

8.5 削除

  • DELETE /api/todos/{id}/

ルール案:

  • 連携済み実績がある TODO は物理削除ではなく制限をかける案を優先
  • MVP ではまず done かつ実績連携済み TODO の削除可否を要確認とする

8.6 並び替え

  • PATCH /api/todos/reorder/

payload 例:

{
  "items": [
    {"id": 31, "priority": 1000},
    {"id": 27, "priority": 2000},
    {"id": 42, "priority": 3000}
  ]
}

方針:

  • 一括更新で保存する
  • DnD が難しい場合も、矢印移動 UI から同 API を呼ぶ

8.7 計画から TODO 生成

  • POST /api/todos/from-plan/

payload 例:

{
  "plan_type": "fertilization",
  "plan_id": 8,
  "title": "2026春肥の散布",
  "field_ids": [12, 18],
  "due_date": "2026-04-15",
  "should_link_record": true
}

生成ルール:

  • 既存計画をリンクする
  • field_ids 未指定時は計画内の全圃場を初期対象にする
  • work_typeplan_type から自動補完する
  • タイトルは自動生成可能にする

8.8 完了処理

  • POST /api/todos/{id}/complete/

方針:

  • status=done にする専用入口を用意する
  • should_link_record=true かつ対応実績アプリがある場合、関連画面へ遷移するための情報を返す
  • MVP で自動実績作成まで行うか、完了導線のみ返すかは実装時に選べるようにする

9. UI 仕様案

9.1 一覧画面 /todos

表示内容:

  • 未着手、進行中 TODO を優先表示
  • タイトル
  • ステータス
  • 期日
  • 作業種別
  • 対象圃場数
  • 紐づき計画

操作:

  • 新規作成
  • ステータス変更
  • 並び替え
  • 完了済み、キャンセル済み表示切り替え
  • 絞り込み

視覚表現:

  • 期限超過は赤系
  • 当日期限は強調
  • 進行中は目立つバッジ表示

9.2 詳細画面 /todos/{id}

表示・編集項目:

  • タイトル
  • 説明
  • ステータス
  • 期日
  • 作業種別
  • 実績連携フラグ
  • 対象圃場
  • 分類作物、分類品種
  • 計画リンク

下部表示:

  • 実績連携先
  • 完了日時
  • 更新日時

9.3 作成導線

MVP では少なくとも以下の 2 導線を持つ。

  1. TODO 一覧から新規作成
  2. 計画詳細または一覧から TODO 生成

9.4 計画画面からの導線

対象候補:

  • 施肥計画
  • 田植え計画
  • 運搬計画

ボタン例:

  • TODOを作成
  • この計画からTODO生成

初期値:

  • タイトル
  • 作業種別
  • 対象圃場候補
  • should_link_record

10. 実績連携の考え方

10.1 基本原則

  • TODO は実績そのものではない
  • ただし、実績入力の起点にはなる
  • すべての TODO が実績へ行くわけではない

10.2 施肥

将来像:

  1. 施肥計画を作る
  2. TODO を生成する
  3. TODO を実施する
  4. 完了時に施肥実績へつなぐ

考え方:

  • 従来の 施肥計画 -> 施肥実績 に対し、間に TODO が入れるようにする
  • TODO 完了時は SpreadingSession 作成導線へつなぐ
  • 対象圃場は TODO の TodoTargetField を初期値として渡す

10.3 田植え

田植え実績アプリは今後実装予定であるため、今回の TODO 側では以下を前提にする。

  • rice_transplant 種別の TODO を持てる
  • 完了時に将来の田植え実績へ接続できるよう索引設計を残す
  • MVP 時点では「完了済みだが実績アプリ未接続」の状態も許容する

10.4 実績アプリが無い作業

  • general など、実績アプリに紐づかない TODO を許容する
  • その場合は status=done のみで完了とする

11. バリデーション方針

  • done に遷移したら completed_at を自動設定する
  • canceled に遷移したら canceled_at を自動設定する
  • done から todo または doing への差し戻しは MVP では許可する
  • 差し戻し時も completed_at はクリアせず履歴値として保持する
  • plan_links に紐づく計画の年度と TODO の利用年度が必要なら将来追加する
  • field_ids が計画外圃場を含む場合は、plan_links が 1 件以上ある場合のみエラーにする
  • 複数 plan_links がある場合は、それぞれの計画に対して対象圃場整合性を検証する
  • should_link_record=true でも、対応実績アプリが無い場合は保存を許可する
  • TodoTargetField.fieldPROTECT を採用する
  • 理由は、過去 TODO の対象圃場履歴を崩さないことを優先するため

11.1 レビュー反映済み判断

  • done -> todo/doing の差し戻しは許可する
  • 差し戻し後も completed_at は監査用の履歴値として保持する
  • TodoTargetField.field は運用上の削除容易性より履歴保全を優先し、PROTECT を維持する
  • 実績連携フラグ名は should_link_record で確定する

12. 実装方針

12.1 Backend

  • apps/todos/models.py
  • apps/todos/admin.py
  • apps/todos/serializers.py
  • apps/todos/views.py
  • apps/todos/urls.py
  • apps/todos/migrations/
  • keinasystem/settings.py へ app 追加
  • keinasystem/urls.py/api/todos/ 追加

12.2 Frontend

  • frontend/src/app/todos/page.tsx
  • frontend/src/app/todos/[id]/page.tsx
  • frontend/src/app/todos/new/page.tsx
  • 必要に応じて _components 配下に分離
  • ナビゲーションへ TODO 追加

12.3 実装順

  1. モデル、admin、serializer、migration の作成
  2. TODO 一覧と CRUD API
  3. TODO 一覧と詳細 UI
  4. 並び替え API と UI
  5. 計画から TODO 生成
  6. 完了時の実績連携導線
  7. makemigrationsmigrate を実行

13. テスト観点

  • TODO を新規作成できる
  • 対象圃場を複数紐づけできる
  • 計画の一部圃場だけを対象にできる
  • 完了済み、キャンセル済みの表示切り替えができる
  • 並び替え後に順番が保持される
  • 計画画面から TODO を生成できる
  • 実績アプリ未接続の TODO でも完了できる
  • 実績連携済み TODO の挙動が壊れない

14. 未確定事項

14.1 work_type enum の最終一覧

今回の回答で方針は見えたが、初回実装でどこまで列挙するかは確定していない。

候補:

  • 一般
  • 施肥
  • 田植え
  • 運搬
  • 畔塗
  • 防除
  • 計画非紐づき実績系

14.2 完了時の自動生成レベル

MVP で以下のどこまでやるかは実装前に決める。

  • A. 完了ステータス変更のみ
  • B. 実績入力画面への導線生成
  • C. TODO 情報を使った実績レコード仮生成

14.3 削除ポリシー

実績連携後の TODO をどう扱うか。

案:

  • 物理削除禁止
  • 論理削除
  • 参照整合性チェック付き物理削除

14.4 work_type と計画種別の追加ルール

MVP では以下を前提とする。

  • work_type は先に定義する
  • plan_link は実在する計画モデルだけを持つ
  • work_type が存在しても、対応する計画 FK が未実装のことはあり得る

将来、新しい計画機能が増えたときは以下を同時に更新する。

  • Todo.work_type choices
  • TodoPlanLink.plan_type
  • 対応 FK
  • 計画から TODO 生成 API

15. 提案する MVP 決定案

実装着手しやすさを優先し、MVP では以下を採用することを提案する。

  • TODO は year を持つ
  • 対象管理は TodoTargetField を正とする
  • work_typegeneral / fertilization / rice_transplant / delivery / levee_work / pesticide を初期採用する
  • 計画リンクは明示 FK 方式で開始する
  • 実績連携フラグ名は should_link_record を採用する
  • 完了時はまず「実績入力画面への導線生成」を採用し、自動実績作成は後続検討とする
  • 並び替えは API 先行、UI は DnD 優先、難しければ矢印移動で代替する