Files
keinasystem/backend/apps/plans/tests.py

204 lines
7.6 KiB
Python

from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.test import APIRequestFactory, force_authenticate
from apps.fertilizer.models import FertilizationEntry, FertilizationPlan, Fertilizer
from apps.fields.models import Field
from apps.materials.models import Material, StockTransaction
from apps.materials.stock_service import create_reserves_for_plan
from .models import Crop, Plan, PlanVarietyChange, Variety
from .serializers import PlanSerializer
from .views import PlanViewSet
class PlanVarietyChangeTests(TestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.user = get_user_model().objects.create_user(
username='tester',
password='secret12345',
)
self.crop = Crop.objects.create(name='水稲')
self.old_variety = Variety.objects.create(crop=self.crop, name='にこまる')
self.new_variety = Variety.objects.create(crop=self.crop, name='たちはるか特栽')
self.field = Field.objects.create(
name='足川北上',
address='高知県高岡郡',
area_tan='1.2000',
area_m2=1200,
owner_name='吉田',
group_name='',
display_order=1,
)
self.plan = Plan.objects.create(
field=self.field,
year=2026,
crop=self.crop,
variety=self.old_variety,
notes='',
)
self.other_field = Field.objects.create(
name='足川南',
address='高知県高岡郡',
area_tan='0.8000',
area_m2=800,
owner_name='吉田',
group_name='',
display_order=2,
)
def test_serializer_update_creates_history_when_variety_changes(self):
serializer = PlanSerializer(
instance=self.plan,
data={'variety': self.new_variety.id},
partial=True,
)
self.assertTrue(serializer.is_valid(), serializer.errors)
serializer.save()
self.plan.refresh_from_db()
self.assertEqual(self.plan.variety_id, self.new_variety.id)
change = PlanVarietyChange.objects.get(plan=self.plan)
self.assertEqual(change.field_id, self.field.id)
self.assertEqual(change.year, 2026)
self.assertEqual(change.old_variety_id, self.old_variety.id)
self.assertEqual(change.new_variety_id, self.new_variety.id)
self.assertEqual(change.moved_entry_count, 0)
def test_serializer_update_does_not_create_history_without_variety_change(self):
serializer = PlanSerializer(
instance=self.plan,
data={'notes': 'メモ更新'},
partial=True,
)
self.assertTrue(serializer.is_valid(), serializer.errors)
serializer.save()
self.plan.refresh_from_db()
self.assertEqual(self.plan.notes, 'メモ更新')
self.assertFalse(PlanVarietyChange.objects.exists())
def test_bulk_update_creates_history_for_existing_plan(self):
view = PlanViewSet.as_view({'post': 'bulk_update'})
request = self.factory.post(
'/api/plans/bulk_update/',
{
'field_ids': [self.field.id],
'year': 2026,
'crop': self.crop.id,
'variety': self.new_variety.id,
},
format='json',
)
force_authenticate(request, user=self.user)
response = view(request)
self.assertEqual(response.status_code, 200)
self.plan.refresh_from_db()
self.assertEqual(self.plan.variety_id, self.new_variety.id)
change = PlanVarietyChange.objects.get(plan=self.plan)
self.assertEqual(change.old_variety_id, self.old_variety.id)
self.assertEqual(change.new_variety_id, self.new_variety.id)
def test_serializer_update_moves_only_unspread_fertilizer_entries(self):
material_unspread = Material.objects.create(
name='高度化成14号',
material_type=Material.MaterialType.FERTILIZER,
)
material_partial = Material.objects.create(
name='分げつ一発',
material_type=Material.MaterialType.FERTILIZER,
)
fertilizer_unspread = Fertilizer.objects.create(
name='高度化成14号',
material=material_unspread,
)
fertilizer_partial = Fertilizer.objects.create(
name='分げつ一発',
material=material_partial,
)
old_fertilization_plan = FertilizationPlan.objects.create(
name='2026年度 にこまる 元肥',
year=2026,
variety=self.old_variety,
calc_settings=[{'fertilizer_id': fertilizer_unspread.id, 'method': 'per_tan', 'param': '1.0'}],
)
unspread_entry = FertilizationEntry.objects.create(
plan=old_fertilization_plan,
field=self.field,
fertilizer=fertilizer_unspread,
bags='4.00',
actual_bags=None,
)
partial_entry = FertilizationEntry.objects.create(
plan=old_fertilization_plan,
field=self.field,
fertilizer=fertilizer_partial,
bags='3.00',
actual_bags='1.0000',
)
untouched_entry = FertilizationEntry.objects.create(
plan=old_fertilization_plan,
field=self.other_field,
fertilizer=fertilizer_unspread,
bags='2.00',
actual_bags=None,
)
create_reserves_for_plan(old_fertilization_plan)
serializer = PlanSerializer(
instance=self.plan,
data={'variety': self.new_variety.id},
partial=True,
)
self.assertTrue(serializer.is_valid(), serializer.errors)
serializer.save()
change = PlanVarietyChange.objects.get(plan=self.plan)
self.assertEqual(change.moved_entry_count, 1)
old_fertilization_plan.refresh_from_db()
new_plan = FertilizationPlan.objects.exclude(id=old_fertilization_plan.id).get(
year=2026,
variety=self.new_variety,
)
self.assertEqual(
new_plan.name,
f'2026年度 {self.new_variety.name} 施肥計画(品種変更移動)',
)
self.assertEqual(new_plan.calc_settings, old_fertilization_plan.calc_settings)
unspread_entry.refresh_from_db()
partial_entry.refresh_from_db()
untouched_entry.refresh_from_db()
self.assertEqual(unspread_entry.plan_id, new_plan.id)
self.assertEqual(partial_entry.plan_id, old_fertilization_plan.id)
self.assertEqual(untouched_entry.plan_id, old_fertilization_plan.id)
old_reserves = list(
StockTransaction.objects.filter(
fertilization_plan=old_fertilization_plan,
transaction_type=StockTransaction.TransactionType.RESERVE,
).order_by('material__name')
)
new_reserves = list(
StockTransaction.objects.filter(
fertilization_plan=new_plan,
transaction_type=StockTransaction.TransactionType.RESERVE,
).order_by('material__name')
)
self.assertEqual(len(old_reserves), 2)
self.assertEqual(len(new_reserves), 1)
self.assertEqual(
{(reserve.material_id, reserve.quantity) for reserve in old_reserves},
{
(material_partial.id, partial_entry.bags),
(material_unspread.id, untouched_entry.bags),
},
)
self.assertEqual(new_reserves[0].quantity, unspread_entry.bags)