dashboard indikator pertanian

This commit is contained in:
2026-08-07 16:09:24 +07:00
parent 0d9f6c0b64
commit a4f38998d5
2 changed files with 307 additions and 2 deletions
@@ -15,6 +15,7 @@ use App\Models\Pertanian\PraktikBudidaya;
use App\Models\Pertanian\Produksi;
use App\Models\Pertanian\SkorPetani;
use App\Models\Pertanian\SosialEkonomi;
use App\Models\Pertanian\SurveyProduktivitas;
use App\Models\Wilayah\DesaKelurahan;
use App\Models\Wilayah\KabupatenKota;
use App\Models\Wilayah\Kecamatan;
@@ -120,6 +121,12 @@ class IndikatorPertanianController extends Controller
'keparahanSerangan' => $this->keparahanSeranganChart($initialFilters),
'statusHakKelolaLahan' => $this->statusHakKelolaLahanChart($initialFilters),
'praktikPemupukan' => $this->praktikPemupukanChart($initialFilters),
'produksiPerKomoditas' => $this->produksiPerKomoditasChart($initialFilters),
'produktivitasPerKomoditas' => $this->produktivitasPerKomoditasChart($initialFilters),
'luasPanenPerKomoditas' => $this->luasPanenPerKomoditasChart($initialFilters),
'statusPanen' => $this->statusPanenChart($initialFilters),
'surveyProduktivitasHa' => $this->surveyProduktivitasByUnitChart($initialFilters, 'ha_tahun'),
'surveyProduktivitasPohon' => $this->surveyProduktivitasByUnitChart($initialFilters, 'pohon_tahun'),
],
]);
}
@@ -410,6 +417,123 @@ class IndikatorPertanianController extends Controller
);
}
private function produksiPerKomoditasChart(array $filters): array
{
$rows = $this->applyProduksiFilters(Produksi::query(), $filters)
->leftJoin('master_komoditas as k', 'k.id', '=', 'produksi.komoditas_id')
->whereNotNull('jumlah_panen')
->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label")
->selectRaw('produksi.jumlah_panen')
->selectRaw('produksi.satuan')
->get()
->groupBy('label')
->map(fn ($items) => round($items->sum(
fn (Produksi $produksi) => $this->toKilograms(
(float) $produksi->jumlah_panen,
(string) $produksi->satuan
)
), 2))
->filter(fn ($total) => $total > 0)
->sortDesc();
return [
'labels' => $rows->keys()->values()->all(),
'series' => $rows->values()->map(fn ($value) => round((float) $value, 2))->values()->all(),
];
}
private function produktivitasPerKomoditasChart(array $filters): array
{
$rows = $this->applyProduksiFilters(Produksi::query(), $filters)
->leftJoin('master_komoditas as k', 'k.id', '=', 'produksi.komoditas_id')
->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label")
->selectRaw('produksi.jumlah_panen')
->selectRaw('produksi.satuan')
->selectRaw('produksi.luas_panen')
->selectRaw('produksi.produktivitas')
->get()
->groupBy('label')
->map(function ($items) {
$storedAverage = $items
->pluck('produktivitas')
->filter(fn ($value) => (float) $value > 0)
->avg();
if ($storedAverage > 0) {
return round((float) $storedAverage, 2);
}
$totalProduksiKg = $items->sum(
fn (Produksi $produksi) => $this->toKilograms(
(float) $produksi->jumlah_panen,
(string) $produksi->satuan
)
);
$totalLuasPanen = $items->sum(fn (Produksi $produksi) => (float) $produksi->luas_panen);
return $totalLuasPanen > 0
? round($totalProduksiKg / $totalLuasPanen, 2)
: 0;
})
->filter(fn ($total) => $total > 0)
->sortDesc();
return [
'labels' => $rows->keys()->values()->all(),
'series' => $rows->values()->map(fn ($value) => round((float) $value, 2))->values()->all(),
];
}
private function luasPanenPerKomoditasChart(array $filters): array
{
$rows = $this->applyProduksiFilters(Produksi::query(), $filters)
->leftJoin('master_komoditas as k', 'k.id', '=', 'produksi.komoditas_id')
->whereNotNull('luas_panen')
->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label")
->selectRaw('SUM(produksi.luas_panen) as total')
->groupBy('k.id', 'k.nama')
->havingRaw('SUM(produksi.luas_panen) > 0')
->orderByDesc('total')
->get();
return [
'labels' => $rows->pluck('label')->values()->all(),
'series' => $rows->pluck('total')->map(fn ($value) => round((float) $value, 2))->values()->all(),
];
}
private function statusPanenChart(array $filters): array
{
$rows = $this->applyProduksiFilters(Produksi::query(), $filters)
->whereNotNull('status_panen')
->selectRaw("COALESCE(status_panen, 'Belum ditentukan') as label")
->selectRaw('COUNT(produksi.id) as total')
->groupBy('status_panen')
->orderByDesc('total')
->get();
return $this->chartFromRows($rows, fn ($label) => $this->shortEnumLabel((string) $label));
}
private function surveyProduktivitasByUnitChart(array $filters, string $unit): array
{
$rows = $this->applySurveyProduktivitasFilters(SurveyProduktivitas::query(), $filters)
->leftJoin('master_komoditas as k', 'k.id', '=', 'survey_produktivitas.komoditas_id')
->where('satuan', $unit)
->whereNotNull('kuantitas')
->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label")
->selectRaw('AVG(survey_produktivitas.kuantitas) as total')
->groupBy('k.id', 'k.nama')
->havingRaw('AVG(survey_produktivitas.kuantitas) > 0')
->orderByDesc('total')
->get();
return [
'labels' => $rows->pluck('label')->values()->all(),
'series' => $rows->pluck('total')->map(fn ($value) => round((float) $value, 2))->values()->all(),
];
}
private function chartFromRows($rows, callable $labelResolver): array
{
return [
@@ -505,6 +629,15 @@ class IndikatorPertanianController extends Controller
});
}
private function applySurveyProduktivitasFilters($query, array $filters)
{
return $query
->whereHas('petani', function ($petani) use ($filters) {
$this->applyPetaniFilters($petani, $filters);
})
->when($filters['komoditas'] !== 'all', fn ($query) => $query->where('komoditas_id', $filters['komoditas']));
}
private function applyTanamanTableFilters($query, array $filters)
{
return $query