Findings
同一イベント内で同じ有効成分を含む複数製品を使った場合、総使用回数を過少計上します。 18_マスタードキュメント_農薬散布管理編.md:39 (line 39) では「同一有効成分を含む複数製品は合算カウント」と定義していますが、集計式は 同:251 (line 251) の COUNT(DISTINCT SprayEvent.id) です。これだと 1 回の散布で MEP剤A と MEP剤B を同時使用したケースが 2 回ではなく 1 回になります。1イベント=1回 は製品単位には合っても、有効成分の「複数製品合算」とは衝突しています。 SprayEventResolvedField を正源にしたはずなのに、設計判断がまだ旧仕様のままで矛盾しています。 集計の正源は 同:232 (line 232) で SprayEventResolvedField.crop_name_snapshot に統一されていますが、設計判断では 同:599 (line 599) に「作付け計画(Plan)と照合」と残っています。さらに 同:602 (line 602) では削除したはずの crop_snapshot / variety_snapshot をまだ保持対象として書いています。実装者がここを読むと旧設計に引っ張られます。 製品使用回数も、同一イベント内の重複明細をどう扱うかが未定義で、式とモデルが噛み合っていません。 集計式は 同:239 (line 239) の COUNT(DISTINCT SprayEvent.id) ですが、明細モデルには 同:213 (line 213) 以降で event + pesticide の一意制約がありません。つまり同じ農薬を同一イベントに 2 行入れられる設計なのに、集計では 1 回に潰れます。仕様として「同一イベント内で同一農薬は1回しか登録できない」を明記して一意制約を持たせるか、重複明細の意味を定義した方が安全です。 大筋ではかなり良くなっていて、特に「作物単位での法的管理」と「圃場ごとの正源を SprayEventResolvedField に寄せた」方向は明快でした。上の3点だけ揃えると、実装時の解釈ぶれがかなり減ります。
This commit is contained in:
@@ -220,6 +220,7 @@
|
||||
| notes | TextField | blank | 備考 |
|
||||
|
||||
- `pesticide` は PROTECT(使用済み農薬は削除不可)
|
||||
- `unique_together = ['event', 'pesticide']`(同一イベント内で同じ農薬を2回登録不可)
|
||||
|
||||
---
|
||||
|
||||
@@ -236,6 +237,8 @@
|
||||
|
||||
### 製品使用回数の集計
|
||||
|
||||
1イベント = 1散布作業 = 1回。`unique_together=['event', 'pesticide']` により同一イベント内で同一農薬は1行しか存在しないため、イベント単位でカウントして正確。
|
||||
|
||||
```
|
||||
製品使用回数(年度Y・作物C・農薬P)=
|
||||
COUNT(DISTINCT SprayEvent.id)
|
||||
@@ -244,21 +247,24 @@
|
||||
かつ SprayEvent.year = Y
|
||||
```
|
||||
|
||||
※ 1イベントで複数圃場に散布しても、そのイベントは「1回」とカウントする(1イベント=1散布作業)
|
||||
※ 1イベントで複数圃場に散布しても「1回」とカウントする(1イベント=1散布作業)
|
||||
|
||||
### 有効成分総使用回数の集計
|
||||
|
||||
有効成分の総使用回数は「製品」単位でカウントする(農薬取締法の「○○を含む農薬の総使用回数」の定義に従う)。1イベントでMEP剤AとMEP剤Bを同時使用した場合、MEP成分は **2回** カウントされる。
|
||||
|
||||
```
|
||||
有効成分総使用回数(年度Y・作物C・成分名I)=
|
||||
COUNT(DISTINCT SprayEvent.id)
|
||||
where SprayEvent に SprayEventPesticide が紐づく
|
||||
かつ SprayEventPesticide.pesticide の PesticideIngredient に
|
||||
COUNT(SprayEventPesticide)
|
||||
where SprayEventPesticide.pesticide の PesticideIngredient に
|
||||
name=I かつ is_active=True のものが存在する
|
||||
かつ SprayEventPesticide.pesticide.is_non_target=False
|
||||
かつ SprayEvent に SprayEventResolvedField(crop_name_snapshot=C) が紐づく
|
||||
かつ SprayEvent.year = Y
|
||||
かつ SprayEventPesticide.event に SprayEventResolvedField(crop_name_snapshot=C) が紐づく
|
||||
かつ SprayEventPesticide.event.year = Y
|
||||
```
|
||||
|
||||
※ `unique_together=['event', 'pesticide']` により、同一イベント内で同一農薬は重複しないため単純な COUNT で正確に合算できる
|
||||
|
||||
### 特別栽培・使用成分数の集計
|
||||
|
||||
```
|
||||
@@ -596,15 +602,16 @@ Django management command として実装。APIエンドポイントから呼び
|
||||
|
||||
## 設計判断と制約
|
||||
|
||||
1. **散布対象の特定**: `target_type` + 対象FK/文字列で柔軟に対応。作物ごとの集計は作付け計画(Plan)と照合。
|
||||
1. **散布対象の特定**: `target_type` + 対象FK/文字列で柔軟に対応。保存時に `SprayEventResolvedField` で対象圃場と作物を確定保存する。作付け計画(Plan)はあくまで保存時の解決に使うだけで、集計の正源ではない。
|
||||
2. **使用回数上限は作物別に保持**: 同一農薬でも作物ごとに上限が異なるため `PesticideProductLimit` と `PesticideIngredientLimit` を作物別に複数行保持する。
|
||||
3. **作物名の照合は別名テーブルで吸収**: 農水省表記の「稲」と内部の「水稲」のような差異を吸収するため、`PesticideCropAlias` を必須とする。
|
||||
4. **散布対象は保存時に確定保存する**: 後日のグループ名変更や作付け変更で過去実績の集計結果が変わらないよう、`SprayEventResolvedField` と `crop_snapshot` / `variety_snapshot` を保持する。
|
||||
5. **総使用回数はテキストパース**: 農水省サイトの「○○を含む農薬の総使用回数」カラムから正規表現で数値を抽出する。
|
||||
6. **保存はブロックしない**: 使用回数超過は警告表示のみ。農薬散布の記録は法的義務があるため、超過でも保存できるようにする。
|
||||
7. **`SprayEventPesticide.pesticide` は PROTECT**: 散布記録に使用中の農薬は削除不可。
|
||||
8. **成分集計は `is_active=True` のみ対象**: 「その他成分」は総使用回数・特別栽培の成分数集計に含めない。
|
||||
9. **`is_spreader=True` は `is_non_target` 扱い**: 展着剤はカウント除外のため、展着剤フラグをセットすれば節減対象外フラグも自動的に True 扱い(DB保存は別フィールド)。
|
||||
4. **散布対象は保存時に確定保存する**: 後日のグループ名変更や作付け変更で過去実績の集計結果が変わらないよう、`SprayEventResolvedField` に圃場・作物をスナップショット保存する。`SprayEvent` 自体には作物情報を持たない。
|
||||
5. **有効成分総使用回数は `SprayEventPesticide` 単位で集計する**: 1イベントでMEP剤AとMEP剤Bを同時使用した場合、MEP成分は2回とカウントする。`unique_together=['event', 'pesticide']` で重複行を防ぎ、単純な COUNT で正確に計算できる。
|
||||
6. **総使用回数はテキストパース**: 農水省サイトの「○○を含む農薬の総使用回数」カラムから正規表現で数値を抽出する。
|
||||
7. **保存はブロックしない**: 使用回数超過は警告表示のみ。農薬散布の記録は法的義務があるため、超過でも保存できるようにする。
|
||||
8. **`SprayEventPesticide.pesticide` は PROTECT**: 散布記録に使用中の農薬は削除不可。
|
||||
9. **成分集計は `is_active=True` のみ対象**: 「その他成分」は総使用回数・特別栽培の成分数集計に含めない。
|
||||
10. **`is_spreader=True` は `is_non_target` 扱い**: 展着剤はカウント除外のため、展着剤フラグをセットすれば節減対象外フラグも自動的に True 扱い(DB保存は別フィールド)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user