Files
keinasystem/document/16_マスタードキュメント_田植え計画編.md
akira a38472e4a0 品種ごとの種子在庫前提まで実装を進めました。
主な変更は、seed 資材種別の追加と Variety.seed_material の導入です。backend/apps/materials/models.py、backend/apps/plans/models.py、backend/apps/plans/serializers.py で、田植え計画が作物在庫ではなく品種に紐づく種子資材の現在庫を参照するように切り替えました。マイグレーションは backend/apps/materials/migrations/0005_material_seed_type.py と backend/apps/plans/migrations/0008_variety_seed_material.py を追加しています。

画面側は、frontend/src/app/materials/page.tsx と frontend/src/app/materials/masters/page.tsx に「種子」タブを追加し、frontend/src/app/allocation/page.tsx の品種管理モーダルで品種ごとに種子在庫資材を設定できるようにしました。田植え計画画面 frontend/src/app/rice-transplant/_components/RiceTransplantEditPage.tsx も、苗箱数 列中心に整理し、種もみkg 列を削除、反当苗箱枚数 の列反映と ≈ / ↩ の四捨五入トグルを施肥計画寄りの操作感に寄せています。仕様書 document/16_マスタードキュメント_田植え計画編.md も更新済みです。

確認できたのは python3 -m py_compile backend/apps/materials/models.py backend/apps/materials/serializers.py backend/apps/plans/models.py backend/apps/plans/serializers.py backend/apps/plans/views.py までです。frontend/node_modules が無いためフロントのビルド確認はまだできていません。Issue #2 にも反映内容をコメント済みです。必要なら次にコミットします。
2026-04-05 11:22:07 +09:00

309 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# マスタードキュメント:田植え計画機能
> **作成**: 2026-04-04
> **最終更新**: 2026-04-05
> **対象機能**: 田植え計画(年度・品種を軸に複数回作成できる苗箱・種もみ使用量計画)
> **実装状況**: MVP実装完了
---
## 概要
農業生産者が「年度 × 品種」を軸に、田植え前の播種・育苗準備量を見積もる機能。
各圃場について「実際に使う苗箱数」を記録し、計画全体で必要な種もみ量を自動集計する。
圃場候補は既存の作付け計画から自動取得し、種もみ在庫は品種単位、反当苗箱枚数の初期値も品種単位で管理する。
同じ年度・同じ品種でも、播種時期や育苗ロットを分けるために複数の田植え計画を作成できる。
### 機能スコープIN / OUT
| IN実装済み | OUT対象外 |
|---|---|
| 田植え計画の作成・編集・削除 | 育苗日程のカレンダー管理 |
| 作付け計画からの候補圃場自動取得 | 実播種実績の記録 |
| 圃場ごとの苗箱数の個別調整 | 種もみロット管理 |
| 列単位のデフォルト反映・四捨五入 | 在庫の自動引当 |
| 苗箱合計・種もみkg合計の自動集計 | PDF出力 |
| 品種ごとの種もみ在庫参照 | 品種ごとの播種日管理 |
| 品種ごとの反当苗箱枚数デフォルト管理 | |
---
## 業務ルール
1. 田植え計画は `年度 × 品種` を軸に作成する
2. 対象圃場は、その年度・品種の作付け計画が登録されている圃場から取得する
3. 種もみ在庫は品種単位で管理する
4. 反当苗箱枚数の初期値は品種単位で管理する
5. 計画ヘッダ側に `反当苗箱枚数` を持ち、施肥計画の `反当袋数` と同じ役割で使う
6. 画面上では `反当苗箱枚数 × 面積(反)` を各圃場のデフォルト苗箱数として表示する
7. 実際に保存するのは圃場ごとの `苗箱数` であり、手動調整後の値をそのまま保持する
8. `種もみg/箱` は計画全体の共通パラメータとして扱い、圃場ごとには持たない
9. 在庫不足はエラーで保存停止せず、一覧・編集画面で残在庫見込みとして可視化する
10. 同じ年度・同じ品種で複数の計画を作成してよい
11. 複数回に分ける場合は、`計画名` で「第1回」「第2回」「4/10播種分」などを区別する
---
## 計算式
### 圃場ごとのデフォルト苗箱数
`デフォルト苗箱数 = 圃場面積(反) × 反当苗箱枚数`
### 圃場ごとの種もみ使用量
`種もみkg = 苗箱数合計 × 苗箱1枚あたり種もみ(g) ÷ 1000`
### 計画全体の残在庫見込み
`残在庫見込み = 品種の種もみ在庫(kg) - 計画全体の種もみkg合計`
---
## データモデル
### Variety品種マスタ
既存 `plans.Variety` に以下を追加・参照する。
| フィールド | 型 | 制約 | 説明 |
|---|---|---|---|
| default_seedling_boxes_per_tan | decimal(6,2) | default=0 | 反当苗箱枚数の初期値 |
| seed_material | FK(materials.Material) 相当 | nullable | その品種に対応する種子在庫 |
### RiceTransplantPlan田植え計画
| フィールド | 型 | 制約 | 説明 |
|---|---|---|---|
| id | int | PK | |
| name | varchar(200) | required | 計画名 |
| year | int | required | 年度 |
| variety | FK(plans.Variety) | PROTECT | 品種 |
| seedling_boxes_per_tan | decimal(6,2) | default=0 | 計画で使う反当苗箱枚数 |
| default_seed_grams_per_box | decimal(8,2) | default=0 | 苗箱1枚あたり種もみ(g)の初期値 |
| notes | text | blank | 備考 |
| created_at | datetime | auto | |
| updated_at | datetime | auto | |
- `year + variety` の一意制約は持たない
- 同一年度・同一品種で複数レコード作成可能
#### 表示用計算項目APIレスポンスに含まれる
| 項目 | 型 | 説明 |
|---|---|---|
| field_count | int | 対象圃場数 |
| total_seedling_boxes | decimal | 苗箱数合計 |
| total_seed_kg | decimal | 種もみ使用量合計(kg) |
| variety_seed_inventory_kg | decimal | 品種在庫(kg) |
| remaining_seed_kg | decimal | 残在庫見込み(kg) |
### RiceTransplantEntry田植え計画エントリ
| フィールド | 型 | 制約 | 説明 |
|---|---|---|---|
| id | int | PK | |
| plan | FK(RiceTransplantPlan) | CASCADE | |
| field | FK(fields.Field) | CASCADE | |
| installed_seedling_boxes | decimal(8,2) | required | その圃場の苗箱数 |
- `unique_together = ['plan', 'field']`
- 順序: `field__display_order, field__id`
#### 表示用計算項目entryレスポンスに含まれる
| 項目 | 型 | 説明 |
|---|---|---|
| field_name | string | 圃場名 |
| field_area_tan | decimal | 圃場面積(反) |
| default_seedling_boxes | decimal | `反当苗箱枚数 × 面積(反)` で求めたデフォルト候補 |
| planned_boxes | decimal | 圃場ごとの苗箱数 |
---
## API エンドポイント
すべて JWT 認証(`Authorization: Bearer <token>`)が必要。
### 田植え計画
| メソッド | URL | 説明 |
|---|---|---|
| GET | `/api/plans/rice-transplant-plans/?year={year}` | 年度別一覧 |
| POST | `/api/plans/rice-transplant-plans/` | 新規作成 |
| GET | `/api/plans/rice-transplant-plans/{id}/` | 詳細取得 |
| PUT/PATCH | `/api/plans/rice-transplant-plans/{id}/` | 更新 |
| DELETE | `/api/plans/rice-transplant-plans/{id}/` | 削除 |
| GET | `/api/plans/rice-transplant-plans/candidate_fields/?year={year}&variety_id={id}` | 作付け計画から候補圃場取得 |
一覧レスポンス例:
```json
{
"id": 1,
"name": "2026年度 コシヒカリ 田植え計画",
"year": 2026,
"variety": 3,
"variety_name": "コシヒカリ",
"crop_name": "水稲",
"seedling_boxes_per_tan": "12.00",
"default_seed_grams_per_box": "200.00",
"seed_material_name": "にこまる 種もみ",
"notes": "",
"field_count": 8,
"total_seedling_boxes": "98.40",
"total_seed_kg": "19.680",
"variety_seed_inventory_kg": "25.000",
"remaining_seed_kg": "5.320",
"entries": [
{
"id": 10,
"field": 5,
"field_name": "田中上",
"field_area_tan": "1.2000",
"installed_seedling_boxes": "14.40",
"default_seedling_boxes": "14.40",
"planned_boxes": "14.40"
}
]
}
```
POST/PUT リクエスト例:
```json
{
"name": "2026年度 コシヒカリ 田植え計画",
"year": 2026,
"variety": 3,
"seedling_boxes_per_tan": "12.00",
"default_seed_grams_per_box": "200.00",
"notes": "",
"entries": [
{
"field_id": 5,
"installed_seedling_boxes": "14.40"
},
{
"field_id": 6,
"installed_seedling_boxes": "13.80"
}
]
}
```
更新時は `entries` を全置換する。
### 品種マスタ更新 / 在庫管理
田植え計画に必要な既定値は既存 API で更新する。
| メソッド | URL | 更新項目 |
|---|---|---|
| PATCH | `/api/plans/varieties/{id}/` | `default_seedling_boxes_per_tan` |
| PATCH | `/api/plans/varieties/{id}/` | `seed_material` または同等の種子在庫参照 |
| CRUD | `/api/materials/materials/?material_type=seed` | 品種別の種子在庫マスタ |
---
## 画面仕様
### 1. 田植え計画一覧 `/rice-transplant`
- 年度切替
- 田植え計画の一覧表示
- 同一年度・同一品種の計画が複数並ぶことを想定する
- 表示列:
- 計画名
- 作物 / 品種
- 圃場数
- 苗箱合計
- 種もみ計画kg
- 残在庫見込みkg
- 行アクション:
- 編集
- 削除
### 2. 田植え計画編集 `/rice-transplant/new`, `/rice-transplant/{id}/edit`
- 基本情報:
- 計画名
- 同一年度・同一品種の複数計画を区別できる名称を付ける
- 例: `2026年度 コシヒカリ 第1回`, `2026年度 コシヒカリ 4/15播種分`
- 年度
- 品種
- 苗箱1枚あたり種もみ(g) デフォルト
- 備考
- 対象圃場:
- 品種選択後に作付け計画から候補圃場を自動取得
- 新規作成時は候補圃場を初期選択
- 圃場の追加・除外が可能
- 初期値:
- `反当苗箱枚数` は品種マスタの `default_seedling_boxes_per_tan` を初期値として表示
- `反当苗箱枚数 × 面積(反)` で各圃場のデフォルト苗箱数を求める
- `種もみg/箱` は計画全体の共通値
- 圃場テーブル:
- 圃場
- 面積(反)
- 苗箱数入力欄
- 左側にデフォルト苗箱数ラベルを表示
- 小数は 1 桁表示を基本とする
- 列操作:
- `反当苗箱枚数` の入力欄
- デフォルトを列単位で一括反映するボタン
- 列単位の四捨五入ボタン
- 施肥計画の四捨五入ボタンと同じ配置・2ステート動作
- サマリー:
- 対象圃場数
- 苗箱合計
- 種もみ計画kg
- 品種在庫kg
- 残在庫見込みkg
### 3. 品種管理モーダル `/allocation`
既存の作付け計画画面内の品種管理モーダルを拡張。
- 品種単位:
- 反当苗箱枚数デフォルトを更新可能
- 対応する種子在庫を設定可能
---
## バリデーション・運用ルール
1. 計画名は必須
2. 品種は必須
3. 圃場は1件以上必要
4. `installed_seedling_boxes``seedling_boxes_per_tan` は 0 以上の数値を想定
5. 在庫不足でも保存は許可し、UIで不足を可視化する
6. 候補圃場の抽出元は既存 `Plan`(作付け計画)であるため、先に作付け計画が必要
---
## 既知の制約
1. 田植え計画の PDF 出力は未実装
2. 実播種や田植え実績との連携は未実装
---
## 関連ファイル
| 種別 | パス |
|---|---|
| モデル | `backend/apps/plans/models.py` |
| モデル | `backend/apps/materials/models.py` |
| シリアライザ | `backend/apps/plans/serializers.py` |
| シリアライザ | `backend/apps/materials/serializers.py` |
| ViewSet | `backend/apps/plans/views.py` |
| URL | `backend/apps/plans/urls.py` |
| マイグレーション | `backend/apps/plans/migrations/0005_crop_seed_inventory_variety_seedling_boxes_and_rice_transplant.py`, `backend/apps/plans/migrations/0006_rename_seedling_boxes_per_tan_to_installed_seedling_boxes.py`, `backend/apps/plans/migrations/0007_ricetransplantplan_seedling_boxes_per_tan.py`, `backend/apps/plans/migrations/0008_variety_seed_material.py`, `backend/apps/materials/migrations/0005_material_seed_type.py` |
| 一覧画面 | `frontend/src/app/rice-transplant/page.tsx` |
| 編集画面 | `frontend/src/app/rice-transplant/_components/RiceTransplantEditPage.tsx` |
| ナビゲーション | `frontend/src/components/Navbar.tsx` |
| 品種管理モーダル | `frontend/src/app/allocation/page.tsx` |
| 在庫画面 | `frontend/src/app/materials/page.tsx` |
| 資材マスタ | `frontend/src/app/materials/masters/page.tsx` |