施肥計画の計算設定を保存・復元し、未入力圃場のみ計算オプションを追加
- FertilizationPlanにcalc_settings JSONFieldを追加(migration 0004) - 編集画面を開くと前回の計算方式・パラメータが復元される - 「未入力圃場のみ」チェックで既存値を保持したまま新規圃場だけ計算可能 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -91,7 +91,13 @@ export default function FertilizerEditPage({ planId }: { planId?: number }) {
|
||||
const fertIds = Array.from(new Set(plan.entries.map((e) => e.fertilizer)));
|
||||
const ferts = fertsRes.data.filter((f: Fertilizer) => fertIds.includes(f.id));
|
||||
setPlanFertilizers(ferts);
|
||||
setCalcSettings(ferts.map((f: Fertilizer) => ({ fertilizer_id: f.id, method: 'per_tan' as CalcMethod, param: '' })));
|
||||
// 保存済み計算設定を復元、なければデフォルト値
|
||||
setCalcSettings(ferts.map((f: Fertilizer) => {
|
||||
const saved = plan.calc_settings?.find((s) => s.fertilizer_id === f.id);
|
||||
return saved
|
||||
? { fertilizer_id: f.id, method: saved.method as CalcMethod, param: saved.param }
|
||||
: { fertilizer_id: f.id, method: 'per_tan' as CalcMethod, param: '' };
|
||||
}));
|
||||
|
||||
const fieldIds = Array.from(new Set(plan.entries.map((e) => e.field)));
|
||||
const fields = fieldsRes.data.filter((f: Field) => fieldIds.includes(f.id));
|
||||
@@ -172,17 +178,29 @@ export default function FertilizerEditPage({ planId }: { planId?: number }) {
|
||||
setAdjusted((prev) => { const next = { ...prev }; delete next[id]; return next; });
|
||||
};
|
||||
|
||||
const [calcNewOnly, setCalcNewOnly] = useState(true);
|
||||
|
||||
// ─── 自動計算
|
||||
const runCalc = async (setting: CalcSetting) => {
|
||||
if (!setting.param) return alert('パラメータを入力してください');
|
||||
if (selectedFields.length === 0) return alert('対象圃場を選択してください');
|
||||
|
||||
const targetFields = calcNewOnly
|
||||
? selectedFields.filter((f) => {
|
||||
const hasAdjusted = adjusted[f.id]?.[setting.fertilizer_id] !== undefined;
|
||||
const hasCalc = calcMatrix[f.id]?.[setting.fertilizer_id] !== undefined;
|
||||
return !hasAdjusted && !hasCalc;
|
||||
})
|
||||
: selectedFields;
|
||||
|
||||
if (targetFields.length === 0) return alert('未入力の圃場がありません。「全圃場」で実行してください。');
|
||||
|
||||
try {
|
||||
const res = await api.post('/fertilizer/calculate/', {
|
||||
method: setting.method,
|
||||
param: parseFloat(setting.param),
|
||||
fertilizer_id: setting.fertilizer_id,
|
||||
field_ids: selectedFields.map((f) => f.id),
|
||||
field_ids: targetFields.map((f) => f.id),
|
||||
});
|
||||
const results: { field_id: number; bags: number }[] = res.data;
|
||||
|
||||
@@ -311,7 +329,7 @@ export default function FertilizerEditPage({ planId }: { planId?: number }) {
|
||||
|
||||
setSaving(true);
|
||||
try {
|
||||
const payload = { name, year, variety: varietyId, entries };
|
||||
const payload = { name, year, variety: varietyId, calc_settings: calcSettings, entries };
|
||||
if (isNew) {
|
||||
await api.post('/fertilizer/plans/', payload);
|
||||
} else {
|
||||
@@ -481,12 +499,23 @@ export default function FertilizerEditPage({ planId }: { planId?: number }) {
|
||||
<div className="bg-white rounded-lg shadow p-4 mb-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-sm font-semibold text-gray-700">自動計算設定</h2>
|
||||
<button
|
||||
onClick={() => setShowFertPicker(true)}
|
||||
className="flex items-center gap-1 text-xs text-green-600 hover:text-green-800 border border-green-300 rounded px-2 py-1"
|
||||
>
|
||||
<Plus className="h-3 w-3" />肥料を追加
|
||||
</button>
|
||||
<div className="flex items-center gap-3">
|
||||
<label className="flex items-center gap-1.5 text-xs text-gray-600 cursor-pointer select-none">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={calcNewOnly}
|
||||
onChange={(e) => setCalcNewOnly(e.target.checked)}
|
||||
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
未入力圃場のみ
|
||||
</label>
|
||||
<button
|
||||
onClick={() => setShowFertPicker(true)}
|
||||
className="flex items-center gap-1 text-xs text-green-600 hover:text-green-800 border border-green-300 rounded px-2 py-1"
|
||||
>
|
||||
<Plus className="h-3 w-3" />肥料を追加
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{planFertilizers.length === 0 ? (
|
||||
<p className="text-sm text-gray-400">肥料を追加してください</p>
|
||||
|
||||
Reference in New Issue
Block a user