from __future__ import annotations from datetime import date from apps.farms.models import Cycle from apps.operations.models import FeedSacks def recompute_feed_sack_in_totals(cycle: Cycle) -> None: """Rebuild cumulative in_total from daily IoT feed-in only (excludes opening balance).""" running = 0 for fs_row in FeedSacks.objects.filter(cycle=cycle).order_by("date", "pk"): running += fs_row.in_today if fs_row.in_total != running: fs_row.in_total = running fs_row.save(update_fields=["in_total", "updated_at"]) def remove_opening_balance_feed_row( cycle: Cycle, *, balance_date: date | None, balance_amount: int, ) -> None: """Drop a FeedSacks row that only existed to carry opening balance.""" if balance_date is None or balance_amount <= 0: return FeedSacks.objects.filter( cycle=cycle, date=balance_date, in_today=balance_amount, out_today=0, feed_use_today=0, out_total=0, feed_use_total=0, ).delete() def cleanup_opening_balance_feed_rows( cycle: Cycle, *, previous_date: date | None, previous_balance: int, balance_date: date, balance_amount: int, ) -> None: """Remove opening-balance snapshot rows for the previous and current save.""" for row_date, amount in ( (previous_date, previous_balance), (balance_date, balance_amount), ): remove_opening_balance_feed_row( cycle, balance_date=row_date, balance_amount=amount, ) # Legacy cleanup: drop opening-only rows left from earlier saves on other dates. opening_amounts = { amount for amount in (previous_balance, balance_amount) if amount > 0 } if not opening_amounts: return FeedSacks.objects.filter( cycle=cycle, in_today__in=opening_amounts, out_today=0, feed_use_today=0, out_total=0, feed_use_total=0, ).delete()