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

@@ -0,0 +1,163 @@
"""Excel-verified FCR/EEF formula tests (Sukawarna Kandang Atas days 30–35)."""
from django.test import SimpleTestCase
from apps.operations.services.kpi_formulas import (
compute_average_harvest_day,
compute_average_harvest_weight,
compute_chicken_life,
compute_chicken_life_percentage,
compute_eef,
compute_fcr,
compute_stock_akhir,
)
# From Laporan_Akhir-Siklus_Sukawarna_Kandang-Atas … FCR + EEF sheets.
# harvest_total / harvest_age_sum reconstructed so live-blend avgs match Excel.
EXCEL_DAYS = [
{
"age": 30,
"feed_total": 928,
"iot_weight": 1480.51,
"stock_akhir": 17658,
"harvest_weight_total_g": 6272.1 * 1000,
"harvest_total": 6400,
"life_pct": 96.232,
"excel_fcr": 1.4314384667247064,
"excel_avg_bw": 1347.3665965583173,
"excel_avg_day": 29.112145648017293,
"excel_eef": 311.14182093425177,
},
{
"age": 31,
"feed_total": 970,
"iot_weight": 1524.39,
"stock_akhir": 16419,
"harvest_weight_total_g": 7665.3 * 1000,
"harvest_total": 7600,
"life_pct": 96.076,
"excel_fcr": 1.4834408509392811,
"excel_avg_bw": 1361.183205379075,
"excel_avg_day": 29.844248303426454,
"excel_eef": 295.39328356931856,
},
{
"age": 32,
"feed_total": 1013,
"iot_weight": 1578.85,
"stock_akhir": 15929,
"harvest_weight_total_g": 8229.1 * 1000,
"harvest_total": 8045,
"life_pct": 95.896,
"excel_fcr": 1.5174392423955845,
"excel_avg_bw": 1392.2833757403853,
"excel_avg_day": 30.52506882455994,
"excel_eef": 288.2439276697344,
},
{
"age": 33,
"feed_total": 1031,
"iot_weight": 1609.98,
"stock_akhir": 10458,
"harvest_weight_total_g": 16476 * 1000,
"harvest_total": 13421,
"life_pct": 95.516,
"excel_fcr": 1.5474360050440639,
"excel_avg_bw": 1395.0823250554881,
"excel_avg_day": 31.18229406591566,
"excel_eef": 276.15645742250786,
},
{
"age": 34,
"feed_total": 1052,
"iot_weight": 1720.44,
"stock_akhir": 10347,
"harvest_weight_total_g": 16476 * 1000,
"harvest_total": 13421,
"life_pct": 95.072,
"excel_fcr": 1.5345391200273755,
"excel_avg_bw": 1442.1656294177044,
"excel_avg_day": 31.60913833726018,
"excel_eef": 282.668327683184,
},
{
"age": 35,
"feed_total": 1059,
"iot_weight": 1561.1,
"stock_akhir": 5198,
"harvest_weight_total_g": 25032.8 * 1000,
"harvest_total": 18413,
"life_pct": 94.444,
"excel_fcr": 1.5974104609804394,
"excel_avg_bw": 1403.8963957477447,
"excel_avg_day": 32.02481894032442,
"excel_eef": 259.1828280867179,
},
]
def _harvest_age_sum(row: dict) -> float:
"""Invert Excel avg_day blend: (sum + age*stock) / (h + stock) = avg_day."""
age = row["age"]
stock = row["stock_akhir"]
h = row["harvest_total"]
return row["excel_avg_day"] * (h + stock) - age * stock
class KpiFormulaTests(SimpleTestCase):
def test_chicken_life_excludes_harvest(self):
self.assertEqual(compute_chicken_life(25000, 942), 24058)
self.assertEqual(compute_chicken_life_percentage(25000, 24058), 96.232)
self.assertEqual(compute_stock_akhir(24058, 6400), 17658)
def test_fcr_matches_excel_days_30_to_35(self):
for row in EXCEL_DAYS:
with self.subTest(age=row["age"]):
got = compute_fcr(
row["feed_total"],
row["stock_akhir"],
row["iot_weight"],
row["harvest_weight_total_g"],
)
self.assertAlmostEqual(got, row["excel_fcr"], places=9)
def test_average_harvest_blend_matches_excel_days_30_to_35(self):
for row in EXCEL_DAYS:
with self.subTest(age=row["age"]):
avg_bw = compute_average_harvest_weight(
row["harvest_weight_total_g"],
row["stock_akhir"],
row["iot_weight"],
row["harvest_total"],
)
avg_day = compute_average_harvest_day(
_harvest_age_sum(row),
row["age"],
row["stock_akhir"],
row["harvest_total"],
)
self.assertAlmostEqual(avg_bw, row["excel_avg_bw"], places=6)
self.assertAlmostEqual(avg_day, row["excel_avg_day"], places=6)
def test_eef_matches_excel_days_30_to_35(self):
# Use Excel avg columns + computed FCR (same path as verified against the sheet).
for row in EXCEL_DAYS:
with self.subTest(age=row["age"]):
fcr = compute_fcr(
row["feed_total"],
row["stock_akhir"],
row["iot_weight"],
row["harvest_weight_total_g"],
)
got = compute_eef(
row["life_pct"],
row["excel_avg_bw"],
row["excel_avg_day"],
fcr,
)
self.assertAlmostEqual(got, row["excel_eef"], places=9)
def test_fcr_and_eef_zero_when_denom_invalid(self):
self.assertEqual(compute_fcr(100, 0, 0, 0), 0.0)
self.assertEqual(compute_eef(99.0, 1000.0, 0, 1.2), 0.0)
self.assertEqual(compute_eef(99.0, 1000.0, 10, 0), 0.0)