Files
keinasystem/document/18_マスタードキュメント_農薬散布管理編.md
2026-04-09 14:54:12 +09:00

19 KiB
Raw Blame History

マスタードキュメント:農薬散布管理機能

作成: 2026-04-09 最終更新: 2026-04-09 対象機能: 農薬散布管理(農薬マスタ・散布記録・使用回数チェック・特別栽培向け成分数集計) 実装状況: 未着手(仕様確定済み) Gitea Issue: akira/keinasystem#18


概要

農業生産者が散布した農薬を記録・管理し、農薬取締法に基づく使用基準(製品ごと・有効成分ごとの使用回数制限)への適合確認と、特別栽培認証用の成分数集計を行う機能。

機能スコープIN / OUT

IN実装対象 OUT対象外
農薬マスタ管理CRUD 農薬の在庫管理・購入管理
農林水産省サイトからの農薬情報自動取得 農薬費用の管理
散布イベント記録(圃場/グループ/作物/品種対象) 希釈液の量管理
製品ごとの使用回数チェック(年度×作物) 農薬の廃棄記録
有効成分ごとの総使用回数チェック(年度×作物) 農薬散布マップGIS
特別栽培用:節減対象農薬の使用成分数集計 農薬の処方箋・防除暦の自動作成
回数超過アラート表示

使用回数カウントのルール

農薬の使用回数は 製品単位有効成分単位 の2軸で管理する。

ルール1製品ごとの使用回数

農薬製品(例: 住化スミチオン乳剤を1シーズンに使用した回数 ≤ 登録情報の「本剤の使用回数」上限。

ルール2有効成分ごとの総使用回数

同一有効成分を含む複数製品を使用した場合、その有効成分の総使用回数として合算カウントする。

「MEP乳剤A上限3回」と「MEP乳剤B上限3回」、MEP成分の総上限3回
→ A剤2回 + B剤1回 = 合計3回 → OK
→ A剤2回 + B剤2回 = 合計4回 → 超過!

ルール3使用時期別カウント

育苗期・本圃期など時期別に別カウントになる場合がある(登録情報のテキストとして記録)。 システムでは現フェーズで時期別の自動判定は行わず、登録情報テキストを参照情報として表示する。

カウント対象外農薬(節減対象外)

以下の農薬は使用回数・成分数のカウントから除外する(is_non_target フラグで管理):

  • 展着剤(is_spreader フラグでも管理)
  • 有機JAS別表2に掲げる農薬除虫菊乳剤・硫黄剤・天敵生物農薬・性フェロモン剤等
  • 化学合成でないと認められた農薬(カスガマイシン剤・ポリオキシン剤・バリダマイシン剤等)

特別栽培向け成分数集計

「節減対象農薬(is_non_target=False)の有効成分が何種類使われたか」を年度×作物単位でカウントする。 上限はなく、報告用の集計値として表示する。


データモデル

Pesticide農薬マスタ

アプリ: apps/pesticide
テーブル名: pesticide_pesticide

フィールド 制約 説明
id BigAutoField PK
name CharField(200) required 農薬名(例: 住化スミチオン乳剤)
pesticide_type CharField(100) blank 農薬の種類(例: MEP乳剤)
registration_number CharField(20) blank 農薬登録番号(公式登録番号)
system_id CharField(20) blank 農水省サイトの内部ID詳細URLに使用
purpose CharField(100) blank 用途(例: 殺虫剤)
formulation CharField(100) blank 剤型(例: 乳剤)
toxicity CharField(20) blank 製剤毒性(普/毒/劇等)
is_spreader BooleanField default=False 展着剤フラグ
is_non_target BooleanField default=False 節減対象外フラグ(カウント除外)
notes TextField blank 備考
fetched_at DateTimeField null=True 農水省サイトからの最終取得日時
created_at DateTimeField auto
updated_at DateTimeField auto
  • name は unique 制約なし(同名で複数登録番号が存在しうる)
  • is_spreader=True の場合、is_non_target も自動的に True 扱いとする

PesticideIngredient有効成分

テーブル名: pesticide_pesticideingredient

フィールド 制約 説明
id BigAutoField PK
pesticide FK(Pesticide) CASCADE
name CharField(200) required 成分名称(例: MEP
concentration CharField(100) blank 含有濃度(例: 50.0%
is_active BooleanField default=True 有効成分かどうかFalse = その他成分)
max_total_uses IntegerField null=True この成分を含む農薬の総使用回数上限
use_timing_note TextField blank 使用時期別制限のテキスト(例: 種もみへの処理は1回以内、…
  • unique_together = ['pesticide', 'name']

PesticideProductLimit製品の使用回数上限作物別

テーブル名: pesticide_pesticideproductlimit

農水省の適用表は作物ごとに上限が異なるため、作物名をキーとして保存する。

フィールド 制約 説明
id BigAutoField PK
pesticide FK(Pesticide) CASCADE
crop_name CharField(200) required 作物名(農水省登録情報の表記、例: 稲)
max_uses IntegerField required 本剤の使用回数上限
use_timing_note TextField blank 使用時期・条件の補足テキスト
  • unique_together = ['pesticide', 'crop_name']

SprayEvent散布イベント

テーブル名: pesticide_sprayevent

1回の散布作業を1件として記録する。

フィールド 制約 説明
id BigAutoField PK
year IntegerField required 年度(集計フィルタ用)
date DateField required 散布日
target_type CharField(20) required 対象種別: field / group / crop / variety
target_field FK(fields.Field) null=True, PROTECT 対象が圃場の場合
target_group CharField(50) blank 対象が圃場グループの場合group_name
target_crop FK(plans.Crop) null=True, PROTECT 対象が作物の場合
target_variety FK(plans.Variety) null=True, PROTECT 対象が品種の場合
notes TextField blank 備考
created_at DateTimeField auto
updated_at DateTimeField auto

target_type 別のバリデーション

target_type 必須フィールド 意味
field target_field 特定の圃場1筆に散布
group target_group 同一 group_name の全圃場に散布
crop target_crop 特定の作物に対して散布(作付け計画と照合)
variety target_variety 特定の品種に対して散布(作付け計画と照合)

SprayEventPesticide散布農薬明細

テーブル名: pesticide_sprayeventpesticide

1つの散布イベントに複数農薬を紐づける。

フィールド 制約 説明
id BigAutoField PK
event FK(SprayEvent) CASCADE
pesticide FK(Pesticide) PROTECT 使用農薬
dilution_ratio CharField(50) blank 希釈倍率(例: 1000倍
amount_used CharField(50) blank 使用量(例: 500mL、単位込みで自由記述
notes TextField blank 備考
  • pesticide は PROTECT使用済み農薬は削除不可

使用回数集計の仕組み

集計単位

年度 × 作物 を基本単位とする。

  • target_type=field/group の場合: そのイベントの年度の作付け計画Planから作物を特定
  • target_type=crop の場合: target_crop が直接作物
  • target_type=variety の場合: target_variety の crop が作物

製品使用回数の集計

製品使用回数 = COUNT(SprayEventPesticide where pesticide=X)
              で year × 作物 でフィルタしたもの

有効成分総使用回数の集計

有効成分総使用回数 = COUNT(SprayEventPesticide)
                   where SprayEventPesticide.pesticide に
                   当該有効成分PesticideIngredient.nameが含まれる
                   かつ is_non_target=False
                   で year × 作物 でフィルタしたもの

特別栽培・使用成分数の集計

使用成分数 = COUNT(DISTINCT PesticideIngredient.name)
            where 当該年度×作物の散布イベントで使用された農薬の有効成分
            かつ pesticide.is_non_target=False

API エンドポイント

すべて JWT 認証(Authorization: Bearer <token>)が必要。

農薬マスタ

メソッド URL 説明
GET /api/pesticide/pesticides/ 一覧取得
POST /api/pesticide/pesticides/ 新規作成
GET /api/pesticide/pesticides/{id}/ 詳細取得
PUT/PATCH /api/pesticide/pesticides/{id}/ 更新
DELETE /api/pesticide/pesticides/{id}/ 削除(使用中は 400
POST /api/pesticide/pesticides/fetch/ 農水省サイトから情報取得

農薬マスタ レスポンス例:

{
  "id": 1,
  "name": "住化スミチオン乳剤",
  "pesticide_type": "MEP乳剤",
  "registration_number": "4962",
  "system_id": "4962",
  "purpose": "殺虫剤",
  "formulation": "乳剤",
  "toxicity": "普",
  "is_spreader": false,
  "is_non_target": false,
  "notes": "",
  "fetched_at": "2026-04-09T10:00:00Z",
  "ingredients": [
    {
      "id": 1,
      "name": "MEP",
      "concentration": "50.0%",
      "is_active": true,
      "max_total_uses": 3,
      "use_timing_note": "種もみへの処理は1回以内、育苗箱散布は1回以内、本田では2回以内"
    }
  ],
  "product_limits": [
    {
      "id": 1,
      "crop_name": "稲",
      "max_uses": 2,
      "use_timing_note": "収穫21日前まで"
    }
  ]
}

POST /api/pesticide/pesticides/fetch/

農水省農薬登録情報提供システムから農薬情報を取得してマスタに保存する。 取得に失敗した場合は fetch_error を返し、手動入力に切り替える。

リクエスト:

{
  "name": "スミチオン"
}

レスポンス(成功):

{
  "status": "ok",
  "candidates": [
    {
      "system_id": "4962",
      "name": "住化スミチオン乳剤",
      "pesticide_type": "MEP乳剤",
      "registration_number": "4962"
    },
    {
      "system_id": "4991",
      "name": "ホクコースミチオン乳剤",
      "pesticide_type": "MEP乳剤",
      "registration_number": "4991"
    }
  ]
}

候補が複数ある場合はフロントで選択させ、選択後に詳細取得リクエストを投げる:

{ "system_id": "4962" }

レスポンス(失敗):

{
  "status": "error",
  "message": "農林水産省サイトへの接続に失敗しました。手動で入力してください。"
}

散布イベント

メソッド URL 説明
GET /api/pesticide/events/?year={year} 年度別一覧
POST /api/pesticide/events/ 新規作成
GET /api/pesticide/events/{id}/ 詳細取得
PUT/PATCH /api/pesticide/events/{id}/ 更新
DELETE /api/pesticide/events/{id}/ 削除

散布イベント POST リクエスト例(圃場グループを対象に複数農薬散布):

{
  "year": 2026,
  "date": "2026-05-10",
  "target_type": "group",
  "target_group": "田中エリア",
  "notes": "曇り、風弱し",
  "pesticides": [
    {
      "pesticide": 1,
      "dilution_ratio": "1000倍",
      "amount_used": "500mL"
    },
    {
      "pesticide": 3,
      "dilution_ratio": "2000倍",
      "amount_used": "200mL"
    }
  ]
}

散布イベント レスポンス例:

{
  "id": 10,
  "year": 2026,
  "date": "2026-05-10",
  "target_type": "group",
  "target_group": "田中エリア",
  "target_display": "田中エリア(グループ)",
  "notes": "曇り、風弱し",
  "pesticides": [
    {
      "id": 15,
      "pesticide": 1,
      "pesticide_name": "住化スミチオン乳剤",
      "dilution_ratio": "1000倍",
      "amount_used": "500mL"
    }
  ],
  "created_at": "2026-04-09T10:00:00Z",
  "updated_at": "2026-04-09T10:00:00Z"
}

使用回数チェック

GET /api/pesticide/usage-summary/?year={year}&crop_id={crop_id}

年度×作物単位で使用回数の集計・チェック結果を返す。

レスポンス例:

{
  "year": 2026,
  "crop_id": 1,
  "crop_name": "稲",
  "product_usage": [
    {
      "pesticide_id": 1,
      "pesticide_name": "住化スミチオン乳剤",
      "used_count": 2,
      "max_uses": 2,
      "remaining": 0,
      "is_over": false
    }
  ],
  "ingredient_usage": [
    {
      "ingredient_name": "MEP",
      "used_count": 2,
      "max_total_uses": 3,
      "remaining": 1,
      "is_over": false,
      "products_used": ["住化スミチオン乳剤"]
    }
  ],
  "component_count": 2,
  "has_violation": false
}

農水省サイトスクレイピング仕様

対象サイト

農林水産省 農薬登録情報提供システム
URL: https://pesticide.maff.go.jp/

アクセスフロー

1. GET /agricultural-chemicals/name-search/
   → JSESSIONID クッキー + CSRF トークン(フォーム埋め込み)取得

2. POST /agricultural-chemicals/name-search
   Content-Type: application/x-www-form-urlencoded
   Body: _csrf=<token>&agriculturalChemicalsName=<農薬名>&agriculturalChemicalsType=
   → 302 リダイレクト先: /agricultural-chemicals/list

3. GET /agricultural-chemicals/list
   → 検索結果一覧 HTML
   → <a href="/agricultural-chemicals/details/{system_id}"> からリンク抽出

4. GET /agricultural-chemicals/details/{system_id}
   → 詳細ページ HTML → 下記データをパース

詳細ページ パース項目

基本情報テーブル(th[scope=col] + td ペア):

th テキスト 取得項目 保存先
登録番号 登録番号 registration_number
農薬の種類 種類名 pesticide_type
農薬の名称 農薬名 name
用途 用途 purpose
剤型 剤型 formulation
製剤毒性 毒性区分 toxicity

有効成分テーブル:

  • 「有効成分」行: is_active=True、成分名・含有濃度を取得
  • 「その他成分」行: is_active=False

適用表(作物×病害虫ごとの行):

各行のカラム(data-label 属性でカラム識別):

data-label 取得項目 保存先
作物名 作物名 PesticideProductLimit.crop_name
本剤の使用回数 「N回以内」から N を抽出 PesticideProductLimit.max_uses
使用時期 テキストそのまま PesticideProductLimit.use_timing_note
{成分名}を含む農薬の総使用回数 「N回以内(...)」から N と補足を抽出 PesticideIngredient.max_total_uses / use_timing_note

「総使用回数」テキストのパース規則:

入力例: "3回以内(種もみへの処理は1回以内、育苗箱散布は1回以内、本田では2回以内)"
→ max_total_uses = 3
→ use_timing_note = "種もみへの処理は1回以内、育苗箱散布は1回以内、本田では2回以内"

正規表現: r'(\d+)回以内(?:\((.+)\))?'

実装場所

apps/pesticide/management/commands/fetch_pesticide.py
Django management command として実装。APIエンドポイントから呼び出す。

注意事項

  • セッション(requests.Sessionを使用し、クッキーとCSRFを維持する
  • アクセスは農薬マスタ登録時の1件ずつに限定バルク取得は行わない
  • 農水省サイトの内部IDsystem_id)と農薬の公式登録番号は別物
  • タイムアウト: 10秒

画面仕様

農薬マスタ画面(/pesticide/

  • 登録済み農薬の一覧表示
  • 農薬名で検索 → 農水省サイトから候補を取得 → 選択して詳細取得 → 保存
  • 取得失敗時は手動入力フォームに切り替え
  • 展着剤フラグ・節減対象外フラグの編集

散布記録入力画面(/pesticide/events/new

  • 散布日・年度入力
  • 対象種別(圃場/グループ/作物/品種)選択 → 対象を選択
  • 農薬を追加(複数可): 農薬マスタから選択 + 希釈倍率 + 使用量
  • 保存時に使用回数チェックを実行し、超過がある場合は警告を表示(保存はブロックしない)

使用回数チェック画面(/pesticide/usage

  • 年度・作物でフィルタ
  • 製品使用回数テーブル: 農薬名 / 使用回数 / 上限 / 残回数(超過時は赤表示)
  • 有効成分総使用回数テーブル: 成分名 / 使用回数 / 上限 / 残回数 / 使用製品一覧(超過時は赤表示)
  • 特別栽培欄: 節減対象農薬の使用成分数(報告用)

設計判断と制約

  1. 散布対象の特定: target_type + 対象FK/文字列で柔軟に対応。作物ごとの集計は作付け計画Planと照合。
  2. 使用回数上限は作物別に保持: 同一農薬でも稲と野菜で上限が異なるため PesticideProductLimit を作物別に複数行保持。
  3. 総使用回数はテキストパース: 農水省サイトの「○○を含む農薬の総使用回数」カラムから正規表現で数値を抽出。
  4. 保存はブロックしない: 使用回数超過は警告表示のみ。農薬散布の記録は法的義務があるため、超過でも保存できるようにする。
  5. SprayEventPesticide.pesticide は PROTECT: 散布記録に使用中の農薬は削除不可。
  6. is_spreader=Trueis_non_target 扱い: 展着剤はカウント除外のため、展着剤フラグをセットすれば節減対象外フラグも自動的に True 扱いDB保存は別フィールド

ソースファイル索引(実装後に更新)

ファイル 説明
backend/apps/pesticide/models.py Pesticide, PesticideIngredient, PesticideProductLimit, SprayEvent, SprayEventPesticide
backend/apps/pesticide/serializers.py DRF シリアライザ
backend/apps/pesticide/views.py ViewSet
backend/apps/pesticide/urls.py URL ルーティング
backend/apps/pesticide/management/commands/fetch_pesticide.py 農水省スクレイパー
frontend/src/app/pesticide/page.tsx 農薬マスタ一覧・散布記録
frontend/src/app/pesticide/usage/page.tsx 使用回数チェック画面
frontend/src/lib/types.ts 型定義Pesticide, SprayEvent 等)