Files
keinasystem/backend/apps/fertilizer/serializers.py
Akira 5145217481 施肥計画の計算設定を保存・復元し、未入力圃場のみ計算オプションを追加
- FertilizationPlanにcalc_settings JSONFieldを追加(migration 0004)
- 編集画面を開くと前回の計算方式・パラメータが復元される
- 「未入力圃場のみ」チェックで既存値を保持したまま新規圃場だけ計算可能

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 10:50:56 +09:00

219 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from rest_framework import serializers
from .models import Fertilizer, FertilizationPlan, FertilizationEntry, DistributionPlan, DistributionGroup, DistributionGroupField
class FertilizerSerializer(serializers.ModelSerializer):
class Meta:
model = Fertilizer
fields = '__all__'
class FertilizationEntrySerializer(serializers.ModelSerializer):
field_name = serializers.CharField(source='field.name', read_only=True)
field_area_tan = serializers.DecimalField(
source='field.area_tan', max_digits=6, decimal_places=4, read_only=True
)
fertilizer_name = serializers.CharField(source='fertilizer.name', read_only=True)
class Meta:
model = FertilizationEntry
fields = ['id', 'field', 'field_name', 'field_area_tan', 'fertilizer', 'fertilizer_name', 'bags']
class FertilizationPlanSerializer(serializers.ModelSerializer):
variety_name = serializers.SerializerMethodField()
crop_name = serializers.SerializerMethodField()
entries = FertilizationEntrySerializer(many=True, read_only=True)
field_count = serializers.SerializerMethodField()
fertilizer_count = serializers.SerializerMethodField()
class Meta:
model = FertilizationPlan
fields = [
'id', 'name', 'year', 'variety', 'variety_name', 'crop_name',
'calc_settings', 'entries', 'field_count', 'fertilizer_count', 'created_at', 'updated_at'
]
def get_variety_name(self, obj):
return obj.variety.name
def get_crop_name(self, obj):
return obj.variety.crop.name
def get_field_count(self, obj):
return obj.entries.values('field').distinct().count()
def get_fertilizer_count(self, obj):
return obj.entries.values('fertilizer').distinct().count()
class FertilizationPlanWriteSerializer(serializers.ModelSerializer):
"""保存用entries を一括で受け取る)"""
entries = serializers.ListField(child=serializers.DictField(), write_only=True, required=False)
class Meta:
model = FertilizationPlan
fields = ['id', 'name', 'year', 'variety', 'calc_settings', 'entries']
def create(self, validated_data):
entries_data = validated_data.pop('entries', [])
plan = FertilizationPlan.objects.create(**validated_data)
self._save_entries(plan, entries_data)
return plan
def update(self, instance, validated_data):
entries_data = validated_data.pop('entries', None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
if entries_data is not None:
instance.entries.all().delete()
self._save_entries(instance, entries_data)
return instance
def _save_entries(self, plan, entries_data):
for entry in entries_data:
FertilizationEntry.objects.create(
plan=plan,
field_id=entry['field_id'],
fertilizer_id=entry['fertilizer_id'],
bags=entry['bags'],
)
# ─── 分配計画 ────────────────────────────────────────────────────────────
class DistributionGroupFieldSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(source='field.id', read_only=True)
name = serializers.CharField(source='field.name', read_only=True)
area_tan = serializers.DecimalField(
source='field.area_tan', max_digits=6, decimal_places=4, read_only=True
)
class Meta:
model = DistributionGroupField
fields = ['id', 'name', 'area_tan']
class DistributionGroupReadSerializer(serializers.ModelSerializer):
fields = DistributionGroupFieldSerializer(source='field_assignments', many=True, read_only=True)
class Meta:
model = DistributionGroup
fields = ['id', 'name', 'order', 'fields']
class FertilizationPlanForDistributionSerializer(serializers.ModelSerializer):
"""分配計画詳細に埋め込む施肥計画情報肥料一覧・entries 含む)"""
variety_name = serializers.SerializerMethodField()
crop_name = serializers.SerializerMethodField()
fertilizers = serializers.SerializerMethodField()
entries = serializers.SerializerMethodField()
class Meta:
model = FertilizationPlan
fields = ['id', 'name', 'year', 'variety_name', 'crop_name', 'fertilizers', 'entries']
def get_variety_name(self, obj):
return obj.variety.name
def get_crop_name(self, obj):
return obj.variety.crop.name
def get_fertilizers(self, obj):
fert_ids = obj.entries.values_list('fertilizer_id', flat=True).distinct()
from .models import Fertilizer as F
fertilizers = F.objects.filter(id__in=fert_ids).order_by('name')
return [{'id': f.id, 'name': f.name} for f in fertilizers]
def get_entries(self, obj):
return [
{'field': e.field_id, 'fertilizer': e.fertilizer_id, 'bags': str(e.bags)}
for e in obj.entries.all()
]
class DistributionPlanListSerializer(serializers.ModelSerializer):
fertilization_plan_id = serializers.IntegerField(source='fertilization_plan.id', read_only=True)
fertilization_plan_name = serializers.CharField(source='fertilization_plan.name', read_only=True)
year = serializers.IntegerField(source='fertilization_plan.year', read_only=True)
variety_name = serializers.SerializerMethodField()
crop_name = serializers.SerializerMethodField()
group_count = serializers.SerializerMethodField()
field_count = serializers.SerializerMethodField()
class Meta:
model = DistributionPlan
fields = [
'id', 'name', 'fertilization_plan_id', 'fertilization_plan_name',
'year', 'variety_name', 'crop_name', 'group_count', 'field_count',
'created_at', 'updated_at',
]
def get_variety_name(self, obj):
return obj.fertilization_plan.variety.name
def get_crop_name(self, obj):
return obj.fertilization_plan.variety.crop.name
def get_group_count(self, obj):
return obj.groups.count()
def get_field_count(self, obj):
return obj.distributiongroupfield_set.count()
class DistributionPlanReadSerializer(serializers.ModelSerializer):
fertilization_plan = FertilizationPlanForDistributionSerializer(read_only=True)
groups = DistributionGroupReadSerializer(many=True, read_only=True)
unassigned_fields = serializers.SerializerMethodField()
class Meta:
model = DistributionPlan
fields = ['id', 'name', 'fertilization_plan', 'groups', 'unassigned_fields', 'created_at', 'updated_at']
def get_unassigned_fields(self, obj):
assigned_ids = obj.distributiongroupfield_set.values_list('field_id', flat=True)
plan_field_ids = obj.fertilization_plan.entries.values_list('field_id', flat=True).distinct()
from apps.fields.models import Field as F
unassigned = F.objects.filter(id__in=plan_field_ids).exclude(id__in=assigned_ids).order_by('display_order', 'id')
return [{'id': f.id, 'name': f.name, 'area_tan': str(f.area_tan)} for f in unassigned]
class DistributionPlanWriteSerializer(serializers.ModelSerializer):
fertilization_plan_id = serializers.IntegerField(write_only=True)
groups = serializers.ListField(child=serializers.DictField(), write_only=True, required=False)
class Meta:
model = DistributionPlan
fields = ['id', 'name', 'fertilization_plan_id', 'groups']
def create(self, validated_data):
groups_data = validated_data.pop('groups', [])
plan = DistributionPlan.objects.create(**validated_data)
self._save_groups(plan, groups_data)
return plan
def update(self, instance, validated_data):
groups_data = validated_data.pop('groups', None)
instance.name = validated_data.get('name', instance.name)
instance.save()
if groups_data is not None:
instance.groups.all().delete()
self._save_groups(instance, groups_data)
return instance
def _save_groups(self, plan, groups_data):
for g_data in groups_data:
group = DistributionGroup.objects.create(
distribution_plan=plan,
name=g_data['name'],
order=g_data.get('order', 0),
)
for field_id in g_data.get('field_ids', []):
DistributionGroupField.objects.create(
distribution_plan=plan,
group=group,
field_id=field_id,
)