- doc/15 を畔塗作業編からトラクター作業編に改訂 荒代掻き・植代掻き・耕耘を追加、TractorWorkSession モデル導入 - doc/19 TODO管理編: work_type の levee_work → tractor_work 置換、 work_subtype フィールド追加、TodoCompletionLink に tractor_work 追記 - Issue #21(代掻き実績登録)の仕様策定に対応
12 KiB
12 KiB
マスタードキュメント:トラクター作業記録機能
作成: 2026-04-04 最終更新: 2026-04-10 対象機能: トラクター作業記録(畔塗・荒代掻き・植代掻き・耕耘) 実装状況: 畔塗のみ実装済み。荒代掻き・植代掻き・耕耘は設計中(Issue #21) 対象 Issue:
akira/keinasystem#21
概要
農業生産者が、水稲作付け圃場に対して実施したトラクター作業を日付単位で記録する機能。 対象圃場をまとめて選択し、保存時に作業記録一覧へ自動反映する。
対象作業種別:
| 種別 | 日本語名 | 説明 |
|---|---|---|
levee_work |
畔塗 | 畦畔の補修・造成 |
rough_harrowing |
荒代掻き | 田植え前の粗い代掻き |
transplant_harrowing |
植代掻き | 田植え直前の仕上げ代掻き |
cultivation |
耕耘 | 土起こし・耕起 |
これらはいずれもトラクターを用いた資材なし作業であり、同一のデータモデルで管理する。
本機能は、施肥計画の散布実績と同様に 「作業本体を専用テーブルで持ち、作業記録一覧には索引を自動生成する」 という設計方針を採用する。
機能スコープ(IN / OUT)
| IN(本機能で扱う) | OUT(本機能では扱わない) |
|---|---|
| 日付単位の作業記録作成(全4種別) | 作業の工程管理 |
| 水稲作付け圃場の候補抽出 | 作業者別の工数集計 |
| 複数圃場の一括選択・保存 | 機械・資材の在庫管理 |
| 作業記録一覧(WorkRecord)への自動反映 | 写真添付 |
| 記録の編集・削除 | GPS軌跡連携 |
| 対象圃場一覧の参照画面 | 汎用作業日誌への完全統合 |
背景と目的
現状システムには畔塗の記録機能があるが、同じトラクター作業である荒代掻き・植代掻き・耕耘は登録できない。 これらは以下の共通点を持つため、統一モデルで管理する。
- 1日で複数圃場をまとめて実施することが多い
- 対象圃場は当年の作付け計画と密接に関係する
- 後から「いつ、どの圃場を実施したか」を一覧で見返したい
- 使用資材がない(施肥・農薬とは区別される)
データモデル
TractorWorkSession(トラクター作業記録本体)
日付単位のトラクター作業記録。
| フィールド | 型 | 制約 | 説明 |
|---|---|---|---|
| id | int | PK | |
| work_type | varchar(30) | required | 作業種別(下記参照) |
| year | int | required | 年度フィルタ用。原則 date.year と一致させる |
| date | DateField | required | 作業日 |
| title | varchar(100) | required | 一覧表示タイトル。未指定時はサーバー側で work_type に応じたデフォルト値を補完する |
| notes | text | blank | 備考 |
| created_at | datetime | auto | |
| updated_at | datetime | auto |
work_type の値とデフォルトタイトル
| work_type | 表示名 | デフォルトタイトル |
|---|---|---|
levee_work |
畔塗 | 水稲畔塗 |
rough_harrowing |
荒代掻き | 水稲荒代掻き |
transplant_harrowing |
植代掻き | 水稲植代掻き |
cultivation |
耕耘 | 水稲耕耘 |
year + dateの一意制約は付けない- 同日に種別違い・地区違いで複数記録を持てるようにする
TractorWorkSessionItem(対象圃場明細)
トラクター作業記録に紐づく対象圃場一覧。
| フィールド | 型 | 制約 | 説明 |
|---|---|---|---|
| id | int | PK | |
| session | FK(TractorWorkSession) | CASCADE | 親の作業記録 |
| field | FK(fields.Field) | PROTECT | 対象圃場 |
| plan | FK(plans.Plan) | SET_NULL, nullable | 保存時点の作付け計画参照 |
| crop_name_snapshot | varchar(100) | required | 保存時点の作物名 |
| variety_name_snapshot | varchar(100) | blank | 保存時点の品種名 |
| created_at | datetime | auto | |
| updated_at | datetime | auto |
unique_together = ['session', 'field']- 圃場名は
Fieldを参照して表示する - 作物・品種は履歴保全のためスナップショット保持
WorkRecord(作業記録索引)
既存 apps/workrecords の WorkRecord をトラクター作業に対応させる。
| 変更点 | 内容 |
|---|---|
work_type enum |
TRACTOR_WORK = 'tractor_work' を追加(LEVEE_WORK を置換) |
| FK | tractor_work_session = OneToOneField('tractor_work.TractorWorkSession', ...) に改名 |
制約:
on_delete=CASCADEnull=True,blank=Truerelated_name='work_record'
一覧表示時の想定値:
| 項目 | 値 |
|---|---|
| 作業日 | 作業記録の日付 |
| 種別 | トラクター作業(work_type の日本語表示) |
| タイトル | session.title |
| 参照先 | 対象圃場一覧画面 |
候補圃場抽出ルール
候補は作付け計画 Plan から抽出する。
基本条件
- 指定年度の
Planであること crop.name = "水稲"の圃場であること
補足
- 品種未設定でも
crop=水稲なら候補に含める - 並び順は
field.display_order,field.id
候補レスポンスで返す情報
| 項目 | 説明 |
|---|---|
| field_id | 圃場ID |
| field_name | 圃場名 |
| field_area_tan | 面積(反) |
| group_name | グループ名 |
| plan_id | 対応する作付け計画ID |
| crop_name | 作物名 |
| variety_name | 品種名 |
| selected | 初期選択状態(原則 true) |
画面仕様
画面の位置づけ
日付と作業種別を先に決めて対象圃場を選ぶ「日報型UI」。 1回の保存で複数圃場をまとめて記録する。
主要画面
1. トラクター作業記録一覧画面(/tractor-work)
- 年度内の記録を一覧する
- 作業種別でフィルター可能
- 新規作成・既存記録の編集・削除
表示項目: 作業日 / 作業種別 / タイトル / 対象圃場数 / 面積合計 / 備考
2. 作成・編集画面
入力項目:
- 作業種別(畔塗 / 荒代掻き / 植代掻き / 耕耘)← 新規追加
- 日付
- タイトル(work_type に連動したデフォルト値を自動セット)
- 備考
- 対象圃場一覧(チェックボックス)
推奨UIイメージ
トラクター作業記録作成
[作業種別 荒代掻き ▼]
[日付 2026-04-20]
[タイトル 水稲荒代掻き]
[備考 __________________ ]
対象圃場一覧
[全選択] [全解除]
☑ 田中上 1.2反 上エリア コシヒカリ
☑ 田中下 0.8反 上エリア あきたこまち
☐ 山の前 1.5反 南エリア (未設定)
[保存]
API エンドポイント
すべて JWT 認証必須。
トラクター作業記録
| メソッド | URL | 説明 |
|---|---|---|
| GET | /api/tractor-work/sessions/?year={year} |
年度別一覧 |
| POST | /api/tractor-work/sessions/ |
新規作成 |
| GET | /api/tractor-work/sessions/{id}/ |
詳細取得 |
| PUT/PATCH | /api/tractor-work/sessions/{id}/ |
更新 |
| DELETE | /api/tractor-work/sessions/{id}/ |
削除 |
候補圃場取得
| メソッド | URL | 説明 |
|---|---|---|
| GET | /api/tractor-work/candidates/?year={year} |
水稲作付け圃場候補を返す |
リクエスト例(新規作成)
{
"work_type": "rough_harrowing",
"year": 2026,
"date": "2026-04-20",
"title": "水稲荒代掻き",
"notes": "",
"items": [
{ "field": 5, "plan": 12 },
{ "field": 6, "plan": 13 }
]
}
crop_name_snapshot/variety_name_snapshotはクライアント送信不要。サーバーがplanから自動設定するplanがnullの場合はfieldに対応する当年Planから補完を試みる
レスポンス例(詳細)
{
"id": 3,
"work_type": "rough_harrowing",
"year": 2026,
"date": "2026-04-20",
"title": "水稲荒代掻き",
"notes": "",
"work_record_id": 15,
"item_count": 2,
"total_area_tan": "2.0000",
"items": [
{
"id": 11,
"field": 5,
"field_name": "田中上",
"plan": 12,
"crop_name_snapshot": "水稲",
"variety_name_snapshot": "コシヒカリ"
}
],
"created_at": "2026-04-20T08:00:00Z",
"updated_at": "2026-04-20T08:00:00Z"
}
業務フロー
1. 新規作成
- ユーザーが作業種別・年度・日付を選ぶ
- システムが当年の水稲作付け圃場を候補表示する
- ユーザーが対象圃場を選択する
- 保存時に
TractorWorkSessionを作成する - 明細として
TractorWorkSessionItemを一括作成する - 各明細の
crop_name_snapshot/variety_name_snapshotをサーバー側で自動設定する WorkRecordを自動生成する(update_or_create)
2. 編集
- ユーザーが既存の作業記録を開く
- 作業種別・日付・タイトル・備考・対象圃場を変更する
- 保存時に明細を再構成する
WorkRecord側の作業日・タイトルも同期更新する
3. 削除
- ユーザーが作業記録を削除する
- 紐づく
TractorWorkSessionItemはCASCADEで削除される - 紐づく
WorkRecordはtractor_work_sessionのon_delete=CASCADEにより削除される
作業記録連携仕様
追加する種別
| enum値 | 表示名 |
|---|---|
tractor_work |
トラクター作業 |
自動生成ルール
work_date=session.datework_type=tractor_worktitle=session.title(work_type 別デフォルトで補完済み)year=session.yearauto_created=Truetractor_work_session= 対応する作業記録
同期タイミング
- 作成時・更新時:
update_or_create - 削除時:
on_delete=CASCADEにより自動削除
バリデーションルール
必須
work_typeyeardateitems(1件以上)
保存時チェック
- 選択圃場が0件の保存を禁止する
- 同一セッション内で同じ圃場を重複登録しない
yearは原則date.yearと一致しなければならないplanが指定されている場合、plan.fieldとfieldは一致しなければならないplan.yearはsession.yearと一致しなければならない
業務上の許容
- 品種未設定の水稲圃場は保存可
- 同日に別種別・別地区で複数記録を持てる
- 一度作業した圃場を別日に再度記録することは可
実装方針
移行方針(levee_work → tractor_work)
既存 apps/levee_work を apps/tractor_work にアプリごと改名する。
- Django の
RenameModelmigration でテーブルを改名する work_typeフィールドを追加し、既存レコードはlevee_workで埋めるworkrecordsの FK名・enum値も migration で更新する- API パスを
/levee-work/→/tractor-work/に変更する - フロントエンドの
app/levee-work/→app/tractor-work/に移動する
バックエンド
Session/SessionItem構成を維持する- Serializer は
readとwriteを分離する - 候補取得 API は
Planを起点に組み立てる sync_tractor_work_record(session)でWorkRecordと同期する
フロントエンド
- 既存の levee-work ページを tractor-work に移植する
- 作業種別セレクタを追加し、選択に応じてデフォルトタイトルを自動セットする
ソースファイル構成
バックエンド
backend/apps/tractor_work/
├── models.py # TractorWorkSession, TractorWorkSessionItem
├── serializers.py
├── views.py
├── urls.py
├── admin.py
└── migrations/
├── 0001_initial.py # (levee_work から移行)
└── 0002_rename_and_add_work_type.py
変更ファイル:
backend/apps/workrecords/models.py— FK名・enum更新backend/apps/workrecords/services.py— sync関数改名backend/keinasystem/settings.py— INSTALLED_APPS更新backend/keinasystem/urls.py— URLパス更新
フロントエンド
frontend/src/app/tractor-work/
└── page.tsx
変更ファイル:
frontend/src/types/index.ts— 型定義更新frontend/src/components/Navbar.tsx— リンク更新frontend/src/app/workrecords/page.tsx— 遷移先更新