Files
keinasystem/document/15_マスタードキュメント_トラクター作業編.md
akira cc6823b071 docs: levee_work をトラクター作業(tractor_work)に再設計
- doc/15 を畔塗作業編からトラクター作業編に改訂
  荒代掻き・植代掻き・耕耘を追加、TractorWorkSession モデル導入
- doc/19 TODO管理編: work_type の levee_work → tractor_work 置換、
  work_subtype フィールド追加、TodoCompletionLink に tractor_work 追記
- Issue #21(代掻き実績登録)の仕様策定に対応
2026-04-10 13:39:47 +09:00

12 KiB
Raw Blame History

マスタードキュメント:トラクター作業記録機能

作成: 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/workrecordsWorkRecord をトラクター作業に対応させる。

変更点 内容
work_type enum TRACTOR_WORK = 'tractor_work' を追加(LEVEE_WORK を置換)
FK tractor_work_session = OneToOneField('tractor_work.TractorWorkSession', ...) に改名

制約:

  • on_delete=CASCADE
  • null=True, blank=True
  • related_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 から自動設定する
  • plannull の場合は 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. 新規作成

  1. ユーザーが作業種別・年度・日付を選ぶ
  2. システムが当年の水稲作付け圃場を候補表示する
  3. ユーザーが対象圃場を選択する
  4. 保存時に TractorWorkSession を作成する
  5. 明細として TractorWorkSessionItem を一括作成する
  6. 各明細の crop_name_snapshot / variety_name_snapshot をサーバー側で自動設定する
  7. WorkRecord を自動生成する(update_or_create

2. 編集

  1. ユーザーが既存の作業記録を開く
  2. 作業種別・日付・タイトル・備考・対象圃場を変更する
  3. 保存時に明細を再構成する
  4. WorkRecord 側の作業日・タイトルも同期更新する

3. 削除

  1. ユーザーが作業記録を削除する
  2. 紐づく TractorWorkSessionItemCASCADE で削除される
  3. 紐づく WorkRecordtractor_work_sessionon_delete=CASCADE により削除される

作業記録連携仕様

追加する種別

enum値 表示名
tractor_work トラクター作業

自動生成ルール

  • work_date = session.date
  • work_type = tractor_work
  • title = session.titlework_type 別デフォルトで補完済み)
  • year = session.year
  • auto_created = True
  • tractor_work_session = 対応する作業記録

同期タイミング

  • 作成時・更新時: update_or_create
  • 削除時: on_delete=CASCADE により自動削除

バリデーションルール

必須

  • work_type
  • year
  • date
  • items1件以上

保存時チェック

  • 選択圃場が0件の保存を禁止する
  • 同一セッション内で同じ圃場を重複登録しない
  • year は原則 date.year と一致しなければならない
  • plan が指定されている場合、plan.fieldfield は一致しなければならない
  • plan.yearsession.year と一致しなければならない

業務上の許容

  • 品種未設定の水稲圃場は保存可
  • 同日に別種別・別地区で複数記録を持てる
  • 一度作業した圃場を別日に再度記録することは可

実装方針

移行方針levee_work → tractor_work

既存 apps/levee_workapps/tractor_work にアプリごと改名する。

  • Django の RenameModel migration でテーブルを改名する
  • work_type フィールドを追加し、既存レコードは levee_work で埋める
  • workrecords の FK名・enum値も migration で更新する
  • API パスを /levee-work//tractor-work/ に変更する
  • フロントエンドの app/levee-work/app/tractor-work/ に移動する

バックエンド

  • Session / SessionItem 構成を維持する
  • Serializer は readwrite を分離する
  • 候補取得 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 — 遷移先更新