MIF_E31231754/app/Http/Controllers/Admin/KriteriaController.php

210 lines
7.9 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Kriteria;
use App\Models\PeriodeSeleksi;
use Illuminate\Http\Request;
class KriteriaController extends Controller
{
/**
* Tampilkan daftar kriteria
*/
public function index()
{
$kriteria = Kriteria::orderBy('kode')->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!');
}
}