route('dashboard.profil-pertanian', array_merge($request->query(), [ 'tab' => 'demografi-petani', ])); } public function profil(Request $request) { if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { abort(403); } $activeTab = $request->query('tab') === 'indeks-petani' ? 'indeks-petani' : 'demografi-petani'; $demografiData = $this->contentData($request); $indeksData = app(IndeksPetaniController::class)->contentData($request); return view('dashboard.profil-pertanian', [ 'activeTab' => $activeTab, 'indeksFilterAction' => route('dashboard.profil-pertanian'), ] + $demografiData + $indeksData); } public function contentData(Request $request): array { $filteredPetaniIds = $this->filteredPetaniIdsQuery($request); $petaniCounts = Petani::whereIn('petani.id', clone $filteredPetaniIds)->selectRaw(" COUNT(*) as total, COUNT(*) FILTER (WHERE jenis_kelamin = true) as laki, COUNT(*) FILTER (WHERE jenis_kelamin = false) as perempuan ")->first(); $totalPetani = $petaniCounts->total; $petaniLakilaki = $petaniCounts->laki; $petaniPerempuan = $petaniCounts->perempuan; $totalKomoditas = Komoditas::query() ->where('is_utama', true) ->whereHas('petani', fn ($query) => $query->whereIn('petani.id', clone $filteredPetaniIds)) ->count(); $totalLuasLahan = Lahan::has('petani') ->whereIn('petani_id', clone $filteredPetaniIds) ->sum('luas_lahan'); $ratarataLuasLahan = $totalLuasLahan && $totalPetani ? $totalLuasLahan / $totalPetani : 0; $umurCounts = Petani::whereIn('petani.id', clone $filteredPetaniIds) ->whereNotNull('tanggal_lahir')->selectRaw(" COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) < 30) as kurang_30, COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 30 AND 39) as umur_30_39, COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 40 AND 49) as umur_40_49, COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 50 AND 59) as umur_50_59, COUNT(*) FILTER (WHERE EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) >= 60) as umur_60_keatas ")->first(); $pendidikanCounts = Petani::whereIn('petani.id', clone $filteredPetaniIds) ->whereNotNull('pendidikan_terakhir') ->select('pendidikan_terakhir', DB::raw('COUNT(*) as total')) ->groupBy('pendidikan_terakhir') ->pluck('total', 'pendidikan_terakhir'); $pendidikan = [ 'tidak_sekolah' => (int) ($pendidikanCounts['01_tidak_sekolah'] ?? 0), 'sd' => (int) ($pendidikanCounts['02_sd'] ?? 0), 'smp' => (int) ($pendidikanCounts['03_smp'] ?? 0), 'sma' => (int) ($pendidikanCounts['04_sma'] ?? 0), 'diploma' => (int) ($pendidikanCounts['05_diploma'] ?? 0), 's1_keatas' => (int) ($pendidikanCounts['06_sarjana'] ?? 0) + (int) ($pendidikanCounts['07_magister'] ?? 0), ]; $jumlahTanggunganBuckets = SosialEkonomi::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->whereNotNull('jumlah_tanggungan') ->selectRaw(" COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan = 0) as tanggungan_0, COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan BETWEEN 1 AND 2) as tanggungan_1_2, COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan BETWEEN 3 AND 4) as tanggungan_3_4, COUNT(DISTINCT petani_id) FILTER (WHERE jumlah_tanggungan >= 5) as tanggungan_5_keatas ") ->first(); $jumlahTanggungan = [ '0' => (int) ($jumlahTanggunganBuckets->tanggungan_0 ?? 0), '1_2' => (int) ($jumlahTanggunganBuckets->tanggungan_1_2 ?? 0), '3_4' => (int) ($jumlahTanggunganBuckets->tanggungan_3_4 ?? 0), '5_keatas' => (int) ($jumlahTanggunganBuckets->tanggungan_5_keatas ?? 0), ]; $kelompokTaniBuckets = Petani::query() ->whereIn('petani.id', clone $filteredPetaniIds) ->leftJoin('sosial_ekonomi', function ($join) { $join->on('sosial_ekonomi.petani_id', '=', 'petani.id') ->whereNull('sosial_ekonomi.deleted_at'); }) ->selectRaw(" COUNT(DISTINCT petani.id) FILTER (WHERE sosial_ekonomi.terdaftar_kelompok_tani = 'ya') as terdaftar, COUNT(DISTINCT petani.id) FILTER (WHERE sosial_ekonomi.terdaftar_kelompok_tani = 'tidak') as tidak_terdaftar, COUNT(DISTINCT petani.id) FILTER (WHERE sosial_ekonomi.terdaftar_kelompok_tani IS NULL OR sosial_ekonomi.terdaftar_kelompok_tani NOT IN ('ya', 'tidak')) as belum_terisi ") ->first(); $kelompokTani = [ 'terdaftar' => (int) ($kelompokTaniBuckets->terdaftar ?? 0), 'tidak_terdaftar' => (int) ($kelompokTaniBuckets->tidak_terdaftar ?? 0), 'belum_terisi' => (int) ($kelompokTaniBuckets->belum_terisi ?? 0), ]; $desaSasaranRows = Petani::query() ->leftJoin('master_desa_kelurahan as desa', 'petani.desa_kelurahan_id', '=', 'desa.id') ->whereIn('petani.id', clone $filteredPetaniIds) ->selectRaw('petani.desa_kelurahan_id as desa_id') ->selectRaw("COALESCE(desa.nama, 'Tidak diketahui') as desa") ->selectRaw('COUNT(*) as total') ->groupBy('petani.desa_kelurahan_id', 'desa.nama') ->orderByDesc('total') ->orderBy('desa') ->get(); $komoditasUtama = Komoditas::query() ->whereHas('petani', fn ($query) => $query->whereIn('petani.id', clone $filteredPetaniIds)) ->withCount(['petani' => fn ($query) => $query->whereIn('petani.id', clone $filteredPetaniIds)]) ->orderByDesc('petani_count') ->get(['id', 'nama']); $luasLahanBuckets = DB::query()->fromSub( Lahan::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->select('petani_id') ->selectRaw('luas_lahan'), 'agg' )->selectRaw(" COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan < 0.5) as kurang_05, COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan >= 0.5 AND luas_lahan <= 1) as luas_05_1, COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan > 1 AND luas_lahan <= 2) as luas_1_2, COUNT(DISTINCT petani_id) FILTER (WHERE luas_lahan > 2) as lebih_2 ")->first(); $luasLahan = [ 'kurang_05' => $luasLahanBuckets->kurang_05, '05_1' => $luasLahanBuckets->luas_05_1, '1_2' => $luasLahanBuckets->luas_1_2, 'lebih_2' => $luasLahanBuckets->lebih_2, ]; $statusKepemilikanLahanRows = Lahan::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->whereNotNull('status_kepemilikan') ->selectRaw('status_kepemilikan as status') ->selectRaw('COUNT(DISTINCT petani_id) as total') ->groupBy('status_kepemilikan') ->orderByDesc('total') ->get(); $pendapatanPerPetaniQuery = PendapatanKomoditas::query() ->join('sosial_ekonomi', 'sosial_ekonomi.id', '=', 'pendapatan_komoditas.sosial_ekonomi_id') ->whereNotNull('sosial_ekonomi.petani_id') ->whereIn('sosial_ekonomi.petani_id', clone $filteredPetaniIds) ->groupBy('sosial_ekonomi.petani_id') ->selectRaw('SUM(pendapatan_komoditas.pendapatan) as total_pendapatan'); $ratarataPenghasilan = (float) DB::query() ->fromSub(clone $pendapatanPerPetaniQuery, 'agg') ->avg('total_pendapatan'); $penghasilanBuckets = DB::query()->fromSub( clone $pendapatanPerPetaniQuery, 'agg' )->selectRaw(" COUNT(*) FILTER (WHERE total_pendapatan < 1000000) as kurang_1, COUNT(*) FILTER (WHERE total_pendapatan >= 1000000 AND total_pendapatan <= 3000000) as p1_3, COUNT(*) FILTER (WHERE total_pendapatan > 3000000 AND total_pendapatan <= 5000000) as p3_5, COUNT(*) FILTER (WHERE total_pendapatan > 5000000 AND total_pendapatan <= 10000000) as p5_10, COUNT(*) FILTER (WHERE total_pendapatan > 10000000) as lebih_10 ")->first(); $penghasilan = [ 'kurang_1' => $penghasilanBuckets->kurang_1, '1_3' => $penghasilanBuckets->p1_3, '3_5' => $penghasilanBuckets->p3_5, '5_10' => $penghasilanBuckets->p5_10, 'lebih_10' => $penghasilanBuckets->lebih_10, ]; $data = [ 'total_petani' => $totalPetani, 'petani_lakilaki' => $petaniLakilaki, 'petani_perempuan' => $petaniPerempuan, 'total_komoditas' => $totalKomoditas, 'total_luas_lahan' => $totalLuasLahan, 'ratarata_luas_lahan' => $ratarataLuasLahan, 'ratarata_penghasilan' => $ratarataPenghasilan, 'kelompok_umur' => [ 'kurang_30' => $umurCounts->kurang_30, '30_39' => $umurCounts->umur_30_39, '40_49' => $umurCounts->umur_40_49, '50_59' => $umurCounts->umur_50_59, '60_keatas' => $umurCounts->umur_60_keatas, ], 'pendidikan' => $pendidikan, 'jumlah_tanggungan' => $jumlahTanggungan, 'kelompok_tani' => $kelompokTani, 'desa_sasaran' => [ 'total' => $desaSasaranRows->count(), 'ids' => $desaSasaranRows->pluck('desa_id')->values(), 'labels' => $desaSasaranRows->pluck('desa')->values(), 'series' => $desaSasaranRows->pluck('total')->map(fn ($v) => (int) $v)->values(), ], 'komoditas_utama' => [ 'ids' => $komoditasUtama->pluck('id')->values(), 'labels' => $komoditasUtama->pluck('nama')->values(), 'series' => $komoditasUtama->pluck('petani_count')->map(fn ($v) => (int) $v)->values(), ], 'luas_lahan' => $luasLahan, 'status_kepemilikan_lahan' => [ 'keys' => $statusKepemilikanLahanRows->pluck('status')->values(), 'labels' => $statusKepemilikanLahanRows ->pluck('status') ->map(fn ($status) => $this->statusLahanLabel((string) $status)) ->values(), 'series' => $statusKepemilikanLahanRows->pluck('total')->map(fn ($v) => (int) $v)->values(), ], 'penghasilan' => $penghasilan, ]; $daftarPetani = Petani::with(['komoditas']) ->whereIn('petani.id', clone $filteredPetaniIds) ->withSum('lahans as total_luas_lahan', 'luas_lahan') ->orderBy('id') ->paginate(10); return compact('data', 'daftarPetani'); } private function filteredPetaniIdsQuery(Request $request) { $query = Petani::query() ->leftJoin('master_desa_kelurahan as desa', 'petani.desa_kelurahan_id', '=', 'desa.id') ->leftJoin('master_kecamatan as kecamatan', 'desa.kecamatan_id', '=', 'kecamatan.id') ->leftJoin('master_kabupaten_kota as kabupaten', 'kecamatan.kabupaten_kota_id', '=', 'kabupaten.id') ->when($request->filled('provinsi_id'), fn ($query) => $query->where('kabupaten.provinsi_id', $request->provinsi_id)) ->when($request->filled('kabupatenKota_id'), fn ($query) => $query->where('kecamatan.kabupaten_kota_id', $request->kabupatenKota_id)) ->when($request->filled('kecamatan_id'), fn ($query) => $query->where('desa.kecamatan_id', $request->kecamatan_id)) ->when($request->filled('desaKelurahan_id'), fn ($query) => $query->where('petani.desa_kelurahan_id', $request->desaKelurahan_id)) ->when($request->filled('komoditas_id'), fn ($query) => $query->where('petani.komoditas_id', $request->komoditas_id)); if ($request->filled('segmen')) { $query->whereHas('skor', function ($query) use ($request) { match ($request->segmen) { 'Penggerak' => $query->where('skor_kesiapan_adopsi', '>=', 4), 'Perintis' => $query->where('skor_kesiapan_adopsi', '>=', 3) ->where('skor_kesiapan_adopsi', '<', 4), 'Pemerhati' => $query->where('skor_kesiapan_adopsi', '>=', 2) ->where('skor_kesiapan_adopsi', '<', 3), 'Pemula' => $query->where('skor_kesiapan_adopsi', '>=', 1) ->where('skor_kesiapan_adopsi', '<', 2), 'Belum Lengkap' => $query->where(function ($query) { $query->whereNull('skor_kesiapan_adopsi') ->orWhere('skor_kesiapan_adopsi', '<', 1); }), default => null, }; }); } return $query->select('petani.id'); } private function statusLahanLabel(string $status): string { return match ($status) { 'sendiri' => 'Milik Pribadi', 'sewa' => 'Sewa', 'adat' => 'Tanah Adat', default => ucwords(str_replace('_', ' ', $status)), }; } public function data(Request $request) { $filteredPetaniIds = $this->filteredPetaniIdsQuery($request); $pendapatanSub = PendapatanKomoditas::query() ->join('sosial_ekonomi', 'sosial_ekonomi.id', '=', 'pendapatan_komoditas.sosial_ekonomi_id') ->whereColumn('sosial_ekonomi.petani_id', 'petani.id') ->selectRaw('SUM(pendapatan_komoditas.pendapatan)'); $query = Petani::with('komoditas') ->whereIn('petani.id', clone $filteredPetaniIds) ->withSum('lahans as total_luas_lahan', 'luas_lahan') ->addSelect(['total_pendapatan' => $pendapatanSub]); if ($request->filled('search')) { $query->where('nama', 'ILIKE', "%{$request->search}%"); } if ($request->has('gender') && $request->gender !== '') { $query->where('jenis_kelamin', $request->gender); } if ($request->filled('umur')) { match ($request->umur) { 'kurang_30' => $query->whereNotNull('tanggal_lahir') ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) < 30"), '30_39' => $query->whereNotNull('tanggal_lahir') ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 30 AND 39"), '40_49' => $query->whereNotNull('tanggal_lahir') ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 40 AND 49"), '50_59' => $query->whereNotNull('tanggal_lahir') ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) BETWEEN 50 AND 59"), '60_keatas' => $query->whereNotNull('tanggal_lahir') ->whereRaw("EXTRACT(YEAR FROM AGE(CURRENT_DATE, tanggal_lahir)) >= 60"), default => null, }; } if ($request->filled('pendidikan')) { $pendidikanMap = [ 'tidak_sekolah' => ['01_tidak_sekolah'], 'sd' => ['02_sd'], 'smp' => ['03_smp'], 'sma' => ['04_sma'], 'diploma' => ['05_diploma'], 's1_keatas' => ['06_sarjana', '07_magister'], ]; if (isset($pendidikanMap[$request->pendidikan])) { $query->whereIn('pendidikan_terakhir', $pendidikanMap[$request->pendidikan]); } } if ($request->filled('jumlah_tanggungan')) { $tanggunganQuery = SosialEkonomi::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->whereNotNull('jumlah_tanggungan') ->select('petani_id') ->distinct(); match ($request->jumlah_tanggungan) { '0' => $tanggunganQuery->where('jumlah_tanggungan', 0), '1_2' => $tanggunganQuery->whereBetween('jumlah_tanggungan', [1, 2]), '3_4' => $tanggunganQuery->whereBetween('jumlah_tanggungan', [3, 4]), '5_keatas' => $tanggunganQuery->where('jumlah_tanggungan', '>=', 5), default => null, }; $query->whereIn('petani.id', $tanggunganQuery); } if ($request->filled('kelompok_tani')) { match ($request->kelompok_tani) { 'terdaftar' => $query->whereIn('petani.id', SosialEkonomi::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->where('terdaftar_kelompok_tani', 'ya') ->select('petani_id') ->distinct()), 'tidak_terdaftar' => $query->whereIn('petani.id', SosialEkonomi::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->where('terdaftar_kelompok_tani', 'tidak') ->select('petani_id') ->distinct()), 'belum_terisi' => $query->whereNotIn('petani.id', SosialEkonomi::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->whereIn('terdaftar_kelompok_tani', ['ya', 'tidak']) ->select('petani_id') ->distinct()), default => null, }; } if ($request->filled('komoditas')) { $query->where('komoditas_id', $request->komoditas); } if ($request->filled('penghasilan')) { [$min, $max] = match ($request->penghasilan) { 'kurang_1' => [null, 999999], '1_3' => [1000000, 3000000], '3_5' => [3000001, 5000000], '5_10' => [5000001, 10000000], 'lebih_10' => [10000001, null], default => [null, null], }; $query->whereIn('id', function ($sub) use ($min, $max) { $sub->from('pendapatan_komoditas') ->join('sosial_ekonomi', 'sosial_ekonomi.id', '=', 'pendapatan_komoditas.sosial_ekonomi_id') ->whereNotNull('sosial_ekonomi.petani_id') ->groupBy('sosial_ekonomi.petani_id') ->select('sosial_ekonomi.petani_id') ->when($min !== null, fn ($q) => $q->havingRaw('SUM(pendapatan_komoditas.pendapatan) >= ?', [$min])) ->when($max !== null, fn ($q) => $q->havingRaw('SUM(pendapatan_komoditas.pendapatan) <= ?', [$max])); }); } if ($request->filled('luas_lahan')) { $lahanQuery = Lahan::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->select('petani_id') ->distinct(); match ($request->luas_lahan) { 'kurang_05' => $lahanQuery->where('luas_lahan', '<', 0.5), '05_1' => $lahanQuery->whereBetween('luas_lahan', [0.5, 1]), '1_2' => $lahanQuery->where('luas_lahan', '>', 1)->where('luas_lahan', '<=', 2), 'lebih_2' => $lahanQuery->where('luas_lahan', '>', 2), default => null, }; $query->whereIn('petani.id', $lahanQuery); } if ($request->filled('status_kepemilikan_lahan')) { $query->whereIn('petani.id', Lahan::query() ->whereIn('petani_id', clone $filteredPetaniIds) ->where('status_kepemilikan', $request->status_kepemilikan_lahan) ->select('petani_id') ->distinct()); } $daftarPetani = $query->orderBy('id')->paginate(10); $pendidikanLabels = [ '01_tidak_sekolah' => 'Tidak Sekolah', '02_sd' => 'SD', '03_smp' => 'SMP', '04_sma' => 'SMA', '05_diploma' => 'Diploma', '06_sarjana' => 'Sarjana', '07_magister' => 'Magister', ]; $rows = collect($daftarPetani->items())->map(function ($petani) use ($pendidikanLabels) { $umur = $petani->tanggal_lahir ? \Carbon\Carbon::parse($petani->tanggal_lahir)->age : null; $pendidikanRaw = $petani->getRawOriginal('pendidikan_terakhir'); $pendapatan = $petani->total_pendapatan; $rentangPenghasilan = match (true) { $pendapatan === null => '-', $pendapatan < 1000000 => '< Rp1 juta', $pendapatan <= 3000000 => 'Rp1 - 3 juta', $pendapatan <= 5000000 => 'Rp3 - 5 juta', $pendapatan <= 10000000 => 'Rp5 - 10 juta', default => '> Rp10 juta', }; return [ 'id' => $petani->id, 'nama' => $petani->nama ?? '-', 'jenis_kelamin' => $petani->jenis_kelamin, 'gender' => $petani->jenis_kelamin == 1 ? 'Laki-laki' : 'Perempuan', 'umur' => $umur, 'komoditas' => $petani->komoditas?->nama ?? '-', 'luas_lahan' => (float) ($petani->total_luas_lahan ?? 0), 'pendidikan' => $pendidikanLabels[$pendidikanRaw] ?? '-', 'rentang_penghasilan' => $rentangPenghasilan, ]; }); return response()->json([ 'data' => $rows, 'pagination' => [ 'current_page' => $daftarPetani->currentPage(), 'last_page' => $daftarPetani->lastPage(), 'per_page' => $daftarPetani->perPage(), 'total' => $daftarPetani->total(), 'from' => $daftarPetani->firstItem(), 'to' => $daftarPetani->lastItem(), ], ]); } }