diff --git a/app/Http/Controllers/Web/Dashboard/SummaryController.php b/app/Http/Controllers/Web/Dashboard/SummaryController.php index f9c6e1a..dd7028f 100644 --- a/app/Http/Controllers/Web/Dashboard/SummaryController.php +++ b/app/Http/Controllers/Web/Dashboard/SummaryController.php @@ -183,7 +183,8 @@ class SummaryController extends Controller $landMetrics = $this->karakteristikLandMetrics($request); $totalLuasLahan = $landMetrics['total_luas_lahan']; $avgLuasPerPetani = $landMetrics['ratarata_luas_lahan']; - $productivityCards = $this->productivityKpiCards($lahanIds); + $actualProductivity = $this->actualProductivityByCommodityChart($request); + $productivityCards = $this->productivityKpiCards($actualProductivity); $praktikBudidaya = $this->filteredPraktikBudidaya($request); $surveyPanen = $this->filteredSurveyPanen($request); $aksesPasar = $this->filteredAksesPasar($request); @@ -243,7 +244,7 @@ class SummaryController extends Controller ), 'praktikSortasiPanen' => $this->enumOptionChart($surveyPanen, 'praktik_sortasi', PraktikSortasi::class), 'praktikFermentasiPascapanen' => $this->fermentationPracticeChart($aksesPasar), - 'produktivitasAktualPerKomoditas' => $this->actualProductivityByCommodityChart($request), + 'produktivitasAktualPerKomoditas' => $actualProductivity, ], ]; } @@ -706,43 +707,18 @@ class SummaryController extends Controller ]; } - private function productivityKpiCards($lahanIds): array + private function productivityKpiCards(array $actualProductivity): array { - $komoditas = Komoditas::query() - ->where('is_utama', true) - ->orderBy('nama') - ->limit(4) - ->get(['id', 'nama']); - - $produksiRows = DB::table('produksi') - ->whereNull('produksi.deleted_at') - ->leftJoin('map_lahan as lahan_produksi', 'lahan_produksi.id', '=', 'produksi.lahan_id') - ->when($lahanIds->isNotEmpty(), fn ($query) => $query->whereIn('produksi.lahan_id', $lahanIds)) - ->when($lahanIds->isEmpty(), fn ($query) => $query->whereRaw('1 = 0')) - ->selectRaw('COALESCE(produksi.komoditas_id, lahan_produksi.komoditas_id) as komoditas_id') - ->addSelect([ - 'produksi.jumlah_panen', - 'produksi.satuan', - 'produksi.luas_panen', - 'produksi.produktivitas', - ]) - ->get() - ->groupBy('komoditas_id'); - $variants = ['primary', 'warning', 'info', 'secondary']; $icon = 'tabler-chart-bar'; - return $komoditas - ->values() - ->map(function ($item, int $index) use ($produksiRows, $variants, $icon) { - $rows = $produksiRows->get($item->id, collect()); - $average = $this->averageProductivity($rows); - + return collect($actualProductivity['labels']) + ->map(function (string $name, int $index) use ($actualProductivity, $variants, $icon) { return [ - 'value' => number_format($average, 0, ',', '.'), + 'value' => number_format((float) ($actualProductivity['series'][$index] ?? 0), 2, ',', '.'), 'unit' => 'kg/ha', - 'label' => 'Produktivitas Rata-rata '.$item->nama, - 'description' => 'Rata-rata produktivitas per komoditas', + 'label' => 'Produktivitas Aktual '.$name, + 'description' => 'Hasil panen per musim dibagi total luas lahan', 'icon' => $icon, 'variant' => $variants[$index % count($variants)], ]; @@ -750,32 +726,6 @@ class SummaryController extends Controller ->all(); } - private function averageProductivity($rows): float - { - if ($rows->isEmpty()) { - return 0; - } - - $storedAverage = $rows - ->pluck('produktivitas') - ->filter(fn ($value) => (float) $value > 0) - ->avg(); - - if ($storedAverage > 0) { - return round((float) $storedAverage, 2); - } - - $totalProduksiKg = $rows->sum(fn ($row) => $this->toKilograms( - (float) ($row->jumlah_panen ?? 0), - (string) ($row->satuan ?? 'kg') - )); - $totalLuasPanen = $rows->sum(fn ($row) => (float) ($row->luas_panen ?? 0)); - - return $totalLuasPanen > 0 - ? round($totalProduksiKg / $totalLuasPanen, 2) - : 0; - } - private function actualProductivityByCommodityChart(Request $request): array { $preferredOrder = ['Kakao', 'Vanili', 'Kemiri', 'Kopi']; @@ -824,15 +774,6 @@ class SummaryController extends Controller ]; } - private function toKilograms(float $value, string $unit): float - { - return match (strtolower($unit)) { - 'ton' => $value * 1000, - 'kuintal', 'kwintal' => $value * 100, - default => $value, - }; - } - private function filteredLahanQuery(Request $request) { return DB::table('map_lahan') diff --git a/tests/Feature/ActualProductivityChartTest.php b/tests/Feature/ActualProductivityChartTest.php index 5a9435f..6d85f35 100644 --- a/tests/Feature/ActualProductivityChartTest.php +++ b/tests/Feature/ActualProductivityChartTest.php @@ -106,3 +106,24 @@ test('actual productivity rounds kg per hectare to two decimals', function () { expect(($this->chart)()['series'][1])->toBe(33.33); }); + +test('productivity cards display the same values and commodities as the chart', function () { + DB::table('map_lahan')->where('petani_id', 5)->update(['luas_lahan' => 0.3]); + $controller = app(SummaryController::class); + $method = new ReflectionMethod($controller, 'productivityKpiCards'); + + foreach ([[], ['desaKelurahan_id' => 2], ['komoditas_id' => 1]] as $filters) { + $chart = ($this->chart)($filters); + $cards = $method->invoke($controller, $chart); + + expect(array_column($cards, 'label'))->toBe(array_map( + fn ($name) => 'Produktivitas Aktual '.$name, + $chart['labels'], + )); + expect(array_column($cards, 'value'))->toBe(array_map( + fn ($value) => number_format($value, 2, ',', '.'), + $chart['series'], + )); + expect(array_column($cards, 'unit'))->toBe(array_fill(0, count($chart['labels']), 'kg/ha')); + } +});