"""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)