diff --git a/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php b/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php index e74952d..e9a6de9 100644 --- a/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/ProfilPetaniController.php @@ -22,10 +22,13 @@ class ProfilPetaniController extends Controller } $title = 'Dashboard Profil Petani'; - $komoditas = Komoditas::where('is_utama', true)->get(); + $komoditas = Komoditas::select('id', 'nama')->where('is_utama', true)->get(); + $komoditasIds = $komoditas->pluck('id'); - $petani = Petani::pluck('id'); - $lahan = Lahan::whereIn('petani_id', $petani)->get(); + $petaniIds = fn () => Petani::query()->select('id'); + $lahanIds = fn () => Lahan::query() + ->whereIn('petani_id', $petaniIds()) + ->select('id'); $petaniSummary = Petani::select( 'komoditas_id', @@ -38,14 +41,14 @@ class ProfilPetaniController extends Controller DB::raw('COUNT(*) as total'), DB::raw('SUM(luas_lahan) as luas_lahan') ) - ->whereIn('petani_id', $petani) + ->whereIn('petani_id', $petaniIds()) ->groupBy('komoditas_id') ->get(); $tanamanSummary = Tanaman::select( 'komoditas_id', DB::raw('COUNT(*) as total') ) - ->whereIn('lahan_id', $lahan->pluck('id')) + ->whereIn('lahan_id', $lahanIds()) ->groupBy('komoditas_id') ->get(); @@ -59,7 +62,7 @@ class ProfilPetaniController extends Controller END "; $skorSummary = SkorPetani::selectRaw("$case AS segmen, COUNT(*) AS total") - ->whereIn('petani_id', $petani) + ->whereIn('petani_id', $petaniIds()) ->groupByRaw($case) ->get(); @@ -70,15 +73,15 @@ class ProfilPetaniController extends Controller $case AS segmen, COUNT(petani.id) AS total ") - ->whereIn('petani_skor.petani_id', $petani) + ->whereIn('petani_skor.petani_id', $petaniIds()) ->groupBy('petani.komoditas_id') ->groupByRaw($case) ->get(); $skorAverage = SkorPetani::query() ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereIn('petani_id', $petani) - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + ->whereIn('petani_id', $petaniIds()) + ->whereIn('petani.komoditas_id', $komoditasIds) ->avg('skor_kesiapan_adopsi'); if ($skorAverage >= 4.0) { $segmenAverage = 'Penggerak'; @@ -94,8 +97,8 @@ class ProfilPetaniController extends Controller $skorDimensi = SkorPetani::query() ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereIn('petani_id', $petani) - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + ->whereIn('petani_id', $petaniIds()) + ->whereIn('petani.komoditas_id', $komoditasIds) ->selectRaw(" avg(skor_d2_sistem_praktik_budidaya) as skor_d2_sistem_praktik_budidaya, avg(skor_d4_sosial_ekonomi) as skor_d4_sosial_ekonomi, @@ -104,8 +107,8 @@ class ProfilPetaniController extends Controller $skorKomponen = SkorPetani::query() ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereIn('petani_id', $petani) - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + ->whereIn('petani_id', $petaniIds()) + ->whereIn('petani.komoditas_id', $komoditasIds) ->selectRaw("avg(skor_komp_1_d4_k3_motivasi_kapasitas_adopsi) as skor_komp_1_d4_k3_motivasi_kapasitas_adopsi, avg(skor_komp_2_d4_k2_ekonomi_rumah_tangga) as skor_komp_2_d4_k2_ekonomi_rumah_tangga, avg(skor_komp_3_d2_praktik_budidaya_gap) as skor_komp_3_d2_praktik_budidaya_gap, @@ -116,8 +119,8 @@ class ProfilPetaniController extends Controller $skorMultiDimensi = SkorPetani::query() ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereIn('petani_id', $petani) - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + ->whereIn('petani_id', $petaniIds()) + ->whereIn('petani.komoditas_id', $komoditasIds) ->selectRaw("$case AS segmen, avg(skor_kesiapan_adopsi) as skor_kesiapan_adopsi, avg(skor_d2_sistem_praktik_budidaya) as skor_d2_sistem_praktik_budidaya, @@ -128,8 +131,8 @@ class ProfilPetaniController extends Controller $skorMultiKomponen = SkorPetani::query() ->join('petani', 'petani_skor.petani_id', '=', 'petani.id') - ->whereIn('petani_id', $petani) - ->whereIn('petani.komoditas_id', $komoditas->pluck('id')) + ->whereIn('petani_id', $petaniIds()) + ->whereIn('petani.komoditas_id', $komoditasIds) ->selectRaw("$case AS segmen, avg(skor_kesiapan_adopsi) as skor_kesiapan_adopsi, avg(skor_komp_1_d4_k3_motivasi_kapasitas_adopsi) as skor_komp_1_d4_k3_motivasi_kapasitas_adopsi, @@ -141,9 +144,14 @@ class ProfilPetaniController extends Controller ->groupByRaw($case) ->get(); - $petani = Petani::with(['skor']) - ->whereIn('id', $petani) - ->whereIn('komoditas_id', $komoditas->pluck('id')) + $petani = Petani::query() + ->select('id', 'nama', 'jenis_kelamin', 'tanggal_lahir', 'komoditas_id') + ->with([ + 'komoditas:id,nama', + 'skor:id,petani_id,skor_kesiapan_adopsi,skor_d2_sistem_praktik_budidaya,skor_d4_sosial_ekonomi,skor_d6_rantai_nilai_akses_pasar,skor_komp_1_d4_k3_motivasi_kapasitas_adopsi,skor_komp_2_d4_k2_ekonomi_rumah_tangga,skor_komp_3_d2_praktik_budidaya_gap,skor_komp_4_d4_k4_keterlibatan_kelembagaan,skor_komp_5_d4_k5_k6_akses_kebebasan_keuangan,skor_komp_6_d6_k1_k4_k5_rantai_nilai_akses_pasar', + ]) + ->whereIn('komoditas_id', $komoditasIds) + ->orderBy('nama') ->get(); return view('dashboard.petani', compact('title', diff --git a/app/Http/Controllers/Web/Ekosistem/FormBasisDataController.php b/app/Http/Controllers/Web/Ekosistem/FormBasisDataController.php index c2982ec..26c4529 100644 --- a/app/Http/Controllers/Web/Ekosistem/FormBasisDataController.php +++ b/app/Http/Controllers/Web/Ekosistem/FormBasisDataController.php @@ -55,19 +55,7 @@ class FormBasisDataController extends Controller ], 404); } - $validated = $request->validate([ - 'parent_id' => ['nullable', 'exists:ekosistem_basis_data_form,id'], - 'tipe' => ['required', Rule::enum(LayoutForm::class)], - 'column_width' => [ - Rule::requiredIf($request->tipe === LayoutForm::COLUMN->value), - 'nullable', 'integer', 'min:1', 'max:12'], - 'kolom_id' => [ - Rule::requiredIf($request->tipe === LayoutForm::VALUE->value), - 'nullable', 'exists:ekosistem_basis_data_kolom,id'], - 'section_label' => [ - Rule::requiredIf($request->tipe === LayoutForm::SECTION->value), - 'nullable', 'string'], - ]); + $validated = $this->validateFormPayload($request, $tabelId); FormBasisData::create([...$validated, 'tabel_id' => $tabelId, @@ -115,19 +103,7 @@ class FormBasisDataController extends Controller ], 404); } - $validated = $request->validate([ - 'parent_id' => ['nullable', 'exists:ekosistem_basis_data_form,id'], - 'tipe' => ['required', Rule::enum(LayoutForm::class)], - 'column_width' => [ - Rule::requiredIf($request->tipe === LayoutForm::COLUMN->value), - 'nullable', 'integer', 'min:1', 'max:12'], - 'kolom_id' => [ - Rule::requiredIf($request->tipe === LayoutForm::VALUE->value), - 'nullable', 'exists:ekosistem_basis_data_kolom,id'], - 'section_label' => [ - Rule::requiredIf($request->tipe === LayoutForm::SECTION->value), - 'nullable', 'string'], - ]); + $validated = $this->validateFormPayload($request, $tabelId, $form); $form->update([...$validated, 'updated_by' => auth()->user()->id @@ -293,4 +269,88 @@ class FormBasisDataController extends Controller 'message' => 'Formulir basis data berhasil diperbarui.' ], 200); } + + private function validateFormPayload(Request $request, string $tabelId, ?FormBasisData $form = null): array + { + $tipe = $request->input('tipe'); + $needsParent = in_array($tipe, [LayoutForm::COLUMN->value, LayoutForm::VALUE->value], true); + $mustBeRoot = in_array($tipe, [LayoutForm::ROW->value, LayoutForm::SECTION->value, LayoutForm::HR_LINE->value], true); + + $validator = Validator::make($request->all(), [ + 'parent_id' => [ + Rule::requiredIf($needsParent), + Rule::prohibitedIf($mustBeRoot), + 'nullable', + Rule::exists('ekosistem_basis_data_form', 'id') + ->where(fn ($query) => $query + ->where('tabel_id', $tabelId) + ->whereNull('deleted_at')), + ], + 'tipe' => ['required', Rule::enum(LayoutForm::class)], + 'column_width' => [ + Rule::requiredIf($tipe === LayoutForm::COLUMN->value), + 'nullable', 'integer', 'min:1', 'max:12' + ], + 'kolom_id' => [ + Rule::requiredIf($tipe === LayoutForm::VALUE->value), + 'nullable', + Rule::exists('ekosistem_basis_data_kolom', 'id') + ->where(fn ($query) => $query + ->where('tabel_id', $tabelId) + ->whereNull('deleted_at')), + ], + 'section_label' => [ + Rule::requiredIf($tipe === LayoutForm::SECTION->value), + 'nullable', 'string' + ], + ]); + + $validator->after(function ($validator) use ($request, $tabelId, $form) { + if ($validator->errors()->isNotEmpty() || !$request->filled('parent_id')) { + return; + } + + if ($form && (int) $request->input('parent_id') === (int) $form->id) { + $validator->errors()->add('parent_id', 'Induk formulir tidak boleh menunjuk ke dirinya sendiri.'); + return; + } + + $layout = LayoutForm::from($request->input('tipe')); + $expectedParent = match ($layout) { + LayoutForm::COLUMN => LayoutForm::ROW, + LayoutForm::VALUE => LayoutForm::COLUMN, + default => null, + }; + + if (!$expectedParent) { + return; + } + + $parent = FormBasisData::where('tabel_id', $tabelId)->find($request->input('parent_id')); + if (!$parent || $parent->tipe !== $expectedParent) { + $validator->errors()->add('parent_id', 'Induk formulir tidak sesuai dengan tipe formulir.'); + } + }); + + $validated = $validator->validate(); + $layout = LayoutForm::from($validated['tipe']); + + if (in_array($layout, [LayoutForm::ROW, LayoutForm::SECTION, LayoutForm::HR_LINE], true)) { + $validated['parent_id'] = null; + } + + if ($layout !== LayoutForm::COLUMN) { + $validated['column_width'] = null; + } + + if ($layout !== LayoutForm::VALUE) { + $validated['kolom_id'] = null; + } + + if ($layout !== LayoutForm::SECTION) { + $validated['section_label'] = null; + } + + return $validated; + } } diff --git a/app/Models/Ekosistem/FormBasisData.php b/app/Models/Ekosistem/FormBasisData.php index 6f36e7f..6ce1b7e 100644 --- a/app/Models/Ekosistem/FormBasisData.php +++ b/app/Models/Ekosistem/FormBasisData.php @@ -56,7 +56,6 @@ class FormBasisData extends Model public function form(): HasMany { return $this->hasMany(FormBasisData::class, 'parent_id') - ->with('form') ->orderBy('urutan'); }