指摘を反映して 改善案/TODO管理機能仕様書案.md を更新しました。

主な修正は、Todo.year の追加、TodoCrop / TodoVariety の具体定義追加、priority の 1000 刻み再採番ルール明記、plan_links がある場合だけ対象圃場整合性を検証する形への明確化、levee_work を「MVP では計画リンクなしの work_type」として整理、plan_type + plan_id を Serializer で各 FK に変換する方針追記、admin.py と migrations の追加、見出し階層の修正です。

あわせて、実績連携フラグ名は should_link_record に寄せました。まだコミットはしていないので、必要ならこの修正分もそのままコミットします。
This commit is contained in:
akira
2026-04-09 16:34:30 +09:00
parent 83525c2f59
commit 5f58c2c686

View File

@@ -137,20 +137,21 @@ TODO は「作業指示」兼「実行待ちキュー」として扱う。
## 7. データモデル方針 ## 7. データモデル方針
## 7.1 Todo ### 7.1 Todo
TODO 本体。 TODO 本体。
| フィールド | 型 | 必須 | 説明 | | フィールド | 型 | 必須 | 説明 |
|---|---|---|---| |---|---|---|---|
| id | bigint | ✓ | PK | | id | bigint | ✓ | PK |
| year | integer | ✓ | 年度 |
| title | varchar(200) | ✓ | タイトル | | title | varchar(200) | ✓ | タイトル |
| description | text | | 説明 | | description | text | | 説明 |
| status | enum | ✓ | `todo / doing / done / canceled` | | status | enum | ✓ | `todo / doing / done / canceled` |
| priority | integer | ✓ | 小さいほど上位 | | priority | integer | ✓ | 小さいほど上位 |
| due_date | date | | 期日 | | due_date | date | | 期日 |
| work_type | enum | ✓ | 作業種別 | | work_type | enum | ✓ | 作業種別 |
| reflect_to_record | boolean | ✓ | 完了時に実績連携するか | | should_link_record | boolean | ✓ | 完了時に実績連携導線を有効にするか |
| completed_at | datetime | | 完了日時 | | completed_at | datetime | | 完了日時 |
| canceled_at | datetime | | キャンセル日時 | | canceled_at | datetime | | キャンセル日時 |
| created_at | datetime | ✓ | | | created_at | datetime | ✓ | |
@@ -167,10 +168,19 @@ TODO 本体。
- 基本は FILO とする - 基本は FILO とする
- 新規作成時は最上位へ入る - 新規作成時は最上位へ入る
- ユーザーが並び替えた後は `priority`保存する - `priority` は 1000 刻みの整数で保存する
- 初回作成時は最上位 TODO の `priority - 1000` を新規 TODO に割り当てる
- 一覧では `priority` 昇順で表示する
- ユーザーが並び替えた後は、表示順に 1000, 2000, 3000... と振り直して保存する
- 既存レコードの一括インクリメントや小数 priority は採用しない
- 完了、キャンセル済みも `priority` は保持する - 完了、キャンセル済みも `priority` は保持する
- 一覧のデフォルト表示は `todo / doing` のみを `priority` 昇順で表示する - 一覧のデフォルト表示は `todo / doing` のみを `priority` 昇順で表示する
補足:
- 1000 刻みは API の中間挿入余地ではなく、再採番時の可読性のために採用する
- 並び順変更は常に表示対象全体を受け取って再採番する前提とする
### 7.1.3 作業種別 ### 7.1.3 作業種別
作業種別は「計画に対応するもの」と「計画に対応しないもの」の両方を含める。 作業種別は「計画に対応するもの」と「計画に対応しないもの」の両方を含める。
@@ -190,7 +200,7 @@ TODO 本体。
- 実装時点で将来の全計画種別を確定できない場合は、MVP では現行アプリに対応する種別を先行定義する - 実装時点で将来の全計画種別を確定できない場合は、MVP では現行アプリに対応する種別を先行定義する
- `general` はどれにも当てはまらない作業用に必須 - `general` はどれにも当てはまらない作業用に必須
## 7.2 TodoTargetField ### 7.2 TodoTargetField
TODO が実際に対象とする圃場。 TODO が実際に対象とする圃場。
@@ -211,14 +221,31 @@ TODO が実際に対象とする圃場。
- グループ、作物、品種から一括選択する UI は許可する - グループ、作物、品種から一括選択する UI は許可する
- ただし保存時は対象圃場へ展開して保持する - ただし保存時は対象圃場へ展開して保持する
## 7.3 TodoCrop / TodoVariety ### 7.3 TodoCrop / TodoVariety
TODO の分類補助用。 TODO の分類補助用。
| モデル | 役割 | #### TodoCrop
|---|---|
| TodoCrop | 作物ベースの目印、絞り込み、表示補助 | | フィールド | 型 | 必須 | 説明 |
| TodoVariety | 品種ベースの目印、絞り込み、表示補助 | |---|---|---|---|
| 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']`
注意: 注意:
@@ -226,7 +253,7 @@ TODO の分類補助用。
- `Crop``Variety` だけ紐づいていて圃場が 0 件の TODO は許可する - `Crop``Variety` だけ紐づいていて圃場が 0 件の TODO は許可する
- これにより、圃場未確定の準備作業も登録できる - これにより、圃場未確定の準備作業も登録できる
## 7.4 TodoPlanLink ### 7.4 TodoPlanLink
TODO と既存計画との紐づけ。 TODO と既存計画との紐づけ。
@@ -238,7 +265,6 @@ TODO と既存計画との紐づけ。
| fertilization_plan | FK | | 施肥計画 | | fertilization_plan | FK | | 施肥計画 |
| rice_transplant_plan | FK | | 田植え計画 | | rice_transplant_plan | FK | | 田植え計画 |
| delivery_plan | FK | | 運搬計画 | | delivery_plan | FK | | 運搬計画 |
| levee_work_session | FK | | 畔塗は計画というより実績寄りのため要検討 |
| created_at | datetime | ✓ | | | created_at | datetime | ✓ | |
方針: 方針:
@@ -253,20 +279,22 @@ TODO と既存計画との紐づけ。
- 施肥計画 `FertilizationPlan` - 施肥計画 `FertilizationPlan`
- 田植え計画 `RiceTransplantPlan` - 田植え計画 `RiceTransplantPlan`
- 運搬計画 `DeliveryPlan` - 運搬計画 `DeliveryPlan`
- 畔塗 `levee_work` は MVP では「計画リンクなしで持てる work_type」として扱う
- 将来、畔塗に計画モデルが導入された時点で `TodoPlanLink` に追加する
補足: 補足:
- 作付け計画 `Plan` は「年内の計画情報」であり、TODO 生成元としては必須ではない - 作付け計画 `Plan` は「年内の計画情報」であり、TODO 生成元としては必須ではない
- 当面は Issue 回答に合わせ、`作付け計画以外のすべての計画` を TODO の対象候補とする - 当面は Issue 回答に合わせ、`作付け計画以外のすべての計画` を TODO の対象候補とする
## 7.5 TodoCompletionLink ### 7.5 TodoCompletionLink
完了時の実績連携先を記録する索引。 完了時の実績連携先を記録する索引。
| フィールド | 型 | 必須 | 説明 | | フィールド | 型 | 必須 | 説明 |
|---|---|---|---| |---|---|---|---|
| id | bigint | ✓ | PK | | id | bigint | ✓ | PK |
| todo | OneToOne または FK | ✓ | TODO | | todo | FK(Todo) | ✓ | TODO |
| record_type | enum | ✓ | 実績種別 | | record_type | enum | ✓ | 実績種別 |
| work_record | FK(workrecords.WorkRecord) | | 共通索引 | | work_record | FK(workrecords.WorkRecord) | | 共通索引 |
| spreading_session | FK(fertilizer.SpreadingSession) | | 施肥実績 | | spreading_session | FK(fertilizer.SpreadingSession) | | 施肥実績 |
@@ -276,6 +304,8 @@ TODO と既存計画との紐づけ。
方針: 方針:
- 完了時に何へ連携したかを TODO 側から追えるようにする - 完了時に何へ連携したかを TODO 側から追えるようにする
- `todo` は OneToOne に固定せず FK とする
- 理由は 1 TODO から複数実績へ分割される可能性を残すため
- 実績アプリが未実装の種別は空でよい - 実績アプリが未実装の種別は空でよい
- 将来の田植え実績導入時に拡張できる形にする - 将来の田植え実績導入時に拡張できる形にする
@@ -324,9 +354,10 @@ TODO と既存計画との紐づけ。
"title": "西田エリアの追肥", "title": "西田エリアの追肥",
"description": "週内に先行実施", "description": "週内に先行実施",
"status": "todo", "status": "todo",
"year": 2026,
"due_date": "2026-04-12", "due_date": "2026-04-12",
"work_type": "fertilization", "work_type": "fertilization",
"reflect_to_record": true, "should_link_record": true,
"field_ids": [12, 18, 21], "field_ids": [12, 18, 21],
"crop_ids": [1], "crop_ids": [1],
"variety_ids": [4], "variety_ids": [4],
@@ -336,6 +367,16 @@ TODO と既存計画との紐づけ。
} }
``` ```
`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 更新 ### 8.4 更新
- `PATCH /api/todos/{id}/` - `PATCH /api/todos/{id}/`
@@ -370,9 +411,9 @@ payload 例:
```json ```json
{ {
"items": [ "items": [
{"id": 31, "priority": 10}, {"id": 31, "priority": 1000},
{"id": 27, "priority": 20}, {"id": 27, "priority": 2000},
{"id": 42, "priority": 30} {"id": 42, "priority": 3000}
] ]
} }
``` ```
@@ -395,7 +436,7 @@ payload 例:
"title": "2026春肥の散布", "title": "2026春肥の散布",
"field_ids": [12, 18], "field_ids": [12, 18],
"due_date": "2026-04-15", "due_date": "2026-04-15",
"reflect_to_record": true "should_link_record": true
} }
``` ```
@@ -413,14 +454,14 @@ payload 例:
方針: 方針:
- `status=done` にする専用入口を用意する - `status=done` にする専用入口を用意する
- `reflect_to_record=true` かつ対応実績アプリがある場合、関連画面へ遷移するための情報を返す - `should_link_record=true` かつ対応実績アプリがある場合、関連画面へ遷移するための情報を返す
- MVP で自動実績作成まで行うか、完了導線のみ返すかは実装時に選べるようにする - MVP で自動実績作成まで行うか、完了導線のみ返すかは実装時に選べるようにする
--- ---
## 9. UI 仕様案 ## 9. UI 仕様案
## 9.1 一覧画面 `/todos` ### 9.1 一覧画面 `/todos`
表示内容: 表示内容:
@@ -446,7 +487,7 @@ payload 例:
- 当日期限は強調 - 当日期限は強調
- 進行中は目立つバッジ表示 - 進行中は目立つバッジ表示
## 9.2 詳細画面 `/todos/{id}` ### 9.2 詳細画面 `/todos/{id}`
表示・編集項目: 表示・編集項目:
@@ -466,14 +507,14 @@ payload 例:
- 完了日時 - 完了日時
- 更新日時 - 更新日時
## 9.3 作成導線 ### 9.3 作成導線
MVP では少なくとも以下の 2 導線を持つ。 MVP では少なくとも以下の 2 導線を持つ。
1. TODO 一覧から新規作成 1. TODO 一覧から新規作成
2. 計画詳細または一覧から TODO 生成 2. 計画詳細または一覧から TODO 生成
## 9.4 計画画面からの導線 ### 9.4 計画画面からの導線
対象候補: 対象候補:
@@ -491,19 +532,19 @@ MVP では少なくとも以下の 2 導線を持つ。
- タイトル - タイトル
- 作業種別 - 作業種別
- 対象圃場候補 - 対象圃場候補
- `reflect_to_record` - `should_link_record`
--- ---
## 10. 実績連携の考え方 ## 10. 実績連携の考え方
## 10.1 基本原則 ### 10.1 基本原則
- TODO は実績そのものではない - TODO は実績そのものではない
- ただし、実績入力の起点にはなる - ただし、実績入力の起点にはなる
- すべての TODO が実績へ行くわけではない - すべての TODO が実績へ行くわけではない
## 10.2 施肥 ### 10.2 施肥
将来像: 将来像:
@@ -518,7 +559,7 @@ MVP では少なくとも以下の 2 導線を持つ。
- TODO 完了時は `SpreadingSession` 作成導線へつなぐ - TODO 完了時は `SpreadingSession` 作成導線へつなぐ
- 対象圃場は TODO の `TodoTargetField` を初期値として渡す - 対象圃場は TODO の `TodoTargetField` を初期値として渡す
## 10.3 田植え ### 10.3 田植え
田植え実績アプリは今後実装予定であるため、今回の TODO 側では以下を前提にする。 田植え実績アプリは今後実装予定であるため、今回の TODO 側では以下を前提にする。
@@ -526,7 +567,7 @@ MVP では少なくとも以下の 2 導線を持つ。
- 完了時に将来の田植え実績へ接続できるよう索引設計を残す - 完了時に将来の田植え実績へ接続できるよう索引設計を残す
- MVP 時点では「完了済みだが実績アプリ未接続」の状態も許容する - MVP 時点では「完了済みだが実績アプリ未接続」の状態も許容する
## 10.4 実績アプリが無い作業 ### 10.4 実績アプリが無い作業
- `general` など、実績アプリに紐づかない TODO を許容する - `general` など、実績アプリに紐づかない TODO を許容する
- その場合は `status=done` のみで完了とする - その場合は `status=done` のみで完了とする
@@ -537,25 +578,31 @@ MVP では少なくとも以下の 2 導線を持つ。
- `done` に遷移したら `completed_at` を自動設定する - `done` に遷移したら `completed_at` を自動設定する
- `canceled` に遷移したら `canceled_at` を自動設定する - `canceled` に遷移したら `canceled_at` を自動設定する
- `todo` または `doing` に戻した場合の日時取り扱いは要件次第だが、MVP ではクリアしない案を優先 - `done` から `todo` または `doing` への差し戻しは MVP では許可する
- 差し戻し時も `completed_at` はクリアせず履歴値として保持する
- `plan_links` に紐づく計画の年度と TODO の利用年度が必要なら将来追加する - `plan_links` に紐づく計画の年度と TODO の利用年度が必要なら将来追加する
- `field_ids` が計画外圃場を含む場合はエラーにする - `field_ids` が計画外圃場を含む場合は`plan_links` が 1 件以上ある場合のみエラーにする
- `reflect_to_record=true` でも、対応実績アプリが無い場合は保存を許可する - 複数 `plan_links` がある場合は、それぞれの計画に対して対象圃場整合性を検証する
- `should_link_record=true` でも、対応実績アプリが無い場合は保存を許可する
- `TodoTargetField.field``PROTECT` を採用する
- 理由は、過去 TODO の対象圃場履歴を崩さないことを優先するため
--- ---
## 12. 実装方針 ## 12. 実装方針
## 12.1 Backend ### 12.1 Backend
- `apps/todos/models.py` - `apps/todos/models.py`
- `apps/todos/admin.py`
- `apps/todos/serializers.py` - `apps/todos/serializers.py`
- `apps/todos/views.py` - `apps/todos/views.py`
- `apps/todos/urls.py` - `apps/todos/urls.py`
- `apps/todos/migrations/`
- `keinasystem/settings.py` へ app 追加 - `keinasystem/settings.py` へ app 追加
- `keinasystem/urls.py``/api/todos/` 追加 - `keinasystem/urls.py``/api/todos/` 追加
## 12.2 Frontend ### 12.2 Frontend
- `frontend/src/app/todos/page.tsx` - `frontend/src/app/todos/page.tsx`
- `frontend/src/app/todos/[id]/page.tsx` - `frontend/src/app/todos/[id]/page.tsx`
@@ -563,13 +610,15 @@ MVP では少なくとも以下の 2 導線を持つ。
- 必要に応じて `_components` 配下に分離 - 必要に応じて `_components` 配下に分離
- ナビゲーションへ TODO 追加 - ナビゲーションへ TODO 追加
## 12.3 実装順 ### 12.3 実装順
1. モデルと API の土台 1. モデル、admin、serializer、migration の作成
2. TODO 一覧と CRUD 2. TODO 一覧と CRUD API
3. 並び替え 3. TODO 一覧と詳細 UI
4. 計画から TODO 生成 4. 並び替え API と UI
5. 完了時の実績連携導線 5. 計画から TODO 生成
6. 完了時の実績連携導線
7. `makemigrations``migrate` を実行
--- ---
@@ -620,20 +669,20 @@ MVP で以下のどこまでやるかは実装前に決める。
- 論理削除 - 論理削除
- 参照整合性チェック付き物理削除 - 参照整合性チェック付き物理削除
### 14.4 年度の持ち方 ### 14.4 work_type と計画種別の追加ルール
TODO 本体に `year` を明示的に持つかは未確定 MVP では以下を前提とする
持つメリット: - work_type は先に定義する
- plan_link は実在する計画モデルだけを持つ
- work_type が存在しても、対応する計画 FK が未実装のことはあり得る
- 年度フィルタが簡単 将来、新しい計画機能が増えたときは以下を同時に更新する。
- 実績や計画との一覧整合が取りやすい
持たないメリット: - `Todo.work_type` choices
- `TodoPlanLink.plan_type`
- TODO を純粋な作業単位として保てる - 対応 FK
- 計画から TODO 生成 API
MVP では年度を持たせる方が実用上は扱いやすい可能性が高い。
--- ---
@@ -645,6 +694,6 @@ MVP では年度を持たせる方が実用上は扱いやすい可能性が高
- 対象管理は `TodoTargetField` を正とする - 対象管理は `TodoTargetField` を正とする
- `work_type``general / fertilization / rice_transplant / delivery / levee_work / pesticide` を初期採用する - `work_type``general / fertilization / rice_transplant / delivery / levee_work / pesticide` を初期採用する
- 計画リンクは明示 FK 方式で開始する - 計画リンクは明示 FK 方式で開始する
- 実績連携フラグ名は `should_link_record` を採用する
- 完了時はまず「実績入力画面への導線生成」を採用し、自動実績作成は後続検討とする - 完了時はまず「実績入力画面への導線生成」を採用し、自動実績作成は後続検討とする
- 並び替えは API 先行、UI は DnD 優先、難しければ矢印移動で代替する - 並び替えは API 先行、UI は DnD 優先、難しければ矢印移動で代替する