Update Kelompok Tani

This commit is contained in:
2026-11-05 21:30:38 +07:00
parent c55ff109a0
commit 291ebf919c
16 changed files with 823 additions and 413 deletions
@@ -0,0 +1,161 @@
<?php
namespace App\Services\Produktivitas;
use App\Enums\JenisKelompokTani;
use App\Enums\StatusLegalitasKelompokTani;
use App\Models\Pertanian\KelompokTani;
use App\Models\Pertanian\Komoditas;
use App\Models\Wilayah\DesaKelurahan;
use App\Models\Wilayah\KabupatenKota;
use App\Models\Wilayah\Kecamatan;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
class KelompokTaniService
{
public function profileSummary(?KelompokTani $kelompokTani = null): array
{
$kelompokTani?->loadMissing('desaKelurahan.kecamatan.kabupatenKota');
$desa = $kelompokTani?->desaKelurahan;
$statusSk = $kelompokTani?->status_legalitas;
$memilikiSk = in_array($statusSk, KelompokTani::STATUS_LEGALITAS_DENGAN_SK, true);
$komoditas = $kelompokTani?->komoditas_id
? Komoditas::whereIn('id', $kelompokTani->komoditas_id)->orderBy('nama')->pluck('nama')->unique()->values()->all()
: [];
$tanggalPerubahan = collect([$kelompokTani?->updated_at ?? $kelompokTani?->created_at])->filter();
if ($kelompokTani?->exists) {
foreach (['pengurus', 'aset', 'bantuan'] as $relation) {
// Penghapusan data bagian juga termasuk pembaruan profil kelompok.
$tanggal = $kelompokTani->{$relation}()->withTrashed()->max(DB::raw('COALESCE(updated_at, created_at)'));
if ($tanggal) {
$tanggalPerubahan->push(Carbon::parse($tanggal));
}
}
}
return [
'judul' => $kelompokTani ? ($kelompokTani->nama_kelompok ?: 'Profil Kelompok Tani') : 'Profil Kelompok Tani Baru',
'lokasi' => collect([$desa?->nama, $desa?->kecamatan?->nama, $desa?->kecamatan?->kabupatenKota?->nama])
->filter()->implode(' · ') ?: 'Lokasi belum terisi',
'jenis' => $kelompokTani?->jenis_kelompok ?: 'Belum terisi',
'legalitas' => [
'label' => $memilikiSk ? 'Sudah ada SK' : ($statusSk ?: 'Belum terisi'),
'detail' => $statusSk ?: 'Belum terisi',
'warna' => $memilikiSk ? 'success' : 'secondary',
],
'pengurus' => $kelompokTani?->jumlah_pengurus !== null ? number_format($kelompokTani->jumlah_pengurus, 0, ',', '.') : 'Belum terisi',
'anggota' => $kelompokTani?->jumlah_anggota_terdaftar !== null ? number_format($kelompokTani->jumlah_anggota_terdaftar, 0, ',', '.') : 'Belum terisi',
'komoditas' => $komoditas,
'responden' => $kelompokTani?->nama_responden ?: 'Belum terisi',
'jabatan' => $kelompokTani?->jabatan_responden ?: 'Belum terisi',
'kontak' => $kelompokTani?->kontak_responden ?: 'Belum terisi',
'tahun_berdiri' => $kelompokTani?->tahun_berdiri ?: 'Belum terisi',
'diperbarui' => $tanggalPerubahan->sortByDesc(fn ($tanggal) => $tanggal->getTimestamp())->first(),
];
}
public function indexData(array $validated): array
{
$defaultKabupaten = KabupatenKota::select('id', 'nama')
->whereRaw('lower(nama) like ?', ['%ngada%'])->orderBy('nama')->first();
$filters = [
'search' => $validated['search'] ?? null,
'kabupaten_kota_id' => $validated['kabupaten_kota_id'] ?? $defaultKabupaten?->id,
'kecamatan_id' => $validated['kecamatan_id'] ?? null,
'desa_kelurahan_id' => $validated['desa_kelurahan_id'] ?? null,
'komoditas_id' => $validated['komoditas_id'] ?? null,
'jenis_kelompok' => $validated['jenis_kelompok'] ?? null,
'status_legalitas' => $validated['status_legalitas'] ?? null,
'sort_by' => in_array($validated['sort_by'] ?? null, ['nama_asc', 'nama_desc', 'anggota_desc', 'anggota_asc'], true)
? $validated['sort_by'] : null,
];
$query = KelompokTani::query()
->when(filled($filters['search']), function ($query) use ($filters) {
$search = '%'.Str::lower($filters['search']).'%';
$query->where(function ($query) use ($search) {
$query->whereRaw('lower(nama_kelompok) like ?', [$search])
->orWhereRaw('lower(nama_responden) like ?', [$search])
->orWhereHas('desaKelurahan', function ($query) use ($search) {
$query->where(function ($query) use ($search) {
$query->whereRaw('lower(nama) like ?', [$search])
->orWhereHas('kecamatan', fn ($query) => $query->whereRaw('lower(nama) like ?', [$search]));
});
});
});
})
->when($filters['kabupaten_kota_id'], fn ($query, $id) => $query
->whereHas('desaKelurahan.kecamatan', fn ($query) => $query->where('kabupaten_kota_id', $id)))
->when($filters['kecamatan_id'], fn ($query, $id) => $query
->whereHas('desaKelurahan', fn ($query) => $query->where('kecamatan_id', $id)))
->when($filters['desa_kelurahan_id'], fn ($query, $id) => $query->where('desa_kelurahan_id', $id))
->when($filters['komoditas_id'], fn ($query, $id) => $query->where(function ($query) use ($id) {
$query->whereJsonContains('komoditas_id', (string) $id)->orWhereJsonContains('komoditas_id', (int) $id);
}))
->when($filters['jenis_kelompok'], function ($query, $value) {
if ($value === JenisKelompokTani::LAINNYA->value) {
$jenisStandar = array_diff(JenisKelompokTani::options(), [JenisKelompokTani::LAINNYA->value]);
$query->whereNotNull('jenis_kelompok')->where('jenis_kelompok', '!=', '')->whereNotIn('jenis_kelompok', $jenisStandar);
} else {
$query->where('jenis_kelompok', $value);
}
})
->when($filters['status_legalitas'], fn ($query, $value) => $query->where('status_legalitas', $value));
$summary = (clone $query)->selectRaw('
COUNT(*) AS total_kelompok,
COUNT(DISTINCT desa_kelurahan_id) AS total_desa,
COUNT(DISTINCT jenis_kelompok) AS total_jenis,
COALESCE(SUM(jumlah_pengurus), 0) AS total_pengurus,
COALESCE(SUM(jumlah_pengurus_aktif), 0) AS pengurus_aktif,
COALESCE(SUM(jumlah_anggota_terdaftar), 0) AS total_anggota,
COALESCE(SUM(jumlah_anggota_aktif), 0) AS anggota_aktif
')->first();
$summary->memiliki_sk = (clone $query)->whereIn('status_legalitas', KelompokTani::STATUS_LEGALITAS_DENGAN_SK)->count();
match ($filters['sort_by']) {
'nama_asc' => $query->orderBy('nama_kelompok'),
'nama_desc' => $query->orderByDesc('nama_kelompok'),
'anggota_desc' => $query->orderByRaw('COALESCE(jumlah_anggota_terdaftar, 0) DESC'),
'anggota_asc' => $query->orderByRaw('COALESCE(jumlah_anggota_terdaftar, 0) ASC'),
default => $query->latest(),
};
$showEnumerator = Gate::any(['super_admin', 'admin']);
$query->with('desaKelurahan.kecamatan');
if ($showEnumerator) {
$query->with('creator:id,name');
}
$perPage = (int) ($validated['per_page'] ?? 10);
$kelompokTani = $query->orderByDesc('id')->paginate($perPage)->appends([...$filters, 'per_page' => $perPage]);
$komoditasOptions = Komoditas::select('id', 'nama')->orderBy('nama')->get();
$komoditasById = $komoditasOptions->keyBy('id');
$ringkasanKelompok = $kelompokTani->getCollection()->mapWithKeys(function (KelompokTani $item) use ($komoditasById) {
$memilikiSk = in_array($item->status_legalitas, KelompokTani::STATUS_LEGALITAS_DENGAN_SK, true);
return [$item->id => [
'lokasi' => collect([$item->desaKelurahan?->nama, $item->desaKelurahan?->kecamatan?->nama])
->filter()->implode(' · ') ?: 'Lokasi belum terisi',
'komoditas' => collect($item->komoditas_id ?? [])->map(fn ($id) => $komoditasById->get($id)?->nama)->filter()->unique()->values()->all(),
'legalitas' => [
'label' => $memilikiSk ? 'Sudah ada SK' : ($item->status_legalitas ?: 'Belum terisi'),
'warna' => $memilikiSk ? 'success' : 'secondary',
],
]];
});
$selectedKabupaten = $filters['kabupaten_kota_id'] ? KabupatenKota::select('id', 'nama')->find($filters['kabupaten_kota_id']) : null;
$kecamatanOptions = $filters['kabupaten_kota_id']
? Kecamatan::select('id', 'nama')->where('kabupaten_kota_id', $filters['kabupaten_kota_id'])->orderBy('nama')->get() : collect();
$desaOptions = $filters['kecamatan_id']
? DesaKelurahan::select('id', 'nama')->where('kecamatan_id', $filters['kecamatan_id'])->orderBy('nama')->get() : collect();
$jenisKelompokOptions = collect(JenisKelompokTani::options())->values();
$statusLegalitasOptions = collect(StatusLegalitasKelompokTani::options())->values();
return compact('kelompokTani', 'summary', 'filters', 'ringkasanKelompok', 'showEnumerator', 'selectedKabupaten',
'kecamatanOptions', 'desaOptions', 'komoditasOptions', 'jenisKelompokOptions', 'statusLegalitasOptions');
}
}