from django.db import models class Fertilizer(models.Model): name = models.CharField(max_length=100, unique=True, verbose_name='肥料名') maker = models.CharField(max_length=100, blank=True, null=True, verbose_name='メーカー') capacity_kg = models.DecimalField( max_digits=8, decimal_places=3, blank=True, null=True, verbose_name='1袋重量(kg)' ) nitrogen_pct = models.DecimalField( max_digits=5, decimal_places=2, blank=True, null=True, verbose_name='窒素含有率(%)' ) phosphorus_pct = models.DecimalField( max_digits=5, decimal_places=2, blank=True, null=True, verbose_name='リン酸含有率(%)' ) potassium_pct = models.DecimalField( max_digits=5, decimal_places=2, blank=True, null=True, verbose_name='カリ含有率(%)' ) notes = models.TextField(blank=True, null=True, verbose_name='備考') material = models.OneToOneField( 'materials.Material', on_delete=models.SET_NULL, null=True, blank=True, related_name='legacy_fertilizer', verbose_name='資材マスタ', ) class Meta: verbose_name = '肥料マスタ' verbose_name_plural = '肥料マスタ' ordering = ['name'] def __str__(self): return self.name class FertilizationPlan(models.Model): name = models.CharField(max_length=200, verbose_name='計画名') year = models.IntegerField(verbose_name='年度') variety = models.ForeignKey( 'plans.Variety', on_delete=models.PROTECT, related_name='fertilization_plans', verbose_name='品種' ) calc_settings = models.JSONField(default=list, blank=True, verbose_name='計算設定') is_confirmed = models.BooleanField(default=False, verbose_name='散布確定済み') confirmed_at = models.DateTimeField(null=True, blank=True, verbose_name='散布確定日時') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: verbose_name = '施肥計画' verbose_name_plural = '施肥計画' ordering = ['-year', 'variety'] def __str__(self): return f"{self.year} {self.name}" class FertilizationEntry(models.Model): """圃場 × 肥料 × 袋数 の中間テーブル""" plan = models.ForeignKey( FertilizationPlan, on_delete=models.CASCADE, related_name='entries' ) field = models.ForeignKey( 'fields.Field', on_delete=models.CASCADE, verbose_name='圃場' ) fertilizer = models.ForeignKey( Fertilizer, on_delete=models.PROTECT, verbose_name='肥料' ) bags = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='袋数') class Meta: verbose_name = '施肥エントリ' verbose_name_plural = '施肥エントリ' unique_together = [['plan', 'field', 'fertilizer']] ordering = ['field', 'fertilizer'] def __str__(self): return f"{self.plan} / {self.field} / {self.fertilizer}: {self.bags}袋" class DistributionPlan(models.Model): """分配計画:施肥計画の圃場をカスタムグループに割り当て、配置場所単位で集計する""" fertilization_plan = models.ForeignKey( FertilizationPlan, on_delete=models.CASCADE, related_name='distribution_plans', verbose_name='施肥計画' ) name = models.CharField(max_length=200, verbose_name='計画名') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: verbose_name = '分配計画' verbose_name_plural = '分配計画' ordering = ['-fertilization_plan__year', 'name'] def __str__(self): return f"{self.fertilization_plan.year} {self.name}" class DistributionGroup(models.Model): """分配グループ:ある場所にまとめて置く圃場のグループ""" distribution_plan = models.ForeignKey( DistributionPlan, on_delete=models.CASCADE, related_name='groups', verbose_name='分配計画' ) name = models.CharField(max_length=100, verbose_name='グループ名') order = models.PositiveIntegerField(default=0, verbose_name='表示順') class Meta: verbose_name = '分配グループ' verbose_name_plural = '分配グループ' unique_together = [['distribution_plan', 'name']] ordering = ['order', 'id'] def __str__(self): return f"{self.distribution_plan} / {self.name}" class DistributionGroupField(models.Model): """圃場のグループへの割り当て(1圃場=1グループ/1分配計画)""" distribution_plan = models.ForeignKey( DistributionPlan, on_delete=models.CASCADE, verbose_name='分配計画' ) group = models.ForeignKey( DistributionGroup, on_delete=models.CASCADE, related_name='field_assignments', verbose_name='グループ' ) field = models.ForeignKey( 'fields.Field', on_delete=models.PROTECT, verbose_name='圃場' ) class Meta: verbose_name = 'グループ圃場割り当て' verbose_name_plural = 'グループ圃場割り当て' unique_together = [['distribution_plan', 'field']] ordering = ['field__display_order', 'field__id'] def __str__(self): return f"{self.group.name} / {self.field.name}"