get(); $totalBobot = $kriteria->sum('bobot'); $isLocked = PeriodeSeleksi::where('status', 'aktif')->exists(); return view('admin.kriteria.index', compact('kriteria', 'totalBobot', 'isLocked')); } /** * Form tambah kriteria baru */ public function create() { if (PeriodeSeleksi::where('status', 'aktif')->exists()) { return redirect()->route('admin.kriteria.index') ->with('error', 'Aksi ditolak: Struktur kriteria dikunci karena terdapat periode seleksi yang sedang AKTIF.'); } $kriteria = Kriteria::orderBy('kode')->get(); $lastKriteria = Kriteria::orderBy('id', 'desc')->first(); $nextCode = 'C1'; if ($lastKriteria) { $num = (int) filter_var($lastKriteria->kode, FILTER_SANITIZE_NUMBER_INT); $nextCode = 'C' . ($num + 1); } return view('admin.kriteria.create', compact('kriteria', 'nextCode')); } /** * Simpan kriteria baru */ public function store(Request $request) { if (PeriodeSeleksi::where('status', 'aktif')->exists()) { return redirect()->route('admin.kriteria.index') ->with('error', 'Aksi ditolak: Struktur kriteria dikunci karena terdapat periode seleksi yang sedang AKTIF.'); } $validated = $request->validate([ 'kode' => 'required|string|max:50|unique:kriteria,kode', 'nama' => 'required|string|max:255', 'jenis' => 'required|in:benefit,cost', 'bobot' => 'required|numeric|min:0|max:1', 'existing_bobot' => 'nullable|array', 'existing_bobot.*' => 'required|numeric|min:0|max:1', 'sub_keterangan' => 'required|array|size:5', 'sub_keterangan.*' => 'required|string|max:255', ], [ 'kode.required' => 'Kode kriteria harus diisi', 'kode.unique' => 'Kode kriteria sudah digunakan', 'nama.required' => 'Nama kriteria harus diisi', 'jenis.required' => 'Jenis kriteria harus dipilih', 'bobot.required' => 'Bobot harus diisi', 'bobot.min' => 'Bobot minimal 0', 'bobot.max' => 'Bobot maksimal 1', 'sub_keterangan.*.required' => 'Keterangan sub-kriteria harus diisi', ]); $newBobot = (float)$validated['bobot']; $existingBobotSum = 0; if (isset($validated['existing_bobot'])) { foreach ($validated['existing_bobot'] as $id => $val) { $existingBobotSum += (float)$val; } } $totalBobot = $newBobot + $existingBobotSum; if (abs($totalBobot - 1.00) > 0.001) { return back() ->withInput() ->with('error', 'Tidak dapat menyimpan kriteria karena total bobot tidak boleh kurang/lebih dari 1.00 (100%). Total saat ini adalah ' . number_format($totalBobot, 2) . '.'); } \Illuminate\Support\Facades\DB::transaction(function() use ($validated) { if (isset($validated['existing_bobot'])) { foreach ($validated['existing_bobot'] as $id => $val) { Kriteria::where('id', $id)->update(['bobot' => $val]); } } $k = Kriteria::create([ 'kode' => strtoupper($validated['kode']), 'nama' => $validated['nama'], 'jenis' => $validated['jenis'], 'bobot' => $validated['bobot'], ]); foreach ($validated['sub_keterangan'] as $nilai => $keterangan) { \App\Models\SubKriteria::create([ 'kriteria_id' => $k->id, 'nilai' => $nilai, 'keterangan' => $keterangan, ]); } }); return redirect()->route('admin.kriteria.index') ->with('success', 'Kriteria baru berhasil ditambahkan dan bobot disesuaikan!'); } /** * Form edit kriteria */ public function edit(Kriteria $kriterium) { if (PeriodeSeleksi::where('status', 'aktif')->exists()) { return redirect()->route('admin.kriteria.index') ->with('error', 'Aksi ditolak: Struktur kriteria dikunci karena terdapat periode seleksi yang sedang AKTIF.'); } return view('admin.kriteria.edit', ['kriteria' => $kriterium]); } /** * Update kriteria */ public function update(Request $request, Kriteria $kriterium) { if (PeriodeSeleksi::where('status', 'aktif')->exists()) { return redirect()->route('admin.kriteria.index') ->with('error', 'Aksi ditolak: Struktur kriteria dikunci karena terdapat periode seleksi yang sedang AKTIF.'); } $validated = $request->validate([ 'nama' => 'required|string|max:255', 'jenis' => 'required|in:benefit,cost', 'bobot' => 'required|numeric|min:0|max:1', 'sub_keterangan' => 'required|array|size:5', 'sub_keterangan.*' => 'required|string|max:255', ], [ 'nama.required' => 'Nama kriteria harus diisi', 'jenis.required' => 'Jenis atribut harus dipilih', 'bobot.required' => 'Bobot harus diisi', 'bobot.min' => 'Bobot minimal 0', 'bobot.max' => 'Bobot maksimal 1', 'sub_keterangan.*.required' => 'Keterangan sub-kriteria harus diisi', ]); \Illuminate\Support\Facades\DB::transaction(function() use ($kriterium, $validated) { $kriterium->update([ 'nama' => $validated['nama'], 'jenis' => $validated['jenis'], 'bobot' => $validated['bobot'], ]); foreach ($validated['sub_keterangan'] as $nilai => $keterangan) { \App\Models\SubKriteria::updateOrCreate( [ 'kriteria_id' => $kriterium->id, 'nilai' => $nilai, ], [ 'keterangan' => $keterangan, ] ); } }); $totalBobot = Kriteria::sum('bobot'); if (abs($totalBobot - 1.00) > 0.001) { return redirect()->route('admin.kriteria.index') ->with('success', 'Kriteria berhasil diperbarui!') ->with('warning', 'Perhatian: Total bobot kriteria saat ini adalah ' . number_format($totalBobot, 2) . '. Silakan sesuaikan bobot seluruh kriteria agar bernilai tepat 1.00 sebelum menghitung SAW.'); } return redirect()->route('admin.kriteria.index') ->with('success', 'Kriteria berhasil diperbarui!'); } /** * Hapus kriteria */ public function destroy(Kriteria $kriterium) { if (PeriodeSeleksi::where('status', 'aktif')->exists()) { return redirect()->route('admin.kriteria.index') ->with('error', 'Aksi ditolak: Struktur kriteria dikunci karena terdapat periode seleksi yang sedang AKTIF.'); } $kriterium->delete(); $totalBobot = Kriteria::sum('bobot'); if (abs($totalBobot - 1.00) > 0.001) { return redirect()->route('admin.kriteria.index') ->with('success', 'Kriteria berhasil dihapus!') ->with('warning', 'Perhatian: Total bobot kriteria saat ini adalah ' . number_format($totalBobot, 2) . '. Silakan sesuaikan bobot kriteria yang tersisa agar bernilai tepat 1.00 sebelum menghitung SAW.'); } return redirect()->route('admin.kriteria.index') ->with('success', 'Kriteria berhasil dihapus!'); } }