施肥計画機能を追加(年度×品種単位のマトリクス管理)
- Backend: apps/fertilizer を新規追加 - Fertilizer(肥料マスタ)、FertilizationPlan、FertilizationEntry モデル - 肥料マスタ・施肥計画 CRUD API - 3方式の自動計算API(反当袋数・均等配分・反当チッソ成分量) - 作付け計画から圃場候補を取得する API - WeasyPrint による PDF 出力(圃場×肥料=袋数 マトリクス表) - Frontend: app/fertilizer を新規追加 - 施肥計画一覧(年度セレクタ・PDF出力・編集・削除) - 肥料マスタ管理(インライン編集) - 施肥計画編集(品種選択→圃場自動取得→肥料追加→自動計算→マトリクス手動調整) - Navbar に「施肥計画」メニューを追加(Sprout アイコン) - Cursor ルールファイル・連携ガイドを削除(Claude Code 単独運用へ) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
67
backend/apps/fertilizer/migrations/0001_initial.py
Normal file
67
backend/apps/fertilizer/migrations/0001_initial.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# Generated by Django 5.0 on 2026-03-01 02:50
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('fields', '0006_e1c_chusankan_17_fields'),
|
||||
('plans', '0004_crop_base_temp'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Fertilizer',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True, verbose_name='肥料名')),
|
||||
('maker', models.CharField(blank=True, max_length=100, null=True, verbose_name='メーカー')),
|
||||
('capacity_kg', models.DecimalField(blank=True, decimal_places=3, max_digits=8, null=True, verbose_name='1袋重量(kg)')),
|
||||
('nitrogen_pct', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True, verbose_name='窒素含有率(%)')),
|
||||
('phosphorus_pct', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True, verbose_name='リン酸含有率(%)')),
|
||||
('potassium_pct', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True, verbose_name='カリ含有率(%)')),
|
||||
('notes', models.TextField(blank=True, null=True, verbose_name='備考')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '肥料マスタ',
|
||||
'verbose_name_plural': '肥料マスタ',
|
||||
'ordering': ['name'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FertilizationPlan',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200, verbose_name='計画名')),
|
||||
('year', models.IntegerField(verbose_name='年度')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('variety', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='fertilization_plans', to='plans.variety', verbose_name='品種')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '施肥計画',
|
||||
'verbose_name_plural': '施肥計画',
|
||||
'ordering': ['-year', 'variety'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FertilizationEntry',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('bags', models.DecimalField(decimal_places=2, max_digits=8, verbose_name='袋数')),
|
||||
('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fields.field', verbose_name='圃場')),
|
||||
('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='entries', to='fertilizer.fertilizationplan')),
|
||||
('fertilizer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fertilizer.fertilizer', verbose_name='肥料')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '施肥エントリ',
|
||||
'verbose_name_plural': '施肥エントリ',
|
||||
'ordering': ['field', 'fertilizer'],
|
||||
'unique_together': {('plan', 'field', 'fertilizer')},
|
||||
},
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user