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

279 lines
9.6 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\PenilaianWarga;
use App\Models\Warga;
use App\Models\PeriodeSeleksi;
use App\Models\Kriteria;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Exports\PenilaianWargaExport;
use App\Imports\PenilaianWargaImport;
use Maatwebsite\Excel\Facades\Excel;
class PenilaianWargaController extends Controller
{
public function export($periode_id)
{
$periode = PeriodeSeleksi::findOrFail($periode_id);
$hasData = PenilaianWarga::where('periode_id', $periode_id)->exists();
if (!$hasData) {
return back()->with('error', 'Gagal: Belum ada data penilaian warga yang diinput pada periode ' . $periode->nama . '.');
}
return Excel::download(new PenilaianWargaExport($periode_id), 'Penilaian-Warga-'.$periode->nama.'.xlsx');
}
public function import(Request $request)
{
$request->validate([
'file' => 'required|mimes:xlsx,xls|max:5120',
], [
'file.required' => 'File Excel harus diunggah.',
'file.mimes' => 'File harus berformat .xlsx atau .xls.',
'file.max' => 'Ukuran file maksimal 5MB.',
]);
$periodeAktif = PeriodeSeleksi::where('status', 'aktif')->first();
if (!$periodeAktif) {
return back()->with('error', 'Gagal: Tidak ada periode aktif. Silakan buat periode terlebih dahulu.');
}
try {
Excel::import(new PenilaianWargaImport($periodeAktif->id), $request->file('file'));
return redirect()->route('admin.penilaian.index')
->with('success', 'Data penilaian berhasil diimpor dari file Excel.');
} catch (\Exception $e) {
return back()->with('error', 'Gagal mengimpor data: ' . $e->getMessage());
}
}
public function index()
{
// Ambil periode aktif
$periodeAktif = PeriodeSeleksi::where('status', 'aktif')->first();
if (!$periodeAktif) {
return redirect()->route('admin.periode.index')
->with('warning', 'Tidak ada periode aktif. Silakan buat periode terlebih dahulu.');
}
// Ambil data warga yang sudah dinilai di periode aktif
$wargaDinilai = DB::table('penilaian_warga')
->select('warga_id')
->where('periode_id', $periodeAktif->id)
->distinct()
->get()
->pluck('warga_id');
// Gunakan relasi 'penilaian' sesuai dengan yang ada di Model Warga
$warga = Warga::with(['wilayah', 'penilaian' => function ($q) use ($periodeAktif) {
$q->where('periode_id', $periodeAktif->id);
}])
->whereIn('id', $wargaDinilai)
->orderBy('nama')
->get();
return view('admin.penilaian.index', compact('warga', 'periodeAktif'));
}
public function create()
{
$warga = Warga::where('is_aktif', true)
->with('wilayah')
->orderBy('nama')
->get();
$periodeAktif = PeriodeSeleksi::where('status', 'aktif')->first();
if (!$periodeAktif) {
return redirect()->route('admin.periode.index')
->with('warning', 'Tidak ada periode aktif. Silakan buat periode terlebih dahulu.');
}
$kriteria = Kriteria::with('subKriteria')->orderBy('kode')->get();
return view('admin.penilaian.create', compact('warga', 'periodeAktif', 'kriteria'));
}
public function store(Request $request)
{
$request->validate([
'warga_id' => 'required|exists:warga,id',
'periode_id' => 'required|exists:periode_seleksi,id',
'nilai.*' => 'required|integer|min:1|max:5',
], [
'warga_id.required' => 'Warga harus dipilih',
'periode_id.required' => 'Periode harus dipilih',
'nilai.*.required' => 'Semua kriteria harus diisi',
'nilai.*.integer' => 'Nilai harus berupa angka',
'nilai.*.min' => 'Nilai minimal 1',
'nilai.*.max' => 'Nilai maksimal 5',
]);
// Cek apakah warga sudah dinilai di periode ini
$exists = PenilaianWarga::where('warga_id', $request->warga_id)
->where('periode_id', $request->periode_id)
->exists();
if ($exists) {
return back()->with('error', 'Warga ini sudah dinilai pada periode tersebut.')
->withInput();
}
DB::beginTransaction();
try {
// Simpan penilaian untuk setiap kriteria
$kriteria = Kriteria::orderBy('kode')->get();
foreach ($kriteria as $k) {
if (isset($request->nilai[$k->id])) {
PenilaianWarga::create([
'warga_id' => $request->warga_id,
'periode_id' => $request->periode_id,
'kriteria_id' => $k->id,
'nilai' => $request->nilai[$k->id],
]);
}
}
DB::commit();
return redirect()->route('admin.penilaian.index')
->with('success', 'Penilaian berhasil disimpan.');
} catch (\Exception $e) {
DB::rollBack();
return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage())
->withInput();
}
}
public function show(Request $request, $id)
{
$periodeId = $request->get('periode_id');
$periodeAktif = $periodeId
? PeriodeSeleksi::find($periodeId)
: PeriodeSeleksi::where('status', 'aktif')->first();
if (!$periodeAktif) {
return redirect()->route('admin.periode.index')
->with('warning', 'Tidak ada periode aktif atau periode yang dipilih.');
}
$warga = Warga::with('wilayah')->findOrFail($id);
// Gunakan relasi 'penilaian' dengan eager load kriteria
$penilaian = PenilaianWarga::with('kriteria')
->where('warga_id', $id)
->where('periode_id', $periodeAktif->id)
->get();
$kriteria = Kriteria::with('subKriteria')->orderBy('kode')->get();
return view('admin.penilaian.show', compact('warga', 'penilaian', 'periodeAktif', 'kriteria'));
}
public function edit(Request $request, $id)
{
$periodeId = $request->get('periode_id');
$periodeAktif = $periodeId
? PeriodeSeleksi::find($periodeId)
: PeriodeSeleksi::where('status', 'aktif')->first();
if (!$periodeAktif) {
return redirect()->route('admin.periode.index')
->with('warning', 'Tidak ada periode aktif atau periode yang dipilih.');
}
$warga = Warga::with('wilayah')->findOrFail($id);
$penilaian = PenilaianWarga::where('warga_id', $id)
->where('periode_id', $periodeAktif->id)
->get()
->keyBy('kriteria_id');
$kriteria = Kriteria::with('subKriteria')->orderBy('kode')->get();
return view('admin.penilaian.edit', compact('warga', 'penilaian', 'periodeAktif', 'kriteria'));
}
public function update(Request $request, $id)
{
$request->validate([
'nilai.*' => 'required|integer|min:1|max:5',
'periode_id' => 'required|exists:periode_seleksi,id',
], [
'nilai.*.required' => 'Semua kriteria harus diisi',
'nilai.*.integer' => 'Nilai harus berupa angka',
'nilai.*.min' => 'Nilai minimal 1',
'nilai.*.max' => 'Nilai maksimal 5',
]);
// ✅ BUG #6 FIX: Gunakan periode_id dari form, bukan periodeAktif
// Ini mencegah data tersimpan ke periode yang salah
$periodeId = $request->periode_id;
DB::beginTransaction();
try {
$kriteria = Kriteria::orderBy('kode')->get();
foreach ($kriteria as $k) {
if (isset($request->nilai[$k->id])) {
PenilaianWarga::updateOrCreate(
[
'warga_id' => $id,
'periode_id' => $periodeId,
'kriteria_id' => $k->id,
],
[
'nilai' => $request->nilai[$k->id],
]
);
}
}
DB::commit();
return redirect()->route('admin.penilaian.index')
->with('success', 'Penilaian berhasil diperbarui.');
} catch (\Exception $e) {
DB::rollBack();
return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage())
->withInput();
}
}
public function destroy($id)
{
$periodeAktif = PeriodeSeleksi::where('status', 'aktif')->first();
// ✅ BUG #3 FIX: Null-safety — jika tidak ada periode aktif, redirect dengan pesan
if (!$periodeAktif) {
return redirect()->route('admin.periode.index')
->with('warning', 'Tidak ada periode aktif. Tidak dapat menghapus penilaian.');
}
DB::beginTransaction();
try {
PenilaianWarga::where('warga_id', $id)
->where('periode_id', $periodeAktif->id)
->delete();
DB::commit();
return redirect()->route('admin.penilaian.index')
->with('success', 'Penilaian berhasil dihapus.');
} catch (\Exception $e) {
DB::rollBack();
return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
}
}
}