移動した圃場の施肥計画画面での扱いについて #11

Closed
opened 2026-04-05 08:47:28 +00:00 by akira · 8 comments
Owner

現在の状態(なぜOpenか)

(1行で)

次にすること(Next Action)

(1行で)

ブロック要因

(なければ「なし」)


問題の概要

再現手順

#10で、作付け計画は表示されるようになりましたが、足川北上の品種を「にこまる」から「たちはるか特栽」に変更
施肥計画を表示
2026年度 たちはるか 施肥計画(品種変更移動) | 水稲 / たちはるか
が増えている
「2026年度 たちはるか 施肥計画(品種変更移動」の編集ボタンを押す
リン酸グアノと仁井田米有機が見えている

「にこまる」の編集ボタンを押す
足川北上が存在し、
ミネラルホウ素、 リン酸グアノ、仁井田米有機、電気炉さい
がいずれも入力可能

期待する動作

移動したのだから、「にこまる」の足川北上は消えてなければならないのでは?
2026年度 たちはるか 施肥計画(品種変更移動には、値が設定してあったミネラルホウ素、電気炉さいも表示されていないといけないのでは?

実際の動作

関連

## 現在の状態(なぜOpenか) (1行で) ## 次にすること(Next Action) (1行で) ## ブロック要因 (なければ「なし」) --- ## 問題の概要 ## 再現手順 #10で、作付け計画は表示されるようになりましたが、足川北上の品種を「にこまる」から「たちはるか特栽」に変更 施肥計画を表示 2026年度 たちはるか 施肥計画(品種変更移動) | 水稲 / たちはるか が増えている 「2026年度 たちはるか 施肥計画(品種変更移動」の編集ボタンを押す リン酸グアノと仁井田米有機が見えている 「にこまる」の編集ボタンを押す 足川北上が存在し、 ミネラルホウ素、 リン酸グアノ、仁井田米有機、電気炉さい がいずれも入力可能 ## 期待する動作 移動したのだから、「にこまる」の足川北上は消えてなければならないのでは? 2026年度 たちはるか 施肥計画(品種変更移動には、値が設定してあったミネラルホウ素、電気炉さいも表示されていないといけないのでは? ## 実際の動作 ## 関連
Author
Owner

調査結果です。実データと実装の両方で確認しました。

直接確認できた事実

対象圃場 足川北上 の 2026 年施肥計画 entry を確認すると、現在は次の状態でした。

旧計画: にこまる

  • ミネラルホウ素: bags=4.00, actual_bags=4.0000
  • 電気炉さい: bags=2.00, actual_bags=2.0000

新計画: 2026年度 たちはるか 施肥計画(品種変更移動)

  • リン酸グアノ: bags=3.00, actual_bags=None
  • 仁井田米有機: bags=6.00, actual_bags=None

また、PlanVarietyChange には以下が記録されていました。

  • old_variety: にこまる
  • new_variety: たちはるか
  • fertilizer_moved_entry_count: 2

実装との対応

現在の移動ロジックは backend/apps/fertilizer/services.pymove_unspread_entries_for_variety_change() で、actual_bags IS NULL の entry だけを新品種計画へ移動します。

したがって今回の結果は、実装と一致しています。

  • リン酸グアノ仁井田米有機 は未散布なので新計画へ移動
  • ミネラルホウ素電気炉さいactual_bags が入っているので旧計画に残留

画面上そう見える理由

施肥計画編集画面は、表示対象圃場を「その plan に存在する entry から組み立て」ています。
そのため:

  • 旧計画にはまだ 足川北上 の entry が 2 件残っているので、圃場自体が表示されます
  • 新計画には移動した 2 件しか無いので、その 2 肥料だけ表示されます

現時点の整理

今回の挙動はコード不整合ではなく、「未散布 entry のみ移動する」という現在仕様の結果です。

一方で、issue に書かれている期待動作は次のどちらかを意味しています。

  1. 散布済み entry も含めて、圃場単位で施肥計画を丸ごと新品種へ移す
  2. 旧計画には散布済み履歴だけ残しつつ、編集画面では未散布対象だけ見せる

どちらを正とするかで次の対応が変わります。少なくとも現状は「仕様どおり動いているが、UI/仕様の見え方に違和感がある」状態です。

調査結果です。実データと実装の両方で確認しました。 ## 直接確認できた事実 対象圃場 `足川北上` の 2026 年施肥計画 entry を確認すると、現在は次の状態でした。 ### 旧計画: `にこまる` - ミネラルホウ素: `bags=4.00`, `actual_bags=4.0000` - 電気炉さい: `bags=2.00`, `actual_bags=2.0000` ### 新計画: `2026年度 たちはるか 施肥計画(品種変更移動)` - リン酸グアノ: `bags=3.00`, `actual_bags=None` - 仁井田米有機: `bags=6.00`, `actual_bags=None` また、`PlanVarietyChange` には以下が記録されていました。 - old_variety: `にこまる` - new_variety: `たちはるか` - fertilizer_moved_entry_count: `2` ## 実装との対応 現在の移動ロジックは [backend/apps/fertilizer/services.py](/akira/keinasystem/src/branch/main/backend/apps/fertilizer/services.py) の `move_unspread_entries_for_variety_change()` で、**`actual_bags IS NULL` の entry だけを新品種計画へ移動**します。 したがって今回の結果は、実装と一致しています。 - `リン酸グアノ` と `仁井田米有機` は未散布なので新計画へ移動 - `ミネラルホウ素` と `電気炉さい` は `actual_bags` が入っているので旧計画に残留 ## 画面上そう見える理由 施肥計画編集画面は、表示対象圃場を「その plan に存在する entry から組み立て」ています。 そのため: - 旧計画にはまだ `足川北上` の entry が 2 件残っているので、圃場自体が表示されます - 新計画には移動した 2 件しか無いので、その 2 肥料だけ表示されます ## 現時点の整理 今回の挙動はコード不整合ではなく、**「未散布 entry のみ移動する」という現在仕様の結果**です。 一方で、issue に書かれている期待動作は次のどちらかを意味しています。 1. 散布済み entry も含めて、圃場単位で施肥計画を丸ごと新品種へ移す 2. 旧計画には散布済み履歴だけ残しつつ、編集画面では未散布対象だけ見せる どちらを正とするかで次の対応が変わります。少なくとも現状は「仕様どおり動いているが、UI/仕様の見え方に違和感がある」状態です。
Author
Owner

仕様の整理としては、少なくとも次の 2 案に明示的に分けるのが妥当だと思います。

A案

旧計画には散布済みのものを残し、未散布のものだけ新計画へ移動する。
移動した未散布 entry は旧計画から削除する。

利点

  • 旧品種前提で実施した散布履歴をそのまま保持できる
  • 実績・在庫・RESERVE の履歴整合を守りやすい

欠点

  • 同じ圃場が旧計画と新計画の両方に見える場合がある
  • 施肥計画編集画面の見せ方を工夫しないと違和感が残る

B案

旧計画から圃場ごと消し、新計画へ全部移動する。

利点

  • 現在の計画としては非常に分かりやすい
  • 旧計画側に対象圃場が残らないので、画面上の混乱が少ない

欠点

  • 旧品種前提で散布した実績まで新品種計画側へ移る
  • 履歴の意味づけが弱くなり、変更履歴表示や監査ログをより厚くしないと後から読み解きにくい

現状実装との関係

今の実装は A案に寄せています。
ただし UI は A案向けに最適化されていないため、旧計画・新計画の両方に圃場が見えることで違和感が出ています。

私の見立て

履歴整合を優先するなら A案、画面の分かりやすさを優先するなら B案です。
施肥実績・RESERVE・在庫引当まで扱っている現行システムでは、基本は A案の方が安全だと思います。
ただし A案を採るなら、旧計画編集画面は「今後編集する計画」ではなく「散布済み履歴を含む計画」として見せ方を再設計した方がよいです。

仕様の整理としては、少なくとも次の 2 案に明示的に分けるのが妥当だと思います。 ## A案 旧計画には散布済みのものを残し、未散布のものだけ新計画へ移動する。 移動した未散布 entry は旧計画から削除する。 ### 利点 - 旧品種前提で実施した散布履歴をそのまま保持できる - 実績・在庫・RESERVE の履歴整合を守りやすい ### 欠点 - 同じ圃場が旧計画と新計画の両方に見える場合がある - 施肥計画編集画面の見せ方を工夫しないと違和感が残る ## B案 旧計画から圃場ごと消し、新計画へ全部移動する。 ### 利点 - 現在の計画としては非常に分かりやすい - 旧計画側に対象圃場が残らないので、画面上の混乱が少ない ### 欠点 - 旧品種前提で散布した実績まで新品種計画側へ移る - 履歴の意味づけが弱くなり、変更履歴表示や監査ログをより厚くしないと後から読み解きにくい ## 現状実装との関係 今の実装は A案に寄せています。 ただし UI は A案向けに最適化されていないため、旧計画・新計画の両方に圃場が見えることで違和感が出ています。 ## 私の見立て 履歴整合を優先するなら A案、画面の分かりやすさを優先するなら B案です。 施肥実績・RESERVE・在庫引当まで扱っている現行システムでは、基本は A案の方が安全だと思います。 ただし A案を採るなら、旧計画編集画面は「今後編集する計画」ではなく「散布済み履歴を含む計画」として見せ方を再設計した方がよいです。
Author
Owner

B案を採るなら、変更履歴は別建てで持つのがよいと思います。

ただし、この履歴は「旧品種→新品種に変えた」という差分メモでは足りず、旧計画時点の状態を再現できる情報を持つ必要があります。

なぜそこまで必要か

B案では、旧計画から圃場ごと消して新計画へ全部移すため、日常画面からは旧状態が見えなくなります。
そのため履歴側で、少なくとも「変更前に何が設定されていたか」を後から辿れないと、監査・確認・説明ができません。

現時点の考え方

履歴側には、旧計画時に設定されていた情報をできるだけ網羅して保存する必要があります。
しかも、今ある項目だけではなく、将来項目が増えることも考えると、個別カラムの羅列だけでは追いつかない可能性があります。

そのため、実装方針としては次のようなイメージです。

  • 変更イベント本体
    • old_variety / new_variety / changed_at / changed_by など
  • 旧計画のスナップショット
    • 計画ヘッダ情報一式
    • entry 一式
    • actual_bags
    • calc_settings
    • その時点で画面や業務上意味を持つ関連情報

つまり、「差分記録」よりも「変更前状態の丸ごと保存」に寄せる方が安全です。

補足

このスナップショットでどこまで持つかは、実装してみると過不足が見える可能性があります。
したがって、現時点では完全確定というより、まずは「旧計画状態を再現できること」を目標にして設計し、実装後に必要に応じて見直す前提でよいと思います。

B案を採るなら、変更履歴は別建てで持つのがよいと思います。 ただし、この履歴は「旧品種→新品種に変えた」という差分メモでは足りず、**旧計画時点の状態を再現できる情報**を持つ必要があります。 ## なぜそこまで必要か B案では、旧計画から圃場ごと消して新計画へ全部移すため、日常画面からは旧状態が見えなくなります。 そのため履歴側で、少なくとも「変更前に何が設定されていたか」を後から辿れないと、監査・確認・説明ができません。 ## 現時点の考え方 履歴側には、旧計画時に設定されていた情報をできるだけ網羅して保存する必要があります。 しかも、今ある項目だけではなく、将来項目が増えることも考えると、個別カラムの羅列だけでは追いつかない可能性があります。 そのため、実装方針としては次のようなイメージです。 - 変更イベント本体 - old_variety / new_variety / changed_at / changed_by など - 旧計画のスナップショット - 計画ヘッダ情報一式 - entry 一式 - actual_bags - calc_settings - その時点で画面や業務上意味を持つ関連情報 つまり、「差分記録」よりも「変更前状態の丸ごと保存」に寄せる方が安全です。 ## 補足 このスナップショットでどこまで持つかは、実装してみると過不足が見える可能性があります。 したがって、現時点では完全確定というより、まずは「旧計画状態を再現できること」を目標にして設計し、実装後に必要に応じて見直す前提でよいと思います。
Author
Owner

議論の結論

栽培記録の観点からA案が業務上成立しないことが判明

将来実装予定の栽培記録では「ある圃場・ある年度に何を施用したか」を集計する。
A案(散布済みentryを旧計画に残す)のままでは、同じ圃場・同じ年度のentryが複数の品種計画に分裂する。

例:

  • にこまる計画 → 足川北上のミネラルホウ素・電気炉さい(散布済み)
  • たちはるか計画 → 足川北上のリン酸グアノ・仁井田米有機(未散布)

「足川北上で今年作ったのはたちはるか特栽」なので、施用肥料の記録は全てたちはるか特栽に紐づくべき。
A案では栽培記録実装時に「品種変更があった圃場かどうか」を特別処理しなければならず、設計の足かせになる。

決定: B案(圃場ごと全entry移動)に変更する

  • 散布済み・未散布を問わず、対象圃場のentryを全て新品種計画へ移動する
  • move_unspread_entries_for_variety_changeactual_bags IS NULL フィルタを外す
  • 改善案/issue_3_計画始動後の作付け変更_調査.md の確定仕様をB案に更新する

スナップショットについて

コメント558で指摘された「旧計画状態の丸ごと保存」は、将来必要になった時点で追加する。
現時点では PlanVarietyChange(いつ・どの圃場・どの品種から→どの品種へ・移動件数)で最低限の監査は可能。

次のアクション

  • 改善案/issue_3_計画始動後の作付け変更_調査.md の確定仕様をB案に更新
  • move_unspread_entries_for_variety_change を全entry移動に変更
  • テストを更新(散布済みentryも移動することを検証するケースに差し替え)
## 議論の結論 ### 栽培記録の観点からA案が業務上成立しないことが判明 将来実装予定の栽培記録では「ある圃場・ある年度に何を施用したか」を集計する。 A案(散布済みentryを旧計画に残す)のままでは、同じ圃場・同じ年度のentryが複数の品種計画に分裂する。 例: - にこまる計画 → 足川北上のミネラルホウ素・電気炉さい(散布済み) - たちはるか計画 → 足川北上のリン酸グアノ・仁井田米有機(未散布) 「足川北上で今年作ったのはたちはるか特栽」なので、施用肥料の記録は全てたちはるか特栽に紐づくべき。 A案では栽培記録実装時に「品種変更があった圃場かどうか」を特別処理しなければならず、設計の足かせになる。 ### 決定: B案(圃場ごと全entry移動)に変更する - 散布済み・未散布を問わず、対象圃場のentryを全て新品種計画へ移動する - `move_unspread_entries_for_variety_change` の `actual_bags IS NULL` フィルタを外す - `改善案/issue_3_計画始動後の作付け変更_調査.md` の確定仕様をB案に更新する ### スナップショットについて コメント558で指摘された「旧計画状態の丸ごと保存」は、将来必要になった時点で追加する。 現時点では `PlanVarietyChange`(いつ・どの圃場・どの品種から→どの品種へ・移動件数)で最低限の監査は可能。 ### 次のアクション - [ ] `改善案/issue_3_計画始動後の作付け変更_調査.md` の確定仕様をB案に更新 - [ ] `move_unspread_entries_for_variety_change` を全entry移動に変更 - [ ] テストを更新(散布済みentryも移動することを検証するケースに差し替え)
Author
Owner

B案について、さらに変更できるかどうか検討してください。
今、作付け計画で品種を変更した場合、新たな施肥計画が出来ますが、
これを既存の施肥計画にマージする事は可能でしょうか?

B案について、さらに変更できるかどうか検討してください。 今、作付け計画で品種を変更した場合、新たな施肥計画が出来ますが、 これを既存の施肥計画にマージする事は可能でしょうか?
Author
Owner

追加案として、次の運用が現実的だと思います。

運用案

  1. 品種変更時は、まず従来どおり専用の「品種変更移動 plan」を自動作成する
  2. その後、必要に応じてユーザーが「マージ先 plan」を明示的に指定して統合する

この案の利点

  • 品種変更時の自動処理は単純に保てる
  • 同一年・同品種に既存 plan が複数ある場合でも、誤って自動マージしない
  • マージ時に競合解決ルールを出せる

なぜこの案が安全か

現状の施肥計画は、同一年・同品種でも複数 plan が存在しうる。
そのため「既存 plan へ自動マージ」は、どの plan に寄せるべきか自動で決めにくい。

また、マージ先に同じ field + fertilizer の entry が存在する場合は、

  • 加算するのか
  • 移動元を優先するのか
  • 移動先を優先するのか
  • 競合として止めるのか

を明示的に決める必要がある。

実装イメージ

  • 品種変更時
    • 2026年度 たちはるか(特栽) 施肥計画(品種変更移動) のような専用 plan を自動作成
  • 後から施肥計画画面で
    • 「既存計画へマージ」操作を実行
    • マージ先 plan を選択
    • 競合がある場合は確認して統合
    • 完了後、移動 plan が空になれば削除
    • 新旧 plan の RESERVE を再生成

この方式なら、「品種変更時の自動処理」と「既存計画への統合判断」を分離できるため、現状のデータ構造にはかなり合っていると思います。

追加案として、次の運用が現実的だと思います。 ## 運用案 1. 品種変更時は、まず従来どおり専用の「品種変更移動 plan」を自動作成する 2. その後、必要に応じてユーザーが「マージ先 plan」を明示的に指定して統合する ## この案の利点 - 品種変更時の自動処理は単純に保てる - 同一年・同品種に既存 plan が複数ある場合でも、誤って自動マージしない - マージ時に競合解決ルールを出せる ## なぜこの案が安全か 現状の施肥計画は、同一年・同品種でも複数 plan が存在しうる。 そのため「既存 plan へ自動マージ」は、どの plan に寄せるべきか自動で決めにくい。 また、マージ先に同じ `field + fertilizer` の entry が存在する場合は、 - 加算するのか - 移動元を優先するのか - 移動先を優先するのか - 競合として止めるのか を明示的に決める必要がある。 ## 実装イメージ - 品種変更時 - `2026年度 たちはるか(特栽) 施肥計画(品種変更移動)` のような専用 plan を自動作成 - 後から施肥計画画面で - 「既存計画へマージ」操作を実行 - マージ先 plan を選択 - 競合がある場合は確認して統合 - 完了後、移動 plan が空になれば削除 - 新旧 plan の RESERVE を再生成 この方式なら、「品種変更時の自動処理」と「既存計画への統合判断」を分離できるため、現状のデータ構造にはかなり合っていると思います。
Author
Owner

レビュー反映です。

競合時の方針

競合時のルールは 「止める」 を採るのがよいと思います。

理由:
同一 圃場 × 肥料 が移動元 plan と移動先 plan の両方に存在するケースは、
「旧品種向けに一度計画した後、品種変更後に新品種向けとして同じ肥料を別意図で計画した」可能性が高く、
bags を単純に加算したり自動上書きしたりすると業務意味を壊しやすいためです。

したがって、競合時は自動マージせず、ユーザーに見直してもらう前提にするのが安全です。

競合発生時の想定アクション

  1. ユーザーが移動先 plan 側の該当 entry を消す
  2. ユーザーが移動元 plan 側の該当 entry を消す
  3. ユーザーが作付け計画自体を見直す

空になった移動 plan の後始末

「完了後、移動 plan が空になれば削除」とする場合は、plan 本体だけではなく、
その plan に紐づく RESERVE などの関連データも合わせて削除することを設計に明示しておくべきです。

現行実装では delete_reserves_for_plan があるため、RESERVE の後始末は既存ロジックで対応可能です。
必要なら WorkRecord 等の関連も確認対象に含めます。

レビュー反映です。 ## 競合時の方針 競合時のルールは **「止める」** を採るのがよいと思います。 理由: 同一 `圃場 × 肥料` が移動元 plan と移動先 plan の両方に存在するケースは、 「旧品種向けに一度計画した後、品種変更後に新品種向けとして同じ肥料を別意図で計画した」可能性が高く、 `bags` を単純に加算したり自動上書きしたりすると業務意味を壊しやすいためです。 したがって、競合時は自動マージせず、ユーザーに見直してもらう前提にするのが安全です。 ### 競合発生時の想定アクション 1. ユーザーが移動先 plan 側の該当 entry を消す 2. ユーザーが移動元 plan 側の該当 entry を消す 3. ユーザーが作付け計画自体を見直す ## 空になった移動 plan の後始末 「完了後、移動 plan が空になれば削除」とする場合は、plan 本体だけではなく、 その plan に紐づく RESERVE などの関連データも合わせて削除することを設計に明示しておくべきです。 現行実装では `delete_reserves_for_plan` があるため、RESERVE の後始末は既存ロジックで対応可能です。 必要なら WorkRecord 等の関連も確認対象に含めます。
Author
Owner

議論と実装が完了したためクローズします。

確定仕様(B案)

  • 散布済み・未散布を問わず、対象圃場のentryを全件新品種計画へ移動する
  • 栽培記録の将来実装との整合性を優先(同一圃場の実績が複数品種計画に分裂しない)

マージ機能の仕様

  • 品種変更時は自動で「品種変更移動 plan」を作成
  • 後から施肥計画画面の「既存計画へマージ」操作で統合可能
  • 競合(同一 圃場x肥料 が両planに存在)時は実行を止めてユーザーに確認を求める

対応コミット

  • c675b7b Move all fertilization entries on variety change
  • c90c621 Add fertilization plan merge workflow
議論と実装が完了したためクローズします。 ## 確定仕様(B案) - 散布済み・未散布を問わず、対象圃場のentryを全件新品種計画へ移動する - 栽培記録の将来実装との整合性を優先(同一圃場の実績が複数品種計画に分裂しない) ## マージ機能の仕様 - 品種変更時は自動で「品種変更移動 plan」を作成 - 後から施肥計画画面の「既存計画へマージ」操作で統合可能 - 競合(同一 圃場x肥料 が両planに存在)時は実行を止めてユーザーに確認を求める ## 対応コミット - c675b7b Move all fertilization entries on variety change - c90c621 Add fertilization plan merge workflow
akira closed this issue 2026-04-07 01:24:29 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: akira/keinasystem#11