card dashboard produksi
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user