update kelompok tani

This commit is contained in:
2026-11-03 17:53:53 +07:00
parent f455f8b878
commit 53913bebe9
20 changed files with 2319 additions and 1041 deletions
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Web\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
@@ -31,21 +32,30 @@ class AsetKelompokTaniController extends Controller
}
}
private function redirectToSection(string $url, string $section, string $message)
private function redirectToSection(string $url, string $section, string $message, ?string $nextSection = null)
{
return redirect($url . '#section-' . $section)->with([
return redirect($url . '#section-' . ($nextSection ?? $section))->with([
'success' => $message,
'success_section' => $section,
]);
}
private function kegiatanUrl(KelompokTani $kelompokTani): string
{
return route('kelompok-tani.edit', $kelompokTani->id) . '?section=aktivitas-fungsi';
}
private function nextAssetSection(KelompokTani $kelompokTani): string
{
return $kelompokTani->aset()->where('jenis_aset', 'Kas/simpanan kelompok')->where('status_aset', true)->exists()
? 'kas' : 'status-bantuan';
}
public function index(KelompokTani $kelompokTani)
{
$this->authorizeAccess();
$kelompokTani->load('aset');
return view('produktivitas.survey-kelompok-tani.aset-keuangan', compact('kelompokTani'));
return redirect($this->kegiatanUrl($kelompokTani) . '#section-aset-baku');
}
public function update(Request $request, KelompokTani $kelompokTani)
@@ -56,11 +66,26 @@ class AsetKelompokTaniController extends Controller
'aset' => ['required', 'array'],
'aset.*.jenis_aset' => ['required', Rule::in(self::JENIS_ASET_BAKU)],
'aset.*.status_aset' => ['nullable', 'boolean'],
'aset.*.status_pengelolaan_aset' => ['nullable', 'string', 'max:100'],
'aset.*.kondisi_aset' => ['nullable', 'string', 'max:100'],
'aset.*.status_pengelolaan_aset' => ['required_if_accepted:aset.*.status_aset', 'nullable', 'string', 'max:100'],
'aset.*.kondisi_aset' => ['required_if_accepted:aset.*.status_aset', 'nullable', 'string', 'max:100'],
...$this->asetLainnyaRules(),
], [
'aset.*.status_pengelolaan_aset.required_if_accepted' => 'Status Pengelolaan wajib diisi jika aset dipilih Ada.',
'aset.*.kondisi_aset.required_if_accepted' => 'Kondisi wajib diisi jika aset dipilih Ada.',
'aset_lainnya.*.jenis_aset.not_in' => 'Jenis aset ini sudah ada di daftar baku di atas.',
]);
foreach ($validated['aset'] as $item) {
DB::transaction(function () use ($kelompokTani, $validated) {
$this->saveAsetBaku($kelompokTani, $validated['aset']);
$this->createAsetLainnya($kelompokTani, $validated['aset_lainnya'] ?? []);
});
return $this->redirectToSection($this->kegiatanUrl($kelompokTani), 'aset-baku', 'Data Operasional berhasil disimpan.', $this->nextAssetSection($kelompokTani));
}
private function saveAsetBaku(KelompokTani $kelompokTani, array $items): void
{
foreach ($items as $item) {
$jenisAset = $item['jenis_aset'];
$ada = (bool) ($item['status_aset'] ?? false);
@@ -82,8 +107,8 @@ class AsetKelompokTaniController extends Controller
$existing->update([
'status_aset' => true,
'status_pengelolaan_aset' => $item['status_pengelolaan_aset'] ?? $existing->status_pengelolaan_aset,
'kondisi_aset' => $item['kondisi_aset'] ?? $existing->kondisi_aset,
'status_pengelolaan_aset' => $item['status_pengelolaan_aset'],
'kondisi_aset' => $item['kondisi_aset'],
'deleted_by' => null,
'updated_by' => auth()->id(),
]);
@@ -94,30 +119,40 @@ class AsetKelompokTaniController extends Controller
'uid' => 'AKT-' . strtoupper(Str::random(10)),
'jenis_aset' => $jenisAset,
'status_aset' => true,
'status_pengelolaan_aset' => $item['status_pengelolaan_aset'] ?? '-',
'kondisi_aset' => $item['kondisi_aset'] ?? '-',
'status_pengelolaan_aset' => $item['status_pengelolaan_aset'],
'kondisi_aset' => $item['kondisi_aset'],
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
}
}
return $this->redirectToSection(route('kelompok-tani.aset-keuangan.index', $kelompokTani->id), 'aset-baku', 'Data aset produktif berhasil disimpan.');
private function asetLainnyaRules(): array
{
return [
'aset_lainnya' => ['nullable', 'array'],
'aset_lainnya.*.jenis_aset' => ['nullable', 'string', 'max:255', Rule::notIn(self::JENIS_ASET_BAKU)],
'aset_lainnya.*.status_pengelolaan_aset' => ['nullable', 'string', 'max:100'],
'aset_lainnya.*.kondisi_aset' => ['nullable', 'string', 'max:100'],
];
}
public function store(Request $request, KelompokTani $kelompokTani)
{
$this->authorizeAccess();
$validated = $request->validate([
'aset_lainnya' => ['nullable', 'array'],
'aset_lainnya.*.jenis_aset' => ['nullable', 'string', 'max:255', Rule::notIn(self::JENIS_ASET_BAKU)],
'aset_lainnya.*.status_pengelolaan_aset' => ['nullable', 'string', 'max:100'],
'aset_lainnya.*.kondisi_aset' => ['nullable', 'string', 'max:100'],
], [
$validated = $request->validate($this->asetLainnyaRules(), [
'aset_lainnya.*.jenis_aset.not_in' => 'Jenis aset ini sudah ada di daftar baku di atas.',
]);
foreach ($validated['aset_lainnya'] ?? [] as $item) {
DB::transaction(fn () => $this->createAsetLainnya($kelompokTani, $validated['aset_lainnya'] ?? []));
return $this->redirectToSection($this->kegiatanUrl($kelompokTani), 'aset-lainnya', 'Data Operasional berhasil ditambahkan.', $this->nextAssetSection($kelompokTani));
}
private function createAsetLainnya(KelompokTani $kelompokTani, array $items): void
{
foreach ($items as $item) {
$jenisAset = trim($item['jenis_aset'] ?? '');
if ($jenisAset === '') {
@@ -134,8 +169,6 @@ class AsetKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
}
return $this->redirectToSection(route('kelompok-tani.aset-keuangan.index', $kelompokTani->id), 'aset-lainnya', 'Aset lainnya berhasil ditambahkan.');
}
public function destroy(KelompokTani $kelompokTani, AsetKelompokTani $aset)
@@ -143,11 +176,11 @@ class AsetKelompokTaniController extends Controller
$this->authorizeAccess();
abort_unless($aset->survey_kelompok_tani_id === $kelompokTani->id, 404);
abort_if(in_array($aset->jenis_aset, self::JENIS_ASET_BAKU), 422, 'Aset baku diatur lewat checklist, bukan dihapus langsung.');
abort_if(in_array($aset->jenis_aset, self::JENIS_ASET_BAKU), 422, 'Operasional: gunakan pilihan Ada/Tidak pada tabel untuk menghapus aset baku.');
$aset->update(['deleted_by' => auth()->id()]);
$aset->delete();
return $this->redirectToSection(route('kelompok-tani.aset-keuangan.index', $kelompokTani->id), 'aset-lainnya', 'Aset lainnya berhasil dihapus.');
return $this->redirectToSection($this->kegiatanUrl($kelompokTani), 'aset-lainnya', 'Data Operasional berhasil dihapus.');
}
}
@@ -5,7 +5,9 @@ namespace App\Http\Controllers\Web\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use App\Models\Pertanian\KelompokTani;
use App\Models\Pertanian\BantuanKelompokTani;
@@ -19,9 +21,9 @@ class BantuanKelompokTaniController extends Controller
}
}
private function redirectToSection(string $url, string $section, string $message)
private function redirectToSection(string $url, string $section, string $message, ?string $nextSection = null)
{
return redirect($url . '#section-' . $section)->with([
return redirect($url . '#section-' . ($nextSection ?? $section))->with([
'success' => $message,
'success_section' => $section,
]);
@@ -29,7 +31,7 @@ class BantuanKelompokTaniController extends Controller
private function redirectToSectionWithError(string $url, string $section, string $message)
{
return redirect($url . '#section-' . $section)->with([
return redirect($url . '#kelompok-tani-notifications')->with([
'error' => $message,
'error_section' => $section,
]);
@@ -39,9 +41,72 @@ class BantuanKelompokTaniController extends Controller
{
$this->authorizeAccess();
$kelompokTani->load('bantuan');
return redirect($this->operasionalUrl($kelompokTani) . '#section-status-bantuan');
}
return view('produktivitas.survey-kelompok-tani.bantuan-penilaian', compact('kelompokTani'));
private function operasionalUrl(KelompokTani $kelompokTani): string
{
return route('kelompok-tani.edit', $kelompokTani->id) . '?section=aktivitas-fungsi';
}
private function hasRecordedAid(KelompokTani $kelompokTani): bool
{
return $kelompokTani->bantuan()->whereRaw("TRIM(nama_program) <> ''")->exists();
}
private function bantuanRules(bool $pernah = true, bool $requireFirstRow = false): array
{
$exclude = Rule::excludeIf(!$pernah);
return [
'bantuan' => [$exclude, Rule::requiredIf($requireFirstRow), 'nullable', 'array'],
'bantuan.*' => [$exclude, 'array'],
'bantuan.*.nama_program' => [$exclude, 'required_with:bantuan.*.penyelenggara,bantuan.*.bentuk_bantuan,bantuan.*.tahun', 'nullable', 'string', 'max:255'],
'bantuan.*.penyelenggara' => [$exclude, 'nullable', 'string', 'max:255'],
'bantuan.*.bentuk_bantuan' => [$exclude, 'nullable', 'string', 'max:255'],
'bantuan.*.tahun' => [$exclude, 'nullable', 'integer', 'min:1900', 'max:' . date('Y')],
'bantuan.0.nama_program' => [$exclude, Rule::requiredIf($requireFirstRow), 'required_with:bantuan.0.penyelenggara,bantuan.0.bentuk_bantuan,bantuan.0.tahun', 'nullable', 'string', 'max:255'],
'bantuan.0.penyelenggara' => [$exclude, Rule::requiredIf($requireFirstRow), 'nullable', 'string', 'max:255'],
'bantuan.0.bentuk_bantuan' => [$exclude, Rule::requiredIf($requireFirstRow), 'nullable', 'string', 'max:255'],
'bantuan.0.tahun' => [$exclude, Rule::requiredIf($requireFirstRow), 'nullable', 'integer', 'min:1900', 'max:' . date('Y')],
];
}
private function bantuanMessages(): array
{
return [
'pernah_mendapatkan_bantuan.required' => 'Pengalaman Akses Bantuan/Program wajib diisi.',
'pernah_mendapatkan_bantuan.boolean' => 'Pilih Pernah atau Belum Pernah untuk Pengalaman Akses Bantuan/Program.',
'bantuan.required' => 'Isi minimal satu data bantuan jika memilih Pernah.',
'bantuan.0.nama_program.required' => 'Nama Program/Bantuan pada baris pertama wajib diisi.',
'bantuan.0.penyelenggara.required' => 'Penyelenggara pada baris pertama wajib diisi.',
'bantuan.0.bentuk_bantuan.required' => 'Bentuk Bantuan pada baris pertama wajib diisi.',
'bantuan.0.tahun.required' => 'Tahun pada baris pertama wajib diisi.',
'bantuan.*.nama_program.required_with' => 'Nama Program/Bantuan wajib diisi jika baris bantuan diisi.',
];
}
public function update(Request $request, KelompokTani $kelompokTani)
{
$this->authorizeAccess();
$validated = $request->validate([
'pernah_mendapatkan_bantuan' => ['required', 'boolean'],
...$this->bantuanRules(
$request->boolean('pernah_mendapatkan_bantuan'),
$request->boolean('pernah_mendapatkan_bantuan') && !$this->hasRecordedAid($kelompokTani)
),
], $this->bantuanMessages());
DB::transaction(function () use ($kelompokTani, $validated) {
$kelompokTani->update([
'pernah_mendapatkan_bantuan' => $validated['pernah_mendapatkan_bantuan'],
'updated_by' => auth()->id(),
]);
$this->createBantuan($kelompokTani, $validated['bantuan'] ?? []);
});
return $this->redirectToSection($this->operasionalUrl($kelompokTani), 'status-bantuan', 'Data Operasional berhasil disimpan.');
}
public function store(Request $request, KelompokTani $kelompokTani)
@@ -50,37 +115,37 @@ class BantuanKelompokTaniController extends Controller
if (!$kelompokTani->pernah_mendapatkan_bantuan) {
return $this->redirectToSectionWithError(
route('kelompok-tani.bantuan-penilaian.index', $kelompokTani->id),
$this->operasionalUrl($kelompokTani),
'status-bantuan',
'Set status jadi "Pernah" dulu sebelum menambahkan daftar bantuan/program.'
'Operasional: pilih jawaban "Pernah" terlebih dahulu sebelum menambahkan data bantuan/program.'
);
}
$validated = $request->validate([
'bantuan' => ['nullable', 'array'],
'bantuan.*.nama_program' => ['nullable', 'string', 'max:255'],
'bantuan.*.penyelenggara' => ['nullable', 'string', 'max:255'],
'bantuan.*.bentuk_bantuan' => ['nullable', 'string', 'max:255'],
'bantuan.*.tahun' => ['nullable', 'integer', 'min:1900', 'max:' . date('Y')],
]);
$validated = $request->validate($this->bantuanRules(true, !$this->hasRecordedAid($kelompokTani)), $this->bantuanMessages());
foreach ($validated['bantuan'] ?? [] as $item) {
if (empty($item['nama_program']) && empty($item['penyelenggara']) && empty($item['bentuk_bantuan'])) {
DB::transaction(fn () => $this->createBantuan($kelompokTani, $validated['bantuan'] ?? []));
return $this->redirectToSection($this->operasionalUrl($kelompokTani), 'status-bantuan', 'Data Operasional berhasil ditambahkan.');
}
private function createBantuan(KelompokTani $kelompokTani, array $items): void
{
foreach ($items as $item) {
$namaProgram = trim($item['nama_program'] ?? '');
if ($namaProgram === '') {
continue;
}
$kelompokTani->bantuan()->create([
'uid' => 'BKT-' . strtoupper(Str::random(10)),
'nama_program' => $item['nama_program'] ?? null,
'penyelenggara' => $item['penyelenggara'] ?? null,
'bentuk_bantuan' => $item['bentuk_bantuan'] ?? null,
'nama_program' => $namaProgram,
'penyelenggara' => $item['penyelenggara'] ?? '',
'bentuk_bantuan' => $item['bentuk_bantuan'] ?? '',
'tahun' => $item['tahun'] ?? null,
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
}
return $this->redirectToSection(route('kelompok-tani.bantuan-penilaian.index', $kelompokTani->id), 'bantuan', 'Data bantuan berhasil ditambahkan.');
}
public function destroy(KelompokTani $kelompokTani, BantuanKelompokTani $bantuan)
@@ -89,9 +154,18 @@ class BantuanKelompokTaniController extends Controller
abort_unless($bantuan->survey_kelompok_tani_id === $kelompokTani->id, 404);
if ($kelompokTani->pernah_mendapatkan_bantuan && !$kelompokTani->bantuan()
->where('id', '!=', $bantuan->id)->whereRaw("TRIM(nama_program) <> ''")->exists()) {
return $this->redirectToSectionWithError(
$this->operasionalUrl($kelompokTani),
'status-bantuan',
'Operasional: minimal satu data bantuan harus tersedia saat jawaban masih Pernah.'
);
}
$bantuan->update(['deleted_by' => auth()->id()]);
$bantuan->delete();
return $this->redirectToSection(route('kelompok-tani.bantuan-penilaian.index', $kelompokTani->id), 'bantuan', 'Data bantuan berhasil dihapus.');
return $this->redirectToSection($this->operasionalUrl($kelompokTani), 'status-bantuan', 'Data Operasional berhasil dihapus.');
}
}
@@ -31,9 +31,7 @@ class PengurusKelompokTaniController extends Controller
{
$this->authorizeAccess();
$kelompokTani->load('pengurus');
return view('produktivitas.survey-kelompok-tani.pengurus-anggota', compact('kelompokTani'));
return redirect(route('kelompok-tani.edit', $kelompokTani->id) . '#section-ringkasan');
}
public function store(Request $request, KelompokTani $kelompokTani)
@@ -64,7 +62,7 @@ class PengurusKelompokTaniController extends Controller
]);
}
return $this->redirectToSection(route('kelompok-tani.pengurus-anggota.index', $kelompokTani->id), 'pengurus', 'Data pengurus berhasil ditambahkan.');
return $this->redirectToSection(route('kelompok-tani.edit', $kelompokTani->id), 'pengurus', 'Data Profil berhasil ditambahkan.');
}
public function destroy(KelompokTani $kelompokTani, PengurusKelompokTani $pengurus)
@@ -76,6 +74,6 @@ class PengurusKelompokTaniController extends Controller
$pengurus->update(['deleted_by' => auth()->id()]);
$pengurus->delete();
return $this->redirectToSection(route('kelompok-tani.pengurus-anggota.index', $kelompokTani->id), 'pengurus', 'Data pengurus berhasil dihapus.');
return $this->redirectToSection(route('kelompok-tani.edit', $kelompokTani->id), 'pengurus', 'Data Profil berhasil dihapus.');
}
}
@@ -6,9 +6,13 @@ use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use App\Models\Pertanian\KelompokTani;
use App\Models\Wilayah\Provinsi;
use App\Models\Wilayah\KabupatenKota;
use App\Models\Wilayah\Kecamatan;
use App\Models\Wilayah\DesaKelurahan;
use App\Models\Pertanian\Komoditas;
class SurveyKelompokTaniController extends Controller
@@ -20,9 +24,9 @@ class SurveyKelompokTaniController extends Controller
}
}
private function redirectToSection(string $url, string $section, string $message)
private function redirectToSection(string $url, string $section, string $message, ?string $nextSection = null)
{
return redirect($url . '#section-' . $section)->with([
return redirect($url . '#section-' . ($nextSection ?? $section))->with([
'success' => $message,
'success_section' => $section,
]);
@@ -30,13 +34,90 @@ class SurveyKelompokTaniController extends Controller
public function index(Request $request)
{
$kelompokTani = KelompokTani::query()
->when($request->search, fn ($query, $search) => $query->where('nama_kelompok', 'like', "%{$search}%"))
->latest()
->paginate($request->per_page ?? 10)
->appends($request->query());
$validated = $request->validate([
'search' => ['nullable', 'string', 'max:255'],
'kabupaten_kota_id' => ['nullable', 'integer', 'exists:master_kabupaten_kota,id'],
'kecamatan_id' => ['nullable', 'integer', 'exists:master_kecamatan,id'],
'desa_kelurahan_id' => ['nullable', 'integer', 'exists:master_desa_kelurahan,id'],
'komoditas_id' => ['nullable', 'integer', 'exists:master_komoditas,id'],
'jenis_kelompok' => ['nullable', 'string', 'max:50'],
'sort_by' => ['nullable', 'string'],
'per_page' => ['nullable', 'integer', 'in:10,25'],
]);
return view('produktivitas.survey-kelompok-tani.index', compact('kelompokTani'));
$defaultKabupaten = KabupatenKota::select('id', 'nama')
->whereRaw('lower(nama) like ?', ['%ngada%'])->orderBy('nama')->first();
$allowedSorts = ['nama_asc', 'nama_desc', 'anggota_desc', 'anggota_asc'];
$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,
'sort_by' => in_array($validated['sort_by'] ?? null, $allowedSorts, 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]);
});
})
->when($filters['kabupaten_kota_id'], function ($query, $id) {
$query->whereHas('desaKelurahan.kecamatan', fn ($query) => $query->where('kabupaten_kota_id', $id));
})
->when($filters['kecamatan_id'], function ($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'], function ($query, $id) {
$query->where(function ($query) use ($id) {
$query->whereJsonContains('komoditas_id', (string) $id)
->orWhereJsonContains('komoditas_id', (int) $id);
});
})
->when($filters['jenis_kelompok'], fn ($query, $jenis) => $query->where('jenis_kelompok', $jenis));
$summary = (clone $query)->selectRaw('
COUNT(*) AS total_kelompok,
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();
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(),
};
$perPage = (int) ($validated['per_page'] ?? 10);
$kelompokTani = $query->with('desaKelurahan.kecamatan')->orderByDesc('id')
->paginate($perPage)->appends([...$filters, 'per_page' => $perPage]);
$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();
$komoditasOptions = Komoditas::select('id', 'nama')->orderBy('nama')->get();
$jenisKelompokOptions = KelompokTani::query()->whereNotNull('jenis_kelompok')
->where('jenis_kelompok', '!=', '')->distinct()->orderBy('jenis_kelompok')->pluck('jenis_kelompok');
return view('produktivitas.survey-kelompok-tani.index', compact(
'kelompokTani', 'summary', 'filters', 'selectedKabupaten',
'kecamatanOptions', 'desaOptions', 'komoditasOptions', 'jenisKelompokOptions'
));
}
public function create()
@@ -46,7 +127,24 @@ class SurveyKelompokTaniController extends Controller
$provinsi = Provinsi::orderBy('kode', 'asc')->get();
$komoditas = Komoditas::where('is_utama', true)->get();
return view('produktivitas.survey-kelompok-tani.add', compact('provinsi', 'komoditas'));
return view('produktivitas.survey-kelompok-tani.add', [
...compact('provinsi', 'komoditas'),
...$this->profileLocationOptions(),
]);
}
private function profileLocationOptions(?KelompokTani $kelompokTani = null): array
{
$locationId = static fn ($value) => is_scalar($value) && filter_var($value, FILTER_VALIDATE_INT) !== false ? (int) $value : null;
$provinsiId = $locationId(old('provinsi_id', $kelompokTani?->desaKelurahan?->kecamatan?->kabupatenKota?->provinsi_id));
$kabupatenId = $locationId(old('kabupaten_id', $kelompokTani?->desaKelurahan?->kecamatan?->kabupaten_kota_id));
$kecamatanId = $locationId(old('kecamatan_id', $kelompokTani?->desaKelurahan?->kecamatan_id));
return [
'kabupatenOptions' => filled($provinsiId) ? KabupatenKota::where('provinsi_id', $provinsiId)->orderBy('nama')->get() : collect(),
'kecamatanOptions' => filled($kabupatenId) ? Kecamatan::where('kabupaten_kota_id', $kabupatenId)->orderBy('nama')->get() : collect(),
'desaOptions' => filled($kecamatanId) ? DesaKelurahan::where('kecamatan_id', $kecamatanId)->orderBy('nama')->get() : collect(),
];
}
public function store(Request $request)
@@ -67,7 +165,7 @@ class SurveyKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
return $this->redirectToSection(route('kelompok-tani.edit', $kelompokTani->id), 'identitas', 'Data kelompok tani berhasil ditambahkan.');
return $this->redirectToSection(route('kelompok-tani.edit', $kelompokTani->id), 'identitas', 'Data Profil berhasil ditambahkan.', 'pengurus');
}
private function editUrl(KelompokTani $kelompokTani, string $section = 'identitas'): string
@@ -83,12 +181,15 @@ class SurveyKelompokTaniController extends Controller
return match ($request->query('section', 'identitas')) {
'kelembagaan' => view('produktivitas.survey-kelompok-tani.kelembagaan', compact('kelompokTani')),
'aktivitas-fungsi' => view('produktivitas.survey-kelompok-tani.aktivitas-fungsi', compact('kelompokTani')),
'aktivitas-fungsi' => view('produktivitas.survey-kelompok-tani.aktivitas-fungsi', [
'kelompokTani' => $kelompokTani->loadMissing(['aset', 'bantuan']),
]),
'sosial-konflik' => view('produktivitas.survey-kelompok-tani.sosial-konflik', compact('kelompokTani')),
default => view('produktivitas.survey-kelompok-tani.edit', [
'kelompokTani' => $kelompokTani,
'kelompokTani' => $kelompokTani->loadMissing('pengurus'),
'provinsi' => Provinsi::orderBy('kode', 'asc')->get(),
'komoditas' => Komoditas::where('is_utama', true)->get(),
...$this->profileLocationOptions($kelompokTani),
]),
};
}
@@ -103,8 +204,8 @@ class SurveyKelompokTaniController extends Controller
'aktivitas-fungsi' => $this->updateAktivitasFungsi($request, $kelompokTani),
'kas' => $this->updateKasSimpanPinjam($request, $kelompokTani),
'sosial-konflik' => $this->updateSosialKonflik($request, $kelompokTani),
'status-bantuan' => $this->updateStatusBantuan($request, $kelompokTani),
'penilaian' => $this->updatePenilaian($request, $kelompokTani),
'status-bantuan' => app(BantuanKelompokTaniController::class)->update($request, $kelompokTani),
'penilaian' => redirect($this->editUrl($kelompokTani, 'aktivitas-fungsi') . '#section-status-bantuan'),
default => $this->updateIdentitas($request, $kelompokTani),
};
}
@@ -122,7 +223,7 @@ class SurveyKelompokTaniController extends Controller
private function validateIdentitas(Request $request)
{
return $request->validate([
$validated = $request->validate([
// Data Responden
'nama_responden' => ['required', 'string', 'max:255'],
'jabatan_responden' => ['nullable', 'string', 'max:255'],
@@ -130,7 +231,10 @@ class SurveyKelompokTaniController extends Controller
// Identitas Kelompok Tani
'nama_kelompok' => ['required', 'string', 'max:255'],
'desa_kelurahan_id' => ['required', 'exists:master_desa_kelurahan,id'],
'provinsi_id' => ['bail', 'required', 'integer', 'exists:master_provinsi,id'],
'kabupaten_id' => ['bail', 'required', 'integer', 'exists:master_kabupaten_kota,id'],
'kecamatan_id' => ['bail', 'required', 'integer', 'exists:master_kecamatan,id'],
'desa_kelurahan_id' => ['bail', 'required', 'integer', 'exists:master_desa_kelurahan,id'],
'dusun' => ['nullable', 'string', 'max:255'],
'tahun_berdiri' => ['nullable', 'digits:4', 'integer', 'min:1900', 'max:' . date('Y')],
'jenis_kelompok' => ['required', 'string', 'max:50'],
@@ -138,15 +242,30 @@ class SurveyKelompokTaniController extends Controller
'nama_gapoktan' => ['nullable', 'string', 'max:255'],
'komoditas_id' => ['nullable', 'array'],
'komoditas_id.*' => ['exists:master_komoditas,id'],
...$this->keanggotaanRules(),
], [
'nama_responden.required' => 'Nama responden wajib diisi.',
'nama_kelompok.required' => 'Nama kelompok wajib diisi.',
'provinsi_id.required' => 'Provinsi wajib diisi.',
'kabupaten_id.required' => 'Kabupaten/Kota wajib diisi.',
'kecamatan_id.required' => 'Kecamatan wajib diisi.',
'provinsi_id.integer' => 'Pilihan Provinsi tidak valid.',
'kabupaten_id.integer' => 'Pilihan Kabupaten/Kota tidak valid.',
'kecamatan_id.integer' => 'Pilihan Kecamatan tidak valid.',
'desa_kelurahan_id.integer' => 'Pilihan Desa/Kelurahan tidak valid.',
'provinsi_id.exists' => 'Provinsi tidak ditemukan.',
'kabupaten_id.exists' => 'Kabupaten/Kota tidak ditemukan.',
'kecamatan_id.exists' => 'Kecamatan tidak ditemukan.',
'desa_kelurahan_id.required' => 'Desa/Kelurahan wajib dipilih.',
'desa_kelurahan_id.exists' => 'Desa/Kelurahan tidak ditemukan.',
'jenis_kelompok.required' => 'Jenis kelompok wajib dipilih.',
'jenis_kelompok_lainnya.required_if' => 'Sebutkan jenis kelompok lainnya.',
'jenis_kelompok.required' => 'Terdaftar/Dikenal Sebagai wajib diisi.',
'jenis_kelompok_lainnya.required_if' => 'Sebutkan Jenis Kelompok wajib diisi.',
'tahun_berdiri.digits' => 'Tahun berdiri harus 4 digit.',
]);
unset($validated['provinsi_id'], $validated['kabupaten_id'], $validated['kecamatan_id']);
return $validated;
}
private function updateIdentitas(Request $request, KelompokTani $kelompokTani)
@@ -163,12 +282,12 @@ class SurveyKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
return $this->redirectToSection(route('kelompok-tani.edit', $kelompokTani->id), 'identitas', 'Data kelompok tani berhasil diperbarui.');
return $this->redirectToSection(route('kelompok-tani.edit', $kelompokTani->id), 'identitas', 'Data Profil berhasil disimpan.', 'pengurus');
}
private function updateRingkasanPengurus(Request $request, KelompokTani $kelompokTani)
private function keanggotaanRules(): array
{
$validated = $request->validate([
return [
'jumlah_pengurus' => ['nullable', 'integer', 'min:0'],
'jumlah_pengurus_aktif' => ['nullable', 'integer', 'min:0'],
'jumlah_anggota_terdaftar' => ['nullable', 'integer', 'min:0'],
@@ -179,18 +298,24 @@ class SurveyKelompokTaniController extends Controller
'jumlah_anggota_perempuan' => ['nullable', 'integer', 'min:0'],
'jumlah_anggota_pemuda_laki_laki' => ['nullable', 'integer', 'min:0'],
'jumlah_anggota_pemuda_perempuan' => ['nullable', 'integer', 'min:0'],
]);
];
}
private function updateRingkasanPengurus(Request $request, KelompokTani $kelompokTani)
{
$validated = $request->validate($this->keanggotaanRules());
$kelompokTani->update([
...$validated,
'updated_by' => auth()->id(),
]);
return $this->redirectToSection(route('kelompok-tani.pengurus-anggota.index', $kelompokTani->id), 'ringkasan', 'Ringkasan pengurus & anggota berhasil disimpan.');
return $this->redirectToSection($this->editUrl($kelompokTani), 'identitas', 'Data Profil berhasil disimpan.', 'pengurus');
}
private function updateKelembagaan(Request $request, KelompokTani $kelompokTani)
{
$hasSk = in_array($request->input('status_legalitas'), KelompokTani::STATUS_LEGALITAS_DENGAN_SK, true);
$validated = $request->validate([
// Cakupan Wilayah Kelompok
'cakupan_wilayah' => ['nullable', 'string', 'max:50'],
@@ -198,17 +323,9 @@ class SurveyKelompokTaniController extends Controller
// Status Legalitas Kelompok
'status_legalitas' => ['nullable', 'string', 'max:50'],
'nomor_sk' => ['nullable', 'string', 'max:100'],
'tanggal_tahun_penerbitan_sk' => ['nullable', 'string', 'max:30'],
'nomor_sk' => [Rule::excludeIf(!$hasSk), 'nullable', 'string', 'max:100'],
'tanggal_tahun_penerbitan_sk' => [Rule::excludeIf(!$hasSk), 'nullable', 'string', 'max:30'],
// Kualitas Kepemimpinan
'tingkat_keaktifan_ketua' => ['nullable', 'string', 'max:30'],
'status_pembagian_peran' => ['nullable', 'string', 'max:30'],
'status_dokumentasi_rapat' => ['nullable', 'string', 'max:30'],
// Frekuensi Pertemuan Rutin
'frekuensi_pertemuan' => ['nullable', 'string', 'max:50'],
'tanggal_pertemuan_terakhir' => ['nullable', 'date'],
]);
$kelompokTani->update([
@@ -216,7 +333,7 @@ class SurveyKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
return $this->redirectToSection($this->editUrl($kelompokTani, 'kelembagaan'), 'kelembagaan', 'Data kelembagaan berhasil disimpan.');
return $this->redirectToSection($this->editUrl($kelompokTani, 'kelembagaan'), 'kelembagaan', 'Data Kelembagaan berhasil disimpan.');
}
private function resolveLainnya(?array $selected, ?string $lainnyaText): ?array
@@ -233,6 +350,10 @@ class SurveyKelompokTaniController extends Controller
private function updateAktivitasFungsi(Request $request, KelompokTani $kelompokTani)
{
$validated = $request->validate([
// Frekuensi Pertemuan Rutin
'frekuensi_pertemuan' => ['nullable', 'string', 'max:50'],
'tanggal_pertemuan_terakhir' => ['nullable', 'date'],
// Kegiatan Konkret yang Sudah Berjalan
'kegiatan_terlaksana' => ['nullable', 'array'],
'kegiatan_terlaksana.*' => ['string', 'max:255'],
@@ -270,7 +391,7 @@ class SurveyKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
return $this->redirectToSection($this->editUrl($kelompokTani, 'aktivitas-fungsi'), 'aktivitas-fungsi', 'Data aktivitas & fungsi kelompok berhasil disimpan.');
return $this->redirectToSection($this->editUrl($kelompokTani, 'aktivitas-fungsi'), 'aktivitas-fungsi', 'Data Operasional berhasil disimpan.', 'aset-baku');
}
private function updateKasSimpanPinjam(Request $request, KelompokTani $kelompokTani)
@@ -287,22 +408,28 @@ class SurveyKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
return $this->redirectToSection(route('kelompok-tani.aset-keuangan.index', $kelompokTani->id), 'kas', 'Data kas/simpan-pinjam berhasil disimpan.');
return $this->redirectToSection($this->editUrl($kelompokTani, 'aktivitas-fungsi'), 'kas', 'Data Operasional berhasil disimpan.', 'status-bantuan');
}
private function updateSosialKonflik(Request $request, KelompokTani $kelompokTani)
{
$pernahKonflik = in_array($request->input('konflik_kelompok'), [
'Pernah, sudah selesai', 'Pernah, masih berlanjut/belum selesai',
], true);
$validated = $request->validate([
// Keterlibatan Perempuan
'partisipasi_perempuan' => ['nullable', 'string', 'max:255'],
// Riwayat Konflik Internal Kelompok
'konflik_kelompok' => ['nullable', 'string', 'max:255'],
'topik_konflik' => ['nullable', 'string', 'max:255'],
'topik_konflik' => [Rule::requiredIf($pernahKonflik), 'nullable', 'string', 'max:255'],
'penyelesaian_konflik' => ['nullable', 'string'],
], [
'topik_konflik.required' => 'Jika Pernah, Soal Apa? wajib diisi jika pernah terjadi konflik internal.',
]);
if (!in_array($validated['konflik_kelompok'] ?? null, ['Pernah, sudah selesai', 'Pernah, masih berlanjut/belum selesai'])) {
if (!$pernahKonflik) {
$validated['topik_konflik'] = null;
$validated['penyelesaian_konflik'] = null;
}
@@ -312,35 +439,7 @@ class SurveyKelompokTaniController extends Controller
'updated_by' => auth()->id(),
]);
return $this->redirectToSection($this->editUrl($kelompokTani, 'sosial-konflik'), 'sosial-konflik', 'Data sosial & konflik berhasil disimpan.');
return $this->redirectToSection($this->editUrl($kelompokTani, 'sosial-konflik'), 'sosial-konflik', 'Data Sosial berhasil disimpan.');
}
private function updateStatusBantuan(Request $request, KelompokTani $kelompokTani)
{
$validated = $request->validate([
'pernah_mendapatkan_bantuan' => ['required', 'boolean'],
]);
$kelompokTani->update([
...$validated,
'updated_by' => auth()->id(),
]);
return $this->redirectToSection(route('kelompok-tani.bantuan-penilaian.index', $kelompokTani->id), 'status-bantuan', 'Status akses bantuan berhasil disimpan.');
}
private function updatePenilaian(Request $request, KelompokTani $kelompokTani)
{
$validated = $request->validate([
'potensi_kelompok' => ['nullable', 'string', 'max:50'],
'alasan_penilaian_potensi' => ['nullable', 'string'],
]);
$kelompokTani->update([
...$validated,
'updated_by' => auth()->id(),
]);
return $this->redirectToSection(route('kelompok-tani.bantuan-penilaian.index', $kelompokTani->id), 'penilaian', 'Penilaian potensi kelompok berhasil disimpan.');
}
}