card dashboard produksi
This commit is contained in:
@@ -183,7 +183,8 @@ class SummaryController extends Controller
|
|||||||
$landMetrics = $this->karakteristikLandMetrics($request);
|
$landMetrics = $this->karakteristikLandMetrics($request);
|
||||||
$totalLuasLahan = $landMetrics['total_luas_lahan'];
|
$totalLuasLahan = $landMetrics['total_luas_lahan'];
|
||||||
$avgLuasPerPetani = $landMetrics['ratarata_luas_lahan'];
|
$avgLuasPerPetani = $landMetrics['ratarata_luas_lahan'];
|
||||||
$productivityCards = $this->productivityKpiCards($lahanIds);
|
$actualProductivity = $this->actualProductivityByCommodityChart($request);
|
||||||
|
$productivityCards = $this->productivityKpiCards($actualProductivity);
|
||||||
$praktikBudidaya = $this->filteredPraktikBudidaya($request);
|
$praktikBudidaya = $this->filteredPraktikBudidaya($request);
|
||||||
$surveyPanen = $this->filteredSurveyPanen($request);
|
$surveyPanen = $this->filteredSurveyPanen($request);
|
||||||
$aksesPasar = $this->filteredAksesPasar($request);
|
$aksesPasar = $this->filteredAksesPasar($request);
|
||||||
@@ -243,7 +244,7 @@ class SummaryController extends Controller
|
|||||||
),
|
),
|
||||||
'praktikSortasiPanen' => $this->enumOptionChart($surveyPanen, 'praktik_sortasi', PraktikSortasi::class),
|
'praktikSortasiPanen' => $this->enumOptionChart($surveyPanen, 'praktik_sortasi', PraktikSortasi::class),
|
||||||
'praktikFermentasiPascapanen' => $this->fermentationPracticeChart($aksesPasar),
|
'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'];
|
$variants = ['primary', 'warning', 'info', 'secondary'];
|
||||||
$icon = 'tabler-chart-bar';
|
$icon = 'tabler-chart-bar';
|
||||||
|
|
||||||
return $komoditas
|
return collect($actualProductivity['labels'])
|
||||||
->values()
|
->map(function (string $name, int $index) use ($actualProductivity, $variants, $icon) {
|
||||||
->map(function ($item, int $index) use ($produksiRows, $variants, $icon) {
|
|
||||||
$rows = $produksiRows->get($item->id, collect());
|
|
||||||
$average = $this->averageProductivity($rows);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'value' => number_format($average, 0, ',', '.'),
|
'value' => number_format((float) ($actualProductivity['series'][$index] ?? 0), 2, ',', '.'),
|
||||||
'unit' => 'kg/ha',
|
'unit' => 'kg/ha',
|
||||||
'label' => 'Produktivitas Rata-rata '.$item->nama,
|
'label' => 'Produktivitas Aktual '.$name,
|
||||||
'description' => 'Rata-rata produktivitas per komoditas',
|
'description' => 'Hasil panen per musim dibagi total luas lahan',
|
||||||
'icon' => $icon,
|
'icon' => $icon,
|
||||||
'variant' => $variants[$index % count($variants)],
|
'variant' => $variants[$index % count($variants)],
|
||||||
];
|
];
|
||||||
@@ -750,32 +726,6 @@ class SummaryController extends Controller
|
|||||||
->all();
|
->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
|
private function actualProductivityByCommodityChart(Request $request): array
|
||||||
{
|
{
|
||||||
$preferredOrder = ['Kakao', 'Vanili', 'Kemiri', 'Kopi'];
|
$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)
|
private function filteredLahanQuery(Request $request)
|
||||||
{
|
{
|
||||||
return DB::table('map_lahan')
|
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);
|
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