kpi configuration (still prototype some data still use manual need to update later)

This commit is contained in:
Alberto-Audrix committed 2026-09-09 16:50:07 +07:00
1 parent e4dbfd0252
commit ed84d989b7
12 files changed
+547 -89

No files matched your search

@@ -1,58 +1,17 @@
from django.core.management.base import BaseCommand
from django.db.models import Sum
from apps.farms.models import Cycle
from apps.operations.models import ChickenCounting, FeedSacks, KPI
from apps.operations.services.visibility import visible_through_date
from apps.operations.services.kpi_rollups import refresh_kpi_source_fields
class Command(BaseCommand):
help = "Recompute simple KPI rollups from ops tables for active cycles"
help = "Recompute KPI source fields and FCR/EEF for active cycles"
def handle(self, *args, **options):
cutoff = visible_through_date()
count = 0
for cycle in Cycle.objects.filter(status=Cycle.STATUS_ACTIVE):
def visible(model):
return model.objects.filter(cycle=cycle, date__lte=cutoff)
counting = visible(ChickenCounting).aggregate(
mortality=Sum("mortality_count"),
life=Sum("total_count"),
)
feed_sack = visible(FeedSacks).order_by("-date", "-pk").first()
latest_cc = visible(ChickenCounting).order_by("-date").first()
latest_cw = None
latest_fs = feed_sack
latest_mi = None
from apps.operations.models import ChickenWeight, ManualInput
latest_cw = visible(ChickenWeight).order_by("-date").first()
latest_mi = visible(ManualInput).order_by("-date").first()
if not all([latest_cc, latest_cw, latest_fs, latest_mi]):
self.stdout.write(f"cycle={cycle.pk} skipped (missing source records)")
continue
kpi, _ = KPI.objects.update_or_create(
cycle=cycle,
date=latest_cc.date,
defaults={
"cc": latest_cc,
"cw": latest_cw,
"fs": latest_fs,
"manual": latest_mi,
"mortality_total": counting["mortality"] or 0,
"chicken_life": counting["life"] or cycle.doc_in_count,
"feed_total": feed_sack.feed_use_total if feed_sack else 0,
"chicken_life_percentage": (
((counting["life"] or cycle.doc_in_count) / cycle.doc_in_count * 100.0)
if cycle.doc_in_count
else 0.0
),
},
)
count += 1
self.stdout.write(f"KPI {kpi.pk} for cycle {cycle.pk}")
cycles = Cycle.objects.filter(status=Cycle.STATUS_ACTIVE)
for cycle in cycles:
written = refresh_kpi_source_fields(cycle)
count += written
self.stdout.write(f"cycle={cycle.pk} wrote {written} KPI row(s)")
self.stdout.write(self.style.SUCCESS(f"Recomputed {count} KPI row(s)"))