adjust kpi card not showing after manual input before cutoff time
This commit is contained in:
1 parent
3f5db48b16
commit
c963bb778c
2 files changed
+44
-10
No files matched your search
@@ -15,44 +15,56 @@ from apps.operations.services.kpi_formulas import (
|
||||
compute_fcr,
|
||||
compute_stock_akhir,
|
||||
)
|
||||
from apps.operations.services.visibility import visible_through_date
|
||||
|
||||
|
||||
def refresh_kpi_source_fields(cycle: Cycle, *, through: date | None = None) -> int:
|
||||
"""
|
||||
Upsert one KPI row per day that has cc + cw + fs + manual.
|
||||
|
||||
If `through` is specified, rollup calculations are bounded up to that date.
|
||||
Otherwise, rollups are calculated for all complete days of the cycle (up to `cycle.end_date` if set).
|
||||
Dashboard cutoff visibility is enforced by the KPI API queryset layer (`VisibilityFilteredMixin`).
|
||||
|
||||
Returns the number of KPI rows written.
|
||||
"""
|
||||
cutoff = through if through is not None else visible_through_date()
|
||||
cutoff = through if through is not None else cycle.end_date
|
||||
start = cycle.start_date
|
||||
if cycle.end_date and cycle.end_date < cutoff:
|
||||
if through is not None and cycle.end_date and cycle.end_date < cutoff:
|
||||
cutoff = cycle.end_date
|
||||
|
||||
manual_filter: dict = {"cycle": cycle, "date__gte": start}
|
||||
cc_filter: dict = {"cycle": cycle, "date__gte": start}
|
||||
cw_filter: dict = {"cycle": cycle, "date__gte": start}
|
||||
fs_filter: dict = {"cycle": cycle, "date__gte": start}
|
||||
|
||||
if cutoff is not None:
|
||||
manual_filter["date__lte"] = cutoff
|
||||
cc_filter["date__lte"] = cutoff
|
||||
cw_filter["date__lte"] = cutoff
|
||||
fs_filter["date__lte"] = cutoff
|
||||
|
||||
manuals = {
|
||||
row.date: row
|
||||
for row in ManualInput.objects.filter(cycle=cycle, date__gte=start, date__lte=cutoff).order_by(
|
||||
"date", "pk"
|
||||
)
|
||||
for row in ManualInput.objects.filter(**manual_filter).order_by("date", "pk")
|
||||
}
|
||||
countings = {
|
||||
row.date: row
|
||||
for row in ChickenCounting.objects.filter(cycle=cycle, date__gte=start, date__lte=cutoff)
|
||||
for row in ChickenCounting.objects.filter(**cc_filter)
|
||||
}
|
||||
weights = {
|
||||
row.date: row
|
||||
for row in ChickenWeight.objects.filter(cycle=cycle, date__gte=start, date__lte=cutoff)
|
||||
for row in ChickenWeight.objects.filter(**cw_filter)
|
||||
}
|
||||
feeds = {
|
||||
row.date: row
|
||||
for row in FeedSacks.objects.filter(cycle=cycle, date__gte=start, date__lte=cutoff)
|
||||
for row in FeedSacks.objects.filter(**fs_filter)
|
||||
}
|
||||
|
||||
written = 0
|
||||
harvest_age_sum = 0.0
|
||||
|
||||
for day in sorted(set(manuals) | set(countings) | set(weights) | set(feeds)):
|
||||
if day < start or day > cutoff:
|
||||
if day < start or (cutoff is not None and day > cutoff):
|
||||
continue
|
||||
manual = manuals.get(day)
|
||||
cc = countings.get(day)
|
||||
|
||||
@@ -121,3 +121,25 @@ class KpiRollupServiceTests(TestCase):
|
||||
refresh_kpi_source_fields(self.cycle, through=day)
|
||||
self.assertTrue(KPI.objects.filter(cycle=self.cycle, date=day).exists())
|
||||
self.assertEqual(KPI.objects.get(cycle=self.cycle, date=day).mortality_total, 21)
|
||||
|
||||
def test_manual_save_generates_kpi_without_explicit_through(self):
|
||||
day = self.start
|
||||
ChickenCounting.objects.create(cycle=self.cycle, date=day, total_count=1, mortality_count=0)
|
||||
ChickenWeight.objects.create(
|
||||
cycle=self.cycle,
|
||||
date=day,
|
||||
age=0,
|
||||
doc_weight=40,
|
||||
average_weight=35.0,
|
||||
chicken_count=1,
|
||||
uniformity=80,
|
||||
average_daily_gain=0,
|
||||
)
|
||||
FeedSacks.objects.create(cycle=self.cycle, date=day, feed_use_today=15, feed_use_total=15)
|
||||
ManualInput.objects.create(cycle=self.cycle, date=day, mortality_manual=21)
|
||||
recompute_manual_totals(self.cycle)
|
||||
written = refresh_kpi_source_fields(self.cycle)
|
||||
self.assertEqual(written, 1)
|
||||
self.assertTrue(KPI.objects.filter(cycle=self.cycle, date=day).exists())
|
||||
self.assertEqual(KPI.objects.get(cycle=self.cycle, date=day).mortality_total, 21)
|
||||
|
||||
Reference in new issue
Block a user