Add fertilization plan merge workflow
This commit is contained in:
@@ -3,12 +3,22 @@ from decimal import Decimal
|
||||
from django.db import transaction
|
||||
from django.db.models import Sum
|
||||
|
||||
from apps.materials.stock_service import create_reserves_for_plan
|
||||
from apps.materials.stock_service import create_reserves_for_plan, delete_reserves_for_plan
|
||||
from apps.materials.models import StockTransaction
|
||||
from apps.workrecords.services import sync_spreading_work_record
|
||||
from .models import FertilizationEntry, FertilizationPlan, SpreadingSessionItem
|
||||
|
||||
|
||||
class FertilizationPlanMergeError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class FertilizationPlanMergeConflict(FertilizationPlanMergeError):
|
||||
def __init__(self, conflicts):
|
||||
super().__init__('merge conflict')
|
||||
self.conflicts = conflicts
|
||||
|
||||
|
||||
def sync_actual_bags_for_pairs(year, field_fertilizer_pairs):
|
||||
pairs = {
|
||||
(int(field_id), int(fertilizer_id))
|
||||
@@ -103,3 +113,84 @@ def move_fertilization_entries_for_variety_change(change):
|
||||
moved_count += len(entries_to_move)
|
||||
|
||||
return moved_count
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def merge_fertilization_plan_into(source_plan, target_plan):
|
||||
if source_plan.id == target_plan.id:
|
||||
raise FertilizationPlanMergeError('同じ施肥計画にはマージできません。')
|
||||
if source_plan.year != target_plan.year:
|
||||
raise FertilizationPlanMergeError('年度が異なる施肥計画にはマージできません。')
|
||||
if source_plan.variety_id != target_plan.variety_id:
|
||||
raise FertilizationPlanMergeError('品種が異なる施肥計画にはマージできません。')
|
||||
if source_plan.is_confirmed or target_plan.is_confirmed:
|
||||
raise FertilizationPlanMergeError('散布確定済みの施肥計画はマージできません。')
|
||||
|
||||
source_entries = list(
|
||||
source_plan.entries.select_related('field', 'fertilizer').order_by('field_id', 'fertilizer_id')
|
||||
)
|
||||
if not source_entries:
|
||||
raise FertilizationPlanMergeError('移動元の施肥計画にマージ対象の entry がありません。')
|
||||
|
||||
source_pairs = {(entry.field_id, entry.fertilizer_id) for entry in source_entries}
|
||||
target_entries = list(
|
||||
target_plan.entries.select_related('field', 'fertilizer').order_by('field_id', 'fertilizer_id')
|
||||
)
|
||||
target_pairs = {(entry.field_id, entry.fertilizer_id): entry for entry in target_entries}
|
||||
|
||||
conflicts = [
|
||||
{
|
||||
'field_id': entry.field_id,
|
||||
'field_name': entry.field.name,
|
||||
'fertilizer_id': entry.fertilizer_id,
|
||||
'fertilizer_name': entry.fertilizer.name,
|
||||
}
|
||||
for entry in source_entries
|
||||
if (entry.field_id, entry.fertilizer_id) in target_pairs
|
||||
]
|
||||
if conflicts:
|
||||
raise FertilizationPlanMergeConflict(conflicts)
|
||||
|
||||
FertilizationEntry.objects.filter(
|
||||
id__in=[entry.id for entry in source_entries]
|
||||
).update(plan=target_plan)
|
||||
|
||||
target_plan.calc_settings = _merge_calc_settings(
|
||||
target_plan.calc_settings,
|
||||
source_plan.calc_settings,
|
||||
)
|
||||
target_plan.save()
|
||||
|
||||
create_reserves_for_plan(target_plan)
|
||||
|
||||
moved_count = len(source_entries)
|
||||
deleted_source_plan = False
|
||||
if not FertilizationEntry.objects.filter(plan=source_plan).exists():
|
||||
delete_reserves_for_plan(source_plan)
|
||||
source_plan.delete()
|
||||
deleted_source_plan = True
|
||||
else:
|
||||
create_reserves_for_plan(source_plan)
|
||||
|
||||
return {
|
||||
'moved_entry_count': moved_count,
|
||||
'deleted_source_plan': deleted_source_plan,
|
||||
}
|
||||
|
||||
|
||||
def _merge_calc_settings(target_settings, source_settings):
|
||||
merged = list(target_settings or [])
|
||||
existing_fertilizer_ids = {
|
||||
setting.get('fertilizer_id')
|
||||
for setting in merged
|
||||
if isinstance(setting, dict)
|
||||
}
|
||||
for setting in source_settings or []:
|
||||
if not isinstance(setting, dict):
|
||||
continue
|
||||
fertilizer_id = setting.get('fertilizer_id')
|
||||
if fertilizer_id in existing_fertilizer_ids:
|
||||
continue
|
||||
merged.append(setting)
|
||||
existing_fertilizer_ids.add(fertilizer_id)
|
||||
return merged
|
||||
|
||||
Reference in New Issue
Block a user