diff --git a/app/Enums/AksesPasar/PraktikFermentasi.php b/app/Enums/AksesPasar/PraktikFermentasi.php new file mode 100644 index 0000000..2e2d0ac --- /dev/null +++ b/app/Enums/AksesPasar/PraktikFermentasi.php @@ -0,0 +1,28 @@ + self::RUTIN_SENDIRI->value, 'label' => 'Ya, rutin — dilakukan sendiri/individual'], + ['value' => self::RUTIN_KELOMPOK->value, 'label' => 'Ya, rutin — bersama kelompok tani/kolektif'], + ['value' => self::PERNAH_SENDIRI->value, 'label' => 'Pernah mencoba — sendiri'], + ['value' => self::PERNAH_KELOMPOK->value, 'label' => 'Pernah mencoba — bersama kelompok'], + ['value' => self::BELUM_PERNAH->value, 'label' => 'Belum pernah'], + ]; + } + + public static function values(): array + { + return array_column(self::cases(), 'value'); + } +} \ No newline at end of file diff --git a/app/Enums/AksesPasar/SaluranTerdahulu.php b/app/Enums/AksesPasar/SaluranTerdahulu.php new file mode 100644 index 0000000..5fa9c35 --- /dev/null +++ b/app/Enums/AksesPasar/SaluranTerdahulu.php @@ -0,0 +1,28 @@ + self::TENGKULAK->value, 'label' => 'Tengkulak–pedagang lokal'], + ['value' => self::KOPERASI->value, 'label' => 'Koperasi'], + ['value' => self::BUMDES->value, 'label' => 'BUMDes'], + ['value' => self::LANGSUNG_PEMBELI->value, 'label' => 'Langsung ke pembeli–eksportir'], + ['value' => self::LAINNYA->value, 'label' => 'Lainnya'], + ]; + } + + public static function values(): array + { + return array_column(self::cases(), 'value'); + } +} \ No newline at end of file diff --git a/app/Enums/AksesPasar/SkorKesadaranPremium.php b/app/Enums/AksesPasar/SkorKesadaranPremium.php new file mode 100644 index 0000000..4d38322 --- /dev/null +++ b/app/Enums/AksesPasar/SkorKesadaranPremium.php @@ -0,0 +1,28 @@ + self::BELUM_PERNAH_DENGAR->value, 'label' => 'Belum pernah dengar'], + ['value' => self::PERNAH_BELUM_PAHAM->value, 'label' => 'Pernah dengar tapi belum paham syarat'], + ['value' => self::PERNAH_SEDIKIT_PAHAM->value, 'label' => 'Pernah dengar & sedikit paham syarat'], + ['value' => self::SANGAT_PAHAM_BELUM_AKSES->value, 'label' => 'Sangat paham syarat tapi belum pernah akses'], + ['value' => self::SUDAH_AKSES_KONSISTEN->value, 'label' => 'Sudah akses & dapat harga premium konsisten'], + ]; + } + + public static function values(): array + { + return array_column(self::cases(), 'value'); + } +} \ No newline at end of file diff --git a/app/Enums/AksesPasar/SkorPengalaman.php b/app/Enums/AksesPasar/SkorPengalaman.php new file mode 100644 index 0000000..c11dbeb --- /dev/null +++ b/app/Enums/AksesPasar/SkorPengalaman.php @@ -0,0 +1,28 @@ + self::BELUM_PERNAH->value, 'label' => 'Belum pernah coba saluran lain'], + ['value' => self::PERNAH_BERHENTI_TIDAK_ADA_AKSES->value, 'label' => 'Pernah, sudah berhenti & tidak ada akses'], + ['value' => self::PERNAH_BERHENTI_MUNGKIN_KEMBALI->value, 'label' => 'Pernah, berhenti tapi masih mungkin kembali'], + ['value' => self::PERNAH_SESEKALI_JUAL->value, 'label' => 'Pernah & sesekali masih jual ke sana'], + ['value' => self::PERNAH_MASIH_AKTIF->value, 'label' => 'Pernah & masih punya akses aktif'], + ]; + } + + public static function values(): array + { + return array_column(self::cases(), 'value'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Web/Konfigurasi/AuthController.php b/app/Http/Controllers/Web/Konfigurasi/AuthController.php index 89ab07a..b746d23 100644 --- a/app/Http/Controllers/Web/Konfigurasi/AuthController.php +++ b/app/Http/Controllers/Web/Konfigurasi/AuthController.php @@ -8,7 +8,6 @@ use App\Models\User; use Illuminate\Support\Str; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; -use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; class AuthController extends Controller diff --git a/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php b/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php index 14c21a1..8eef63e 100644 --- a/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php +++ b/app/Http/Controllers/Web/Produktivitas/AksesPasarController.php @@ -7,51 +7,46 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Str; +use Illuminate\Validation\Rule; use App\Models\Pertanian\Petani; use App\Models\Pertanian\AksesPasar; use App\Models\Pertanian\HargaJualPanen; +use App\Enums\AksesPasar\SkorPengalaman; +use App\Enums\AksesPasar\SaluranTerdahulu; +use App\Enums\AksesPasar\PraktikFermentasi; +use App\Enums\AksesPasar\SkorKesadaranPremium; + class AksesPasarController extends Controller { public function index($petaniId) { - $petani = Petani::findOrFail($petaniId); + $petani = Petani::findOrFail($petaniId); $aksesPasar = AksesPasar::where('petani_id', $petaniId)->first(); $hargaJualPanen = HargaJualPanen::where('petani_id', $petaniId)->get(); - return view('produktivitas.petani.akses-pasar.index', compact('petani', 'aksesPasar', 'hargaJualPanen')); + return view('produktivitas.petani.akses-pasar.index', array_merge( + compact('petani', 'aksesPasar', 'hargaJualPanen'), + $this->aksesPasarOptions() + )); } public function store(Request $request) { - $request->validate([ - 'petani_id' => 'required|exists:petani,id', - ]); + $validated = $this->validateData($request); DB::beginTransaction(); try { - $aksesPasarData = $request->except(['_token', 'harga_jual']); - $aksesPasarData['uid'] = Str::uuid(); + $aksesPasarData = $this->aksesPasarPayload($validated); + $aksesPasarData['uid'] = 'AKP-' . Str::uuid(); $aksesPasarData['created_by'] = Auth::id(); - AksesPasar::create($aksesPasarData); + $aksesPasar = AksesPasar::create($aksesPasarData); if ($request->has('harga_jual')) { - foreach ($request->harga_jual as $harga) { - if (!empty($harga['bentuk_produk'])) { - HargaJualPanen::create([ - 'uid' => Str::uuid(), - 'petani_id' => $request->petani_id, - 'bentuk_produk' => $harga['bentuk_produk'], - 'harga_panen_terakhir' => $harga['harga_panen_terakhir'], - 'harga_tahun_lalu' => $harga['harga_tahun_lalu'], - 'harga_dua_tahun_lalu' => $harga['harga_dua_tahun_lalu'], - 'created_by' => Auth::id(), - ]); - } - } + $this->syncHargaJual($request->petani_id, $validated['harga_jual'] ?? [], Auth::id()); } DB::commit(); @@ -66,36 +61,20 @@ class AksesPasarController extends Controller public function update(Request $request, $id) { - $request->validate([ - 'petani_id' => 'required|exists:petani,id', - ]); + $validated = $this->validateData($request); DB::beginTransaction(); try { $aksesPasar = AksesPasar::findOrFail($id); - $updateData = $request->except(['_token', '_method', 'harga_jual']); + + $updateData = $this->aksesPasarPayload($validated); $updateData['updated_by'] = Auth::id(); $aksesPasar->update($updateData); - HargaJualPanen::where('petani_id', $request->petani_id)->delete(); - if ($request->has('harga_jual')) { - foreach ($request->harga_jual as $harga) { - if (!empty($harga['bentuk_produk'])) { - HargaJualPanen::create([ - 'uid' => Str::uuid(), - 'petani_id' => $request->petani_id, - 'bentuk_produk' => $harga['bentuk_produk'], - 'harga_panen_terakhir' => $harga['harga_panen_terakhir'], - 'harga_tahun_lalu' => $harga['harga_tahun_lalu'], - 'harga_dua_tahun_lalu' => $harga['harga_dua_tahun_lalu'], - 'created_by' => $aksesPasar->created_by, - 'updated_by' => Auth::id(), - ]); - } - } + $this->syncHargaJual($request->petani_id, $validated['harga_jual'] ?? [], $aksesPasar->created_by, Auth::id()); } DB::commit(); @@ -107,4 +86,136 @@ class AksesPasarController extends Controller return redirect()->back()->withErrors(['error' => 'Gagal memperbarui data: ' . $e->getMessage()])->withInput(); } } + + private function aksesPasarOptions(): array + { + return [ + 'skorPengalamanOptions' => SkorPengalaman::options(), + 'saluranTerdahuluOptions' => SaluranTerdahulu::options(), + 'saluranLainnyaValue' => SaluranTerdahulu::LAINNYA->value, + 'praktikFermentasiOptions' => PraktikFermentasi::options(), + 'praktikBelumPernahValue' => PraktikFermentasi::BELUM_PERNAH->value, + 'skorKesadaranPremiumOptions' => SkorKesadaranPremium::options(), + 'skorPengalamanBerhentiValues' => [ + SkorPengalaman::PERNAH_BERHENTI_TIDAK_ADA_AKSES->value, + SkorPengalaman::PERNAH_BERHENTI_MUNGKIN_KEMBALI->value + ] + ]; + } + + private function validateData(Request $request): array + { + $this->normalizeCurrencyInput($request); + + return $request->validate([ + 'petani_id' => ['required', 'exists:petani,id'], + 'skor_pengalaman' => ['nullable', 'integer', Rule::in(SkorPengalaman::values())], + 'alasan_berhenti' => [ + Rule::requiredIf(fn () => in_array((int)$request->input('skor_pengalaman'), [ + SkorPengalaman::PERNAH_BERHENTI_TIDAK_ADA_AKSES->value, + SkorPengalaman::PERNAH_BERHENTI_MUNGKIN_KEMBALI->value + ], true)), + 'nullable', 'string', 'max:255' + ], + + 'saluran_terdahulu' => ['nullable', 'array'], + 'saluran_terdahulu.*' => ['string', Rule::in(SaluranTerdahulu::values())], + 'saluran_terdahulu_lainnya' => [ + Rule::requiredIf(fn () => in_array(SaluranTerdahulu::LAINNYA->value, $request->input('saluran_terdahulu', []), true)), + 'nullable', 'string', 'max:255' + ], + + 'praktik_fermentasi' => ['nullable', 'string', Rule::in(PraktikFermentasi::values())], + 'proses_fermentasi' => [ + Rule::requiredIf(fn () => filled($request->input('praktik_fermentasi')) && $request->input('praktik_fermentasi') !== PraktikFermentasi::BELUM_PERNAH->value), + 'nullable', 'string' + ], + 'model_fermentasi_memungkinkan' => [ + Rule::requiredIf(fn () => filled($request->input('praktik_fermentasi')) && $request->input('praktik_fermentasi') !== PraktikFermentasi::BELUM_PERNAH->value), + 'nullable', 'string' + ], + + 'skor_kesadaran_premium' => ['nullable', 'integer', Rule::in(SkorKesadaranPremium::values())], + 'sumber_info_premium' => ['nullable', 'string', 'max:255'], + + 'harga_jual' => ['nullable', 'array'], + 'harga_jual.*.bentuk_produk' => ['nullable', 'string'], + 'harga_jual.*.harga_panen_terakhir' => ['nullable', 'numeric', 'min:0'], + 'harga_jual.*.harga_tahun_lalu' => ['nullable', 'numeric', 'min:0'], + 'harga_jual.*.harga_dua_tahun_lalu' => ['nullable', 'numeric', 'min:0'], + ]); + } + + private function aksesPasarPayload(array $validated): array + { + $payload = collect($validated)->except(['harga_jual'])->all(); + + if (!in_array((int)($payload['skor_pengalaman'] ?? 0), [ + SkorPengalaman::PERNAH_BERHENTI_TIDAK_ADA_AKSES->value, + SkorPengalaman::PERNAH_BERHENTI_MUNGKIN_KEMBALI->value + ], true)) { + $payload['alasan_berhenti'] = null; + } + + if (!in_array(SaluranTerdahulu::LAINNYA->value, $payload['saluran_terdahulu'] ?? [], true)) { + $payload['saluran_terdahulu_lainnya'] = null; + } + + if (($payload['praktik_fermentasi'] ?? null) === PraktikFermentasi::BELUM_PERNAH->value) { + $payload['proses_fermentasi'] = null; + $payload['model_fermentasi_memungkinkan'] = null; + } + + return $payload; + } + + + private function syncHargaJual($petaniId, array $hargaJualData, $createdBy, $updatedBy = null): void + { + HargaJualPanen::where('petani_id', $petaniId)->delete(); + + foreach ($hargaJualData as $harga) { + if (!empty($harga['bentuk_produk'])) { + HargaJualPanen::create([ + 'uid' => 'HJP-' . Str::uuid(), + 'petani_id' => $petaniId, + 'bentuk_produk' => $harga['bentuk_produk'], + 'harga_panen_terakhir' => $harga['harga_panen_terakhir'] ?? null, + 'harga_tahun_lalu' => $harga['harga_tahun_lalu'] ?? null, + 'harga_dua_tahun_lalu' => $harga['harga_dua_tahun_lalu'] ?? null, + 'created_by' => $createdBy, + 'updated_by' => $updatedBy ?? $createdBy, + ]); + } + } + } + + private function normalizeCurrencyInput(Request $request): void + { + $data = $request->all(); + + if (isset($data['harga_jual']) && is_array($data['harga_jual'])) { + foreach ($data['harga_jual'] as $index => $item) { + if (is_array($item)) { + if (array_key_exists('harga_panen_terakhir', $item)) { + $data['harga_jual'][$index]['harga_panen_terakhir'] = $this->currencyDigits($item['harga_panen_terakhir']); + } + if (array_key_exists('harga_tahun_lalu', $item)) { + $data['harga_jual'][$index]['harga_tahun_lalu'] = $this->currencyDigits($item['harga_tahun_lalu']); + } + if (array_key_exists('harga_dua_tahun_lalu', $item)) { + $data['harga_jual'][$index]['harga_dua_tahun_lalu'] = $this->currencyDigits($item['harga_dua_tahun_lalu']); + } + } + } + } + $request->merge($data); + } + + private function currencyDigits(mixed $value): ?string + { + if (is_null($value) || $value === '') return null; + $digits = preg_replace('/\D/', '', (string) $value); + return $digits === '' ? null : $digits; + } } \ No newline at end of file diff --git a/resources/views/produktivitas/petani/akses-pasar/index.blade.php b/resources/views/produktivitas/petani/akses-pasar/index.blade.php index f4ede0c..12a97a8 100644 --- a/resources/views/produktivitas/petani/akses-pasar/index.blade.php +++ b/resources/views/produktivitas/petani/akses-pasar/index.blade.php @@ -32,17 +32,18 @@
Apakah sudah ada praktik fermentasi atau pengolahan pascapanen yang Ibu/Bapak lakukan?