diff --git a/app/Enums/KeparahanSerangan.php b/app/Enums/KeparahanSerangan.php index a030eb9..3fb078a 100644 --- a/app/Enums/KeparahanSerangan.php +++ b/app/Enums/KeparahanSerangan.php @@ -11,9 +11,9 @@ enum KeparahanSerangan: string public function label(): string { return match($this) { - self::RINGAN => 'Ringan', - self::SEDANG => 'Sedang', - self::BERAT => 'Berat', + self::RINGAN => 'Ringan, hanya beberapa tanaman', + self::SEDANG => 'Sedang, sebagian tanaman terdampak', + self::BERAT => 'Parah, sebagian besar tanaman terdampak', }; } diff --git a/app/Enums/KondisiTanaman.php b/app/Enums/KondisiTanaman.php index ae73179..4193e4b 100644 --- a/app/Enums/KondisiTanaman.php +++ b/app/Enums/KondisiTanaman.php @@ -13,10 +13,10 @@ enum KondisiTanaman: string public function label(): string { return match($this) { - self::BAIK => 'Baik', - self::SEDANG => 'Sedang', - self::BURUK => 'Buruk', - self::MATI => 'Mati', + self::BAIK => 'Baik, tumbuh lebat, banyak buah', + self::SEDANG => 'Sedang, cukup tumbuh, ada masalah', + self::BURUK => 'Buruk, banyak tanaman tua dan lemah/tidak berbuah', + self::MATI => 'Mati, tanaman telah mati, tidak dapat tumbuh maupun berbuah', }; } diff --git a/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php b/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php index 3c3042e..00886c5 100644 --- a/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php +++ b/app/Http/Controllers/Web/Dashboard/SurveyPetaniController.php @@ -11,6 +11,7 @@ use App\Models\User; use App\Models\Pertanian\Petani; use App\Models\Pertanian\Komoditas; use App\Models\Pertanian\Lahan; +use App\Models\Pertanian\Tanaman; use App\Models\Pertanian\SurveyPelatihan; use App\Models\Pertanian\SurveySertifikasi; @@ -143,24 +144,29 @@ class SurveyPetaniController extends Controller // Ringkasan lahan - $totalLuasLahan = (float) Lahan::query() - ->sum('luas_lahan'); - - $totalJumlahTanaman = (int) Lahan::query() - ->sum('jumlah_tanaman'); + $totalLuasLahan = ((float) Lahan::query() + ->sum('luas_lahan')) / 10000; // Jumlah tanaman berdasarkan komoditas petani - $tanamanPerKomoditasCollection = DB::table("{$lahanTable} as l") + $tanamanTable = (new Tanaman())->getTable(); + + $tanamanPerKomoditasCollection = DB::table("{$tanamanTable} as t") + ->join("{$lahanTable} as l", 'l.id', '=', 't.lahan_id') ->join("{$petaniTable} as p", 'p.id', '=', 'l.petani_id') - ->leftJoin("{$komoditasTable} as k", 'k.id', '=', 'p.komoditas_id') + ->leftJoin("{$komoditasTable} as k", 'k.id', '=', 't.komoditas_id') ->selectRaw("COALESCE(k.nama, 'Belum ditentukan') as label") - ->selectRaw('COALESCE(SUM(l.jumlah_tanaman), 0) as total') + ->selectRaw('COUNT(t.id) as total') ->where('k.is_utama', true) + ->whereNull('t.deleted_at') + ->whereNull('l.deleted_at') + ->whereNull('p.deleted_at') ->groupBy('k.id', 'k.nama') ->orderByDesc('total') ->get(); + $totalJumlahTanaman = (int) $tanamanPerKomoditasCollection->sum('total'); + $tanamanPerKomoditas = $tanamanPerKomoditasCollection ->map(function ($item, $index) use ($colors, $totalJumlahTanaman) { $color = $colors[$index % count($colors)]; diff --git a/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php b/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php index 6556cfd..6c14be4 100644 --- a/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php +++ b/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php @@ -25,9 +25,25 @@ class AksesPasarController extends Controller $aksesPasar = AksesPasar::where('petani_id', $petaniId)->first(); $hargaJualPanen = HargaJualPanen::where('petani_id', $petaniId)->get(); + $hargaJualRows = collect([ + 'Buah segar hasil petik', + 'Biji basah', + 'Biji kering/Biji Kupas', + 'Terfermentasi (Rp/kg)', + ])->map(function (string $bentuk, int $index) use ($hargaJualPanen) { + $existingData = $hargaJualPanen->firstWhere('bentuk_produk', $bentuk); + + return [ + 'index' => $index, + 'bentuk' => $bentuk, + 'harga_panen_terakhir' => $this->currencyForDisplay($existingData?->harga_panen_terakhir), + 'harga_tahun_lalu' => $this->currencyForDisplay($existingData?->harga_tahun_lalu), + 'harga_dua_tahun_lalu' => $this->currencyForDisplay($existingData?->harga_dua_tahun_lalu), + ]; + }); return view('produktivitas.petani.akses-pasar.index', array_merge( - compact('petani', 'aksesPasar', 'hargaJualPanen'), + compact('petani', 'aksesPasar', 'hargaJualPanen', 'hargaJualRows'), $this->aksesPasarOptions() )); } @@ -251,4 +267,11 @@ class AksesPasarController extends Controller $digits = preg_replace('/\D/', '', (string) $value); return $digits === '' ? null : $digits; } -} \ No newline at end of file + + private function currencyForDisplay(mixed $value): string + { + $digits = $this->currencyDigits($value); + + return is_null($digits) ? '' : number_format((int) $digits, 0, ',', '.'); + } +} diff --git a/app/Http/Controllers/Web/Produktivitas/PendidikanPelatihanController.php b/app/Http/Controllers/Web/Produktivitas/PendidikanPelatihanController.php index 18daa53..61515d2 100644 --- a/app/Http/Controllers/Web/Produktivitas/PendidikanPelatihanController.php +++ b/app/Http/Controllers/Web/Produktivitas/PendidikanPelatihanController.php @@ -77,10 +77,11 @@ class PendidikanPelatihanController extends Controller ]); } - return back()->with('success', 'Riwayat pelatihan berhasil disimpan.'); + return $this->redirectBackToFragment($request, 'section-sertifikasi') + ->with('success', 'Riwayat pelatihan berhasil disimpan.'); } - public function destroyPelatihan(Petani $petani, SurveyPelatihan $surveyPelatihan) + public function destroyPelatihan(Request $request, Petani $petani, SurveyPelatihan $surveyPelatihan) { $this->authorizeAccess(); @@ -92,7 +93,8 @@ class PendidikanPelatihanController extends Controller $surveyPelatihan->delete(); - return back()->with('success', 'Riwayat pelatihan berhasil dihapus.'); + return $this->redirectBackToFragment($request, 'section-pelatihan') + ->with('success', 'Riwayat pelatihan berhasil dihapus.'); } public function storeSertifikasi(Request $request, Petani $petani) @@ -155,10 +157,11 @@ class PendidikanPelatihanController extends Controller ]); } - return back()->with('success', 'Sertifikasi berhasil disimpan.'); + return $this->redirectBackToFragment($request, 'section-sertifikasi') + ->with('success', 'Sertifikasi berhasil disimpan.'); } - public function destroySertifikasi(Petani $petani, SurveySertifikasi $surveySertifikasi) + public function destroySertifikasi(Request $request, Petani $petani, SurveySertifikasi $surveySertifikasi) { $this->authorizeAccess(); @@ -170,6 +173,18 @@ class PendidikanPelatihanController extends Controller $surveySertifikasi->delete(); - return back()->with('success', 'Sertifikasi berhasil dihapus.'); + return $this->redirectBackToFragment($request, 'section-sertifikasi') + ->with('success', 'Sertifikasi berhasil dihapus.'); } -} \ No newline at end of file + + private function redirectBackToFragment(Request $request, string $defaultFragment) + { + $fragment = $request->input('redirect_fragment', $defaultFragment); + + if (!is_string($fragment) || !preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) { + $fragment = $defaultFragment; + } + + return redirect()->to(Str::before(url()->previous(), '#') . '#' . $fragment); + } +} diff --git a/app/Http/Controllers/Web/Produktivitas/PetaniController.php b/app/Http/Controllers/Web/Produktivitas/PetaniController.php index 336c77a..04b08a7 100644 --- a/app/Http/Controllers/Web/Produktivitas/PetaniController.php +++ b/app/Http/Controllers/Web/Produktivitas/PetaniController.php @@ -50,14 +50,14 @@ class PetaniController extends Controller $query->where('created_by', auth()->user()->id); } + $summaryPetaniIds = (clone $query)->pluck('id'); $petani = $query->paginate($request->per_page ?? 10); $komoditas = Komoditas::where('is_utama', true)->get(); - $lahan = Lahan::whereIn('petani_id', $petani->pluck('id')) + $lahan = Lahan::whereIn('petani_id', $summaryPetaniIds) ->whereIn('komoditas_id', $komoditas->pluck('id')) ->get(); $tanaman = Tanaman::whereIn('lahan_id', $lahan->pluck('id')) - ->whereIn('lahan_id', $lahan->pluck('id')) ->get(); $case = " @@ -70,7 +70,7 @@ class PetaniController extends Controller END "; $skor = SkorPetani::selectRaw("$case AS segmen, COUNT(*) AS total") - ->whereIn('petani_id', $petani->pluck('id')) + ->whereIn('petani_id', $summaryPetaniIds) ->groupByRaw($case) ->get(); @@ -178,7 +178,7 @@ class PetaniController extends Controller 'created_by' => auth()->id(), 'updated_by' => auth()->id()]); - return redirect()->route('petani.index')->with('success', 'Data petani berhasil ditambahkan.'); + return redirect()->route('petani.edit', $petani->id)->with('success', 'Data petani berhasil ditambahkan.'); } public function show(string $id) @@ -253,7 +253,7 @@ class PetaniController extends Controller $petani->update([...$validatedData, 'updated_by' => auth()->id()]); - return redirect()->route('petani.index')->with('success', 'Data petani berhasil diupdate.'); + return redirect()->route('petani.edit', $petani->id)->with('success', 'Data petani berhasil diupdate.'); } /** diff --git a/app/Http/Controllers/Web/Produktivitas/PetaniLahanController.php b/app/Http/Controllers/Web/Produktivitas/PetaniLahanController.php index 47f08ee..1a20417 100644 --- a/app/Http/Controllers/Web/Produktivitas/PetaniLahanController.php +++ b/app/Http/Controllers/Web/Produktivitas/PetaniLahanController.php @@ -7,6 +7,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Illuminate\Validation\Rules\Enum; @@ -17,6 +18,7 @@ use App\Models\Pertanian\Lahan; use App\Models\Wilayah\DesaKelurahan; use App\Models\Wilayah\Provinsi; use App\Models\Pertanian\Komoditas; +use App\Models\Pertanian\PraktikBudidaya; use App\Models\Pertanian\Tanaman; use App\Models\Master\JenisTanaman; @@ -64,8 +66,46 @@ class PetaniLahanController extends Controller $komoditas = Komoditas::all(); $tanamanPenaung = JenisTanaman::all(); + $autoPestDiseaseData = $this->autoPestDiseaseData($petaniId); + $jenisHamaOtomatis = $autoPestDiseaseData['jenis_hama']; + $jenisPenyakitOtomatis = $autoPestDiseaseData['jenis_penyakit']; - return view('produktivitas.petani.lahan.add', compact('petani', 'lahan', 'provinsi', 'komoditas', 'tanamanPenaung')); + return view('produktivitas.petani.lahan.add', compact('petani', 'lahan', 'provinsi', 'komoditas', 'tanamanPenaung', 'jenisHamaOtomatis', 'jenisPenyakitOtomatis')); + } + + private function autoPestDiseaseData(string|int $petaniId): array + { + $praktikBudidaya = PraktikBudidaya::where('petani_id', $petaniId)->latest()->first(); + + return [ + 'jenis_hama' => $this->normalizeArrayValue($praktikBudidaya?->jenis_hama), + 'jenis_penyakit' => $this->normalizeArrayValue($praktikBudidaya?->jenis_penyakit), + ]; + } + + private function normalizeArrayValue(mixed $value): array + { + if (is_array($value)) { + return array_values(array_filter($value, fn ($item) => filled($item))); + } + + if (is_string($value) && $value !== '') { + $decoded = json_decode($value, true); + + if (is_array($decoded)) { + return array_values(array_filter($decoded, fn ($item) => filled($item))); + } + + return [$value]; + } + + return []; + } + + private function hasPestDiseaseColumns(string $table): bool + { + return Schema::hasColumn($table, 'jenis_hama') + && Schema::hasColumn($table, 'jenis_penyakit'); } private function validateLahan(Request $request) @@ -167,6 +207,14 @@ class PetaniLahanController extends Controller ]); $validated = $this->validateLahan($request); + $autoPestDiseaseData = $this->autoPestDiseaseData($petaniId); + $lahanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Lahan)->getTable()); + $tanamanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Tanaman)->getTable()); + + if ($lahanHasPestDiseaseColumns) { + $validated = array_merge($validated, $autoPestDiseaseData); + } + $komoditas = Komoditas::where('id', $request->komoditas_id)->first(); $lahanCount = Lahan::where('petani_id', $petaniId) ->count(); @@ -196,8 +244,8 @@ class PetaniLahanController extends Controller ); if ($lahan && $lahan->jumlah_tanaman > 0) { - $data = collect(range(1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid) { - return [ + $data = collect(range(1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid, $autoPestDiseaseData, $tanamanHasPestDiseaseColumns) { + $row = [ 'lahan_id' => $lahan->id, 'uid' => 'TNM-' . $lahanUid . '-' . strtoupper(Str::random(10)), 'komoditas_id' => $lahan->komoditas_id, @@ -215,6 +263,13 @@ class PetaniLahanController extends Controller 'created_at' => now(), 'updated_at' => now(), ]; + + if ($tanamanHasPestDiseaseColumns) { + $row['jenis_hama'] = json_encode($autoPestDiseaseData['jenis_hama'] ?? []); + $row['jenis_penyakit'] = json_encode($autoPestDiseaseData['jenis_penyakit'] ?? []); + } + + return $row; }); $data->chunk(500)->each(function ($chunk) { @@ -224,15 +279,15 @@ class PetaniLahanController extends Controller if ($request->ajax()) { return response()->json([ 'success' => true, - 'redirect' => route('petani.lahan-tanaman.index', $petaniId), + 'redirect' => route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id]), 'message' => 'Lahan berhasil ditambahkan.' ]); } - return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil ditambahkan.'); + return redirect()->route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id])->with('success', 'Lahan berhasil ditambahkan.'); } - return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil ditambahkan.'); + return redirect()->route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id])->with('success', 'Lahan berhasil ditambahkan.'); } public function show(string $petaniId, string $id) @@ -269,10 +324,13 @@ class PetaniLahanController extends Controller $komoditas = Komoditas::all(); $tanamanPenaung = JenisTanaman::all(); + $autoPestDiseaseData = $this->autoPestDiseaseData($petaniId); + $jenisHamaOtomatis = $autoPestDiseaseData['jenis_hama']; + $jenisPenyakitOtomatis = $autoPestDiseaseData['jenis_penyakit']; $provinsi = Provinsi::orderBy('kode', 'asc')->get(); - return view('produktivitas.petani.lahan.edit', compact('lahan', 'lahanSelected', 'petani', 'komoditas', 'provinsi', 'tanamanPenaung')); + return view('produktivitas.petani.lahan.edit', compact('lahan', 'lahanSelected', 'petani', 'komoditas', 'provinsi', 'tanamanPenaung', 'jenisHamaOtomatis', 'jenisPenyakitOtomatis')); } public function update(Request $request, string $petaniId, string $id) @@ -290,6 +348,14 @@ class PetaniLahanController extends Controller ->toArray() ]); $validated = $this->validateLahan($request); + $autoPestDiseaseData = $this->autoPestDiseaseData($petaniId); + $lahanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Lahan)->getTable()); + $tanamanHasPestDiseaseColumns = $this->hasPestDiseaseColumns((new Tanaman)->getTable()); + + if ($lahanHasPestDiseaseColumns) { + $validated = array_merge($validated, $autoPestDiseaseData); + } + $komoditas = Komoditas::where('id', $request->komoditas_id)->first(); $tanamanCount = Tanaman::where('lahan_id', $lahan->id)->count(); $lahanCount = Lahan::where('petani_id', $petaniId)->count(); @@ -342,8 +408,8 @@ class PetaniLahanController extends Controller $this->syncTanamanPenaung($request); if ($lahan && $lahan->jumlah_tanaman > $tanamanCount) { - $data = collect(range($tanamanCount + 1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid) { - return [ + $data = collect(range($tanamanCount + 1, $lahan->jumlah_tanaman))->map(function ($i) use ($lahan, $komoditas, $lahanUid, $autoPestDiseaseData, $tanamanHasPestDiseaseColumns) { + $row = [ 'lahan_id' => $lahan->id, 'komoditas_id' => $lahan->komoditas_id, 'jenis_komoditas_id' => $lahan->jenis_komoditas_id, @@ -361,6 +427,13 @@ class PetaniLahanController extends Controller 'created_at' => now(), 'updated_at' => now(), ]; + + if ($tanamanHasPestDiseaseColumns) { + $row['jenis_hama'] = json_encode($autoPestDiseaseData['jenis_hama'] ?? []); + $row['jenis_penyakit'] = json_encode($autoPestDiseaseData['jenis_penyakit'] ?? []); + } + + return $row; }); $data->chunk(500)->each(function ($chunk) { @@ -368,20 +441,42 @@ class PetaniLahanController extends Controller }); } + if ($tanamanHasPestDiseaseColumns) { + $lahan->tanaman()->update([ + 'jenis_hama' => json_encode($autoPestDiseaseData['jenis_hama'] ?? []), + 'jenis_penyakit' => json_encode($autoPestDiseaseData['jenis_penyakit'] ?? []), + 'updated_by' => auth()->id(), + ]); + } + if ($request->ajax()) { return response()->json([ 'success' => true, - 'redirect' => route('petani.lahan-tanaman.index', $petaniId), + 'redirect' => route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id]), 'message' => 'Lahan berhasil diupdate.' ]); } - return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil diperbarui.'); + return redirect()->route('petani.lahan-tanaman.edit', [$petaniId, $lahan->id])->with('success', 'Lahan berhasil diperbarui.'); } - public function destroy(string $id) + public function destroy(string $petaniId, string $id) { - // + if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) { + abort(403); + } + + $lahan = Lahan::findOrFail($id); + $lahan->tanaman()->update([ + 'deleted_by' => auth()->id() + ]); + $lahan->tanaman()->delete(); + $lahan->update([ + 'deleted_by' => auth()->id() + ]); + $lahan->delete(); + + return redirect()->route('petani.lahan-tanaman.index', $petaniId)->with('success', 'Lahan berhasil dihapus.'); } public function summary(string $petaniId) diff --git a/app/Http/Controllers/Web/Produktivitas/PraktikBudidayaController.php b/app/Http/Controllers/Web/Produktivitas/PraktikBudidayaController.php index a58d729..8e9aa16 100644 --- a/app/Http/Controllers/Web/Produktivitas/PraktikBudidayaController.php +++ b/app/Http/Controllers/Web/Produktivitas/PraktikBudidayaController.php @@ -178,8 +178,14 @@ class PraktikBudidayaController extends Controller $teknik_pemangkasan = array_values($teknik_pemangkasan); + if ((int) ($validatedData['frekuensi_pemangkasan_komoditas_utama'] ?? 0) === FrekuensiPemangkasanUtama::TIDAK_PERNAH->value) { + $teknik_pemangkasan = []; + } + $petani = Petani::findOrFail($petaniId); + $pemupukanTidakPernah = (int) ($validatedData['pemberian_pupuk'] ?? 0) === PemberianPupuk::TIDAK_PERNAH->value; + $praktikBudidaya = $petani->praktikBudidaya()->create([ 'petani_id' => $petani->id, 'uid' => 'PB-' . strtoupper(Str::random(10)), @@ -193,12 +199,12 @@ class PraktikBudidayaController extends Controller 'deskripsi_penyerbukan_manual' => $validatedData['alasan_tidak_penyerbukan'] ?? null, 'tingkat_keberhasilan_penyerbukan' => $validatedData['tingkat_keberhasilan_penyerbukan'] ?? null, 'pemberian_pupuk' => $validatedData['pemberian_pupuk'] ?? null, - 'jenis_pupuk' => $validatedData['jenis_pupuk'] ?? null, - 'frekuensi_pemberian_pupuk' => ($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null), - 'estimasi_dosis_pupuk_organik' => $validatedData['estimasi_dosis_pupuk_organik'] ?? null, - 'estimasi_dosis_pupuk_anorganik' => $validatedData['estimasi_dosis_pupuk_anorganik'] ?? null, - 'waktu_pemberian_pupuk' => ($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null), - 'cara_pemberian_pupuk' => ($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null), + 'jenis_pupuk' => $pemupukanTidakPernah ? null : ($validatedData['jenis_pupuk'] ?? null), + 'frekuensi_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null)), + 'estimasi_dosis_pupuk_organik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_organik'] ?? null), + 'estimasi_dosis_pupuk_anorganik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_anorganik'] ?? null), + 'waktu_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null)), + 'cara_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null)), 'created_by' => auth()->id(), 'updated_by' => auth()->id(), ], [ @@ -554,6 +560,12 @@ class PraktikBudidayaController extends Controller } } $teknikPemangkasan = array_values($teknik_pemangkasan); + + if ((int) ($validatedData['frekuensi_pemangkasan_komoditas_utama'] ?? 0) === FrekuensiPemangkasanUtama::TIDAK_PERNAH->value) { + $teknikPemangkasan = []; + } + + $pemupukanTidakPernah = (int) ($validatedData['pemberian_pupuk'] ?? 0) === PemberianPupuk::TIDAK_PERNAH->value; $dataPraktikBudidaya = [ 'tenaga_kerja' => $validatedData['tenaga_kerja'], @@ -566,12 +578,12 @@ class PraktikBudidayaController extends Controller 'deskripsi_penyerbukan_manual' => $validatedData['alasan_tidak_penyerbukan'] ?? null, 'tingkat_keberhasilan_penyerbukan' => $validatedData['tingkat_keberhasilan_penyerbukan'] ?? null, 'pemberian_pupuk' => $validatedData['pemberian_pupuk'] ?? null, - 'jenis_pupuk' => $validatedData['jenis_pupuk'] ?? null, - 'frekuensi_pemberian_pupuk' => ($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null), - 'estimasi_dosis_pupuk_organik' => $validatedData['estimasi_dosis_pupuk_organik'] ?? null, - 'estimasi_dosis_pupuk_anorganik' => $validatedData['estimasi_dosis_pupuk_anorganik'] ?? null, - 'waktu_pemberian_pupuk' => ($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null), - 'cara_pemberian_pupuk' => ($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null), + 'jenis_pupuk' => $pemupukanTidakPernah ? null : ($validatedData['jenis_pupuk'] ?? null), + 'frekuensi_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['frekuensi_pemupukan'] ?? null) === 'Lainnya' ? ($validatedData['frekuensi_pemupukan_lainnya'] ?? null) : ($validatedData['frekuensi_pemupukan'] ?? null)), + 'estimasi_dosis_pupuk_organik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_organik'] ?? null), + 'estimasi_dosis_pupuk_anorganik' => $pemupukanTidakPernah ? null : ($validatedData['estimasi_dosis_pupuk_anorganik'] ?? null), + 'waktu_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['waktu_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['waktu_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['waktu_pemberian_pupuk'] ?? null)), + 'cara_pemberian_pupuk' => $pemupukanTidakPernah ? null : (($validatedData['cara_pemberian_pupuk'] ?? null) === 'Lainnya' ? ($validatedData['cara_pemberian_pupuk_lainnya'] ?? null) : ($validatedData['cara_pemberian_pupuk'] ?? null)), ]; } @@ -675,6 +687,17 @@ class PraktikBudidayaController extends Controller } } - return back()->with('success', 'Data berhasil diperbarui.'); + return $this->redirectBackToFragment($request)->with('success', 'Data berhasil diperbarui.'); + } + + private function redirectBackToFragment(Request $request) + { + $fragment = $request->input('redirect_fragment'); + + if (!is_string($fragment) || !preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) { + return back(); + } + + return redirect()->to(Str::before(url()->previous(), '#') . '#' . $fragment); } } diff --git a/app/Http/Controllers/Web/Produktivitas/SosialEkonomiController.php b/app/Http/Controllers/Web/Produktivitas/SosialEkonomiController.php index 2db7af1..a54498f 100644 --- a/app/Http/Controllers/Web/Produktivitas/SosialEkonomiController.php +++ b/app/Http/Controllers/Web/Produktivitas/SosialEkonomiController.php @@ -154,8 +154,7 @@ class SosialEkonomiController extends Controller }); if (!$request->expectsJson()) { - return redirect() - ->route('petani.sosial-ekonomi.edit', [$sosialEkonomi->petani_id, $sosialEkonomi->id]) + return $this->redirectToEditSection($sosialEkonomi, $request) ->with('success', 'Data sosial ekonomi berhasil disimpan.'); } @@ -206,8 +205,7 @@ class SosialEkonomiController extends Controller }); if (!$request->expectsJson()) { - return redirect() - ->route('petani.sosial-ekonomi.edit', [$sosialEkonomi->petani_id, $sosialEkonomi->id]) + return $this->redirectToEditSection($sosialEkonomi, $request) ->with('success', 'Data sosial ekonomi berhasil diperbarui.'); } @@ -218,6 +216,18 @@ class SosialEkonomiController extends Controller ]); } + private function redirectToEditSection(SosialEkonomi $sosialEkonomi, Request $request): RedirectResponse + { + $url = route('petani.sosial-ekonomi.edit', [$sosialEkonomi->petani_id, $sosialEkonomi->id]); + $fragment = $request->input('redirect_fragment'); + + if (is_string($fragment) && preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) { + $url .= '#' . $fragment; + } + + return redirect()->to($url); + } + public function destroy(string $id): JsonResponse { $sosialEkonomi = SosialEkonomi::findOrFail($id); @@ -589,6 +599,14 @@ class SosialEkonomiController extends Controller $payload = $this->normalizeSkorPayload($payload); + if (array_key_exists('ada_sengketa', $payload) && !filter_var($payload['ada_sengketa'], FILTER_VALIDATE_BOOLEAN)) { + $payload['keterangan_sengketa'] = null; + $payload['pihak_membantu_konflik'] = null; + $payload['pihak_membantu_konflik_nama'] = null; + $payload['tahun_bantuan_konflik'] = null; + $payload['status_konflik'] = null; + } + if (($payload['pihak_membantu_konflik'] ?? null) === PihakMembantuKonflik::TIDAK_ADA_SELESAIKAN_SENDIRI->value) { $payload['pihak_membantu_konflik_nama'] = null; $payload['tahun_bantuan_konflik'] = null; diff --git a/app/Http/Controllers/Web/Produktivitas/SurveyProduktivitasController.php b/app/Http/Controllers/Web/Produktivitas/SurveyProduktivitasController.php index 037a638..3c15d3a 100644 --- a/app/Http/Controllers/Web/Produktivitas/SurveyProduktivitasController.php +++ b/app/Http/Controllers/Web/Produktivitas/SurveyProduktivitasController.php @@ -32,10 +32,10 @@ class SurveyProduktivitasController extends Controller ]); } - return back()->with('success', 'Data produktivitas berhasil disimpan.'); + return $this->redirectBackToFragment($request)->with('success', 'Data produktivitas berhasil disimpan.'); } - public function destroy($petaniId, $surveyProduktivitasId) + public function destroy($petaniId, $surveyProduktivitasId, Request $request) { $surveyProduktivitas = SurveyProduktivitas::where('petani_id', $petaniId) ->where('id', $surveyProduktivitasId) @@ -44,6 +44,17 @@ class SurveyProduktivitasController extends Controller $surveyProduktivitas->save(); $surveyProduktivitas->delete(); - return back()->with('success', 'Data produktivitas berhasil dihapus.'); + return $this->redirectBackToFragment($request)->with('success', 'Data produktivitas berhasil dihapus.'); + } + + private function redirectBackToFragment(Request $request) + { + $fragment = $request->input('redirect_fragment'); + + if (!is_string($fragment) || !preg_match('/^[A-Za-z0-9_-]+$/', $fragment)) { + return back(); + } + + return redirect()->to(Str::before(url()->previous(), '#') . '#' . $fragment); } } diff --git a/app/Models/Pertanian/Lahan.php b/app/Models/Pertanian/Lahan.php index c8c57de..8021c23 100644 --- a/app/Models/Pertanian/Lahan.php +++ b/app/Models/Pertanian/Lahan.php @@ -56,7 +56,10 @@ class Lahan extends Model 'komoditas_lain', 'tanaman_penaung', - 'foto' + 'foto', + + 'jenis_hama', + 'jenis_penyakit', ]; protected $casts = [ @@ -68,7 +71,9 @@ class Lahan extends Model 'serangan_hama' => SeranganHama::class, 'penyakit_tanaman' => PenyakitTanaman::class, 'keparahan_serangan' => KeparahanSerangan::class, - 'foto' => 'array' + 'foto' => 'array', + 'jenis_hama' => 'array', + 'jenis_penyakit' => 'array' ]; public function profile(): BelongsTo diff --git a/app/Models/Pertanian/PraktikBudidaya.php b/app/Models/Pertanian/PraktikBudidaya.php index 0a3782c..bc466c7 100644 --- a/app/Models/Pertanian/PraktikBudidaya.php +++ b/app/Models/Pertanian/PraktikBudidaya.php @@ -8,10 +8,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; use App\Models\Pertanian\Petani; use App\Models\Pertanian\SkorPetani; +use App\Models\Pertanian\Tanaman; +use App\Models\Pertanian\Lahan; class PraktikBudidaya extends Model { @@ -95,6 +98,31 @@ class PraktikBudidaya extends Model $kebiasaan = $praktikBudidaya->kebiasaan_konservasi_tanah ? count($praktikBudidaya->kebiasaan_konservasi_tanah) : 0; $pemahaman = $praktikBudidaya->pemahaman_manfaat_konservasi_tanah == 'Ya, tahu manfaatnya' ? 1 : 0; $skor_konservasi_tanah = 0; + $jenisHama = $praktikBudidaya->jenis_hama ?? []; + $jenisPenyakit = $praktikBudidaya->jenis_penyakit ?? []; + + if (Schema::hasColumn((new Lahan)->getTable(), 'jenis_hama') + && Schema::hasColumn((new Lahan)->getTable(), 'jenis_penyakit')) { + Lahan::where('petani_id', $praktikBudidaya->petani_id)->get()->each(function (Lahan $lahan) use ($jenisHama, $jenisPenyakit, $praktikBudidaya) { + $lahan->update([ + 'jenis_hama' => $jenisHama, + 'jenis_penyakit' => $jenisPenyakit, + 'updated_by' => $praktikBudidaya->updated_by, + ]); + }); + } + + if (Schema::hasColumn((new Tanaman)->getTable(), 'jenis_hama') + && Schema::hasColumn((new Tanaman)->getTable(), 'jenis_penyakit')) { + Tanaman::where('petani_id', $praktikBudidaya->petani_id)->get()->each(function (Tanaman $tanaman) use ($jenisHama, $jenisPenyakit, $praktikBudidaya) { + $tanaman->update([ + 'jenis_hama' => $jenisHama, + 'jenis_penyakit' => $jenisPenyakit, + 'updated_by' => $praktikBudidaya->updated_by, + ]); + }); + } + if ($kebiasaan == 0) { $skor_konservasi_tanah = 1; } elseif ($kebiasaan == 1 && $pemahaman == 0) { @@ -122,4 +150,4 @@ class PraktikBudidaya extends Model { return $this->belongsTo(Petani::class, 'petani_id'); } -} \ No newline at end of file +} diff --git a/app/Models/Pertanian/Tanaman.php b/app/Models/Pertanian/Tanaman.php index e31a616..72febdf 100644 --- a/app/Models/Pertanian/Tanaman.php +++ b/app/Models/Pertanian/Tanaman.php @@ -42,6 +42,9 @@ class Tanaman extends Model 'serangan_hama', 'penyakit_tanaman', 'keparahan_serangan', + + 'jenis_hama', + 'jenis_penyakit', ]; protected $casts = [ @@ -49,6 +52,8 @@ class Tanaman extends Model 'serangan_hama' => SeranganHama::class, 'penyakit_tanaman' => PenyakitTanaman::class, 'keparahan_serangan' => KeparahanSerangan::class, + 'jenis_hama' => 'array', + 'jenis_penyakit' => 'array' ]; public function komoditas() diff --git a/database/migrations/2026_07_22_110145_update_lahan_tanaman_table.php b/database/migrations/2026_07_22_110145_update_lahan_tanaman_table.php new file mode 100644 index 0000000..6fde87c --- /dev/null +++ b/database/migrations/2026_07_22_110145_update_lahan_tanaman_table.php @@ -0,0 +1,57 @@ +jsonb('jenis_hama')->nullable(); + } + + if (! Schema::hasColumn('map_lahan', 'jenis_penyakit')) { + $table->jsonb('jenis_penyakit')->nullable(); + } + }); + + Schema::table('map_tanaman', function (Blueprint $table) { + if (! Schema::hasColumn('map_tanaman', 'jenis_hama')) { + $table->jsonb('jenis_hama')->nullable(); + } + + if (! Schema::hasColumn('map_tanaman', 'jenis_penyakit')) { + $table->jsonb('jenis_penyakit')->nullable(); + } + }); + } + + public function down(): void + { + Schema::table('map_lahan', function (Blueprint $table) { + if (Schema::hasColumn('map_lahan', 'jenis_hama')) { + $table->dropColumn('jenis_hama'); + } + + if (Schema::hasColumn('map_lahan', 'jenis_penyakit')) { + $table->dropColumn('jenis_penyakit'); + } + }); + + Schema::table('map_tanaman', function (Blueprint $table) { + if (Schema::hasColumn('map_tanaman', 'jenis_hama')) { + $table->dropColumn('jenis_hama'); + } + + if (Schema::hasColumn('map_tanaman', 'jenis_penyakit')) { + $table->dropColumn('jenis_penyakit'); + } + }); + } +}; diff --git a/resources/views/dashboard/petani.blade.php b/resources/views/dashboard/petani.blade.php index d214106..ec98bc2 100644 --- a/resources/views/dashboard/petani.blade.php +++ b/resources/views/dashboard/petani.blade.php @@ -31,7 +31,7 @@ -
Lahan
@@ -701,4 +701,4 @@ radarKomponen.render(); }); -@endpush \ No newline at end of file +@endpush diff --git a/resources/views/konfigurasi/profile/index.blade.php b/resources/views/konfigurasi/profile/index.blade.php index 8fd820d..a099cde 100644 --- a/resources/views/konfigurasi/profile/index.blade.php +++ b/resources/views/konfigurasi/profile/index.blade.php @@ -88,12 +88,13 @@ @if($profile) @endif diff --git a/resources/views/produktivitas/petani/akses-pasar/index.blade.php b/resources/views/produktivitas/petani/akses-pasar/index.blade.php index 12a97a8..9894264 100644 --- a/resources/views/produktivitas/petani/akses-pasar/index.blade.php +++ b/resources/views/produktivitas/petani/akses-pasar/index.blade.php @@ -93,34 +93,30 @@
- @php($listBentukProduk = ['Buah segar hasil petik', 'Biji basah', 'Biji kering/Biji Kupas', 'Terfermentasi (Rp/kg)']) - @php($hargaJualPanen = $hargaJualPanen ?? collect()) - - @foreach ($listBentukProduk as $index => $bentuk) - @php($existingData = $hargaJualPanen->firstWhere('bentuk_produk', $bentuk)) + @foreach ($hargaJualRows as $row)Lahan & Tanaman