在庫管理機能実装案.md に ## 18. 補足: 肥料公式データ同期・あいまい検索案 を追記しました。

内容は、普通肥料を主対象に公式データをローカルDB化し、検索時はローカル検索、24時間超過時だけ裏で差分同期する という方針です。FertilizerOfficialMaster のテーブル案、既存 Fertilizer との紐づけ、検索API、同期ジョブ、特殊肥料は手入力併用にする考え方まで入れています。

今回は文書更新のみで、コード変更やテスト実行はしていません。必要なら次は、この18章をもとに models.py レベルの実装草案まで起こせます。
This commit is contained in:
Akira
2026-03-13 13:26:18 +09:00
parent 1425094107
commit 776a269d6d

View File

@@ -848,3 +848,226 @@ UI 表示例:
- 公式データの更新にも追従しやすい
- 外部サイト障害に強い
- 将来の農薬散布記録や適用チェックに発展させやすい
---
## 18. 補足: 肥料公式データ同期・あいまい検索案
肥料についても、農薬と同様に公式データをローカルDBへ取り込み、
肥料マスタ画面であいまい検索できるようにすることは可能である。
ただし、農薬と違って肥料は制度上の区分があるため、初期実装では
`普通肥料を主対象` とし、`特殊肥料や独自資材は手入力を許容する`
方針が現実的である。
### 18.1 目的
- 肥料名や登録番号を手で調べる手間を減らす
- 公式登録銘柄を候補から選べるようにする
- 既存の肥料マスタ登録を速く、正確にする
- 施肥計画で使う肥料名の表記ゆれを減らす
### 18.2 基本方針
農薬と同じく、検索時に毎回外部サイトへ直接問い合わせるのではなく、
ローカルDB検索を主とした構成を採用する。
1. 農水省の肥料登録銘柄データを取得してローカルDB化する
2. 肥料マスタ画面でのあいまい検索はローカルDBに対して行う
3. 画面表示時または検索時に、最終同期から24時間以上経過していれば更新ジョブを起動する
4. 更新ジョブでは公式データを再取得し、差分だけローカルDBに反映する
5. 更新完了後、候補データを再読み込みする
### 18.3 適用範囲
初期対象:
- 普通肥料
- 登録銘柄検索システムで取得できる肥料
初期対象外または要個別対応:
- 特殊肥料
- 堆肥
- 土壌改良資材
- 地域独自資材
- 登録制度外の取扱資材
このため、肥料マスタ画面では以下の2方式を共存させるのがよい。
- `公式候補から選ぶ`
- `手入力で登録する`
### 18.4 追加テーブル案
#### FertilizerOfficialMaster
公式肥料データの取り込み先となるローカル参照テーブル。
想定フィールド:
- `id`
- `registration_no` 登録番号
- `name` 銘柄名
- `fertilizer_type` 普通肥料区分
- `brand_name` 商品名に相当する表記
- `holder_name` 登録業者名
- `guaranteed_nitrogen_pct`
- `guaranteed_phosphorus_pct`
- `guaranteed_potassium_pct`
- `guaranteed_other_text`
- `source_updated_at`
- `last_synced_at`
- `is_active`
- `raw_payload`
用途:
- 肥料あいまい検索の検索元
- 肥料マスタ作成時の候補データ
- 将来の施肥計画での成分初期値補完
#### OfficialDataSyncStatus
既に 17章で定義した同期管理テーブルを共用する。
`source_name` の例:
- `famic_pesticide`
- `maff_fertilizer`
### 18.5 肥料マスタとの紐づけ案
既存 `Fertilizer` モデルには、公式参照用として以下の項目追加を検討する。
- `official_master = ForeignKey(FertilizerOfficialMaster, null=True, blank=True, on_delete=SET_NULL)`
- `registration_no`
- `official_name`
- `holder_name`
また、既存の以下の項目は、公式候補選択時に初期値として自動入力できる。
- `name`
- `maker`
- `nitrogen_pct`
- `phosphorus_pct`
- `potassium_pct`
運用方針:
- 公式候補を選んだら、その時点の名称や登録番号を `Fertilizer` 側にもコピー保持する
- 後で公式マスタの表記が変わっても、登録済みの肥料マスタは勝手に変えない
- ユーザーが手で微修正したい場合は上書きを許可する
### 18.6 同期ジョブ案
初期実装では以下を推奨する。
- `python manage.py sync_fertilizer_official_master`
同期処理の流れ:
1. `OfficialDataSyncStatus(source_name='maff_fertilizer')` を確認する
2. 実行中なら二重起動しない
3. 公式データを取得する
4. 取得データを正規化する
5. `registration_no` を主キー相当として差分比較する
6. 新規追加、更新、失効を反映する
7. 同期結果を記録する
### 18.7 差分更新ルール
差分更新は以下の基準を推奨する。
- `registration_no` が未登録なら新規追加
- `registration_no` が既存で、名称、業者名、保証成分値などが変わっていれば更新
- 公式データから消えた場合は即削除せず `is_active=False` にする
補足:
- 実運用では、過去に使っていた肥料も履歴上残したい可能性が高い
- そのため、物理削除ではなく論理無効化が安全である
### 18.8 あいまい検索 API 案
- `GET /api/materials/fertilizer-official-search/?q=`
レスポンス例:
```json
{
"items": [
{
"id": 5678,
"registration_no": "生第12345号",
"name": "コシヒカリ専用一発肥料",
"holder_name": "サンプル肥料株式会社",
"guaranteed_nitrogen_pct": "14.00",
"guaranteed_phosphorus_pct": "12.00",
"guaranteed_potassium_pct": "12.00",
"is_active": true
}
],
"sync": {
"last_succeeded_at": "2026-03-13T08:10:00Z",
"refresh_started": true
}
}
```
API の考え方:
- 検索結果は必ずローカルDBから返す
- 同時に同期必要性を判定する
- 同期が必要ならバックグラウンド更新を開始する
- API レスポンスには同期状態を含める
### 18.9 フロントエンド動作案
肥料マスタ画面での検索 UI は以下の流れを推奨する。
1. ユーザーが 2〜3 文字入力する
2. 300ms 程度の debounce 後に検索 API を呼ぶ
3. ローカルDBの候補を即表示する
4. `refresh_started=true` の場合は「公式データ更新中」と小さく表示する
5. 候補選択時に、名称、登録番号、メーカー、成分値をフォームへ自動入力する
6. 必要なら `capacity_kg` だけユーザーが補完する
理由:
- 肥料の 1袋重量は流通単位や運用上の入力が必要な場合がある
- 公式データだけでは既存施肥計画に必要な値が必ず揃うとは限らない
### 18.10 失敗時のフォールバック
外部取得に失敗しても、画面は止めない。
想定動作:
- 検索結果は直近のローカルDBをそのまま返す
- 同期失敗はログと同期状態テーブルに記録する
- ユーザーは手入力登録へ切り替えられる
### 18.11 初期実装のスコープ
初期フェーズでは、以下までで十分である。
- 公式肥料マスタのローカルDB化
- 24時間単位の同期判定
- ローカルDBに対するあいまい検索
- 候補選択による名称、登録番号、成分値の自動入力
初期フェーズでは見送ってよいもの:
- 特殊肥料の網羅的取り込み
- 施肥計画との自動引当
- 肥料成分の高度な比較ロジック
- 取扱単位の自動変換
### 18.12 この案のメリット
- 肥料マスタ登録が速くなる
- 肥料名や成分の入力ミスを減らせる
- 施肥計画で使う肥料情報の標準化が進む
- 農薬と同じ UX パターンで実装できる
- 将来の購入管理や必要量算出にもつなげやすい