MIF_E31221225/app/Http/Controllers/Admin/HasilAngketController.php

198 lines
7.5 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Siswa;
use App\Models\PaketMapel;
use App\Models\AngketSiswa;
use App\Models\NilaiTotalMapel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class HasilAngketController extends Controller
{
public function index()
{
$siswas = Siswa::with([
'kelas',
'angket.paketPertama',
'angket.paketKedua',
'angket.paketKetiga',
'angket.paketFinal'
])->paginate(10);
return view('admin.angket.hasil.index', compact('siswas'))->with('info', 'Berikut daftar hasil angket siswa.');
}
public function edit(Siswa $siswa)
{
$paketMapels = PaketMapel::all();
$siswa->load('angket');
if (!$siswa->angket) {
$siswa->angket = new AngketSiswa([
'siswa_id' => $siswa->id,
'nama' => $siswa->nama,
'jenis_kelamin' => $siswa->jenis_kelamin,
'kelas_id' => $siswa->kelas_id
]);
}
return view('admin.angket.hasil.edit', compact('siswa', 'paketMapels'))->with('info', 'Silakan edit hasil pilihan siswa.');
}
public function update(Request $request, Siswa $siswa)
{
$request->validate([
'paket_pertama_id' => 'required|exists:paket_mapel,id',
'paket_kedua_id' => 'nullable|exists:paket_mapel,id',
'paket_ketiga_id' => 'nullable|exists:paket_mapel,id',
'cita_cita' => 'nullable|string|max:255',
'rencana_setelah_lulus' => 'nullable|string|max:255',
'paket_final_id' => 'nullable|exists:paket_mapel,id',
]);
try {
DB::beginTransaction();
$angket = AngketSiswa::updateOrCreate(
['siswa_id' => $siswa->id],
[
'nama' => $siswa->nama,
'jenis_kelamin' => $siswa->jenis_kelamin,
'kelas_id' => $siswa->kelas_id,
'paket_pertama_id' => $request->paket_pertama_id,
'paket_kedua_id' => $request->paket_kedua_id,
'paket_ketiga_id' => $request->paket_ketiga_id,
'cita_cita' => $request->cita_cita ?? '-',
'rencana_setelah_lulus' => $request->rencana_setelah_lulus ?? '-',
'paket_final_id' => $request->has('paket_final_id') ? $request->paket_final_id : $siswa->angket->paket_final_id ?? null,
]
);
DB::commit();
Log::info('Berhasil memperbarui AngketSiswa:', $angket->toArray());
return redirect()->route('admin.hasil.index')->with('success', 'Hasil pemilihan berhasil diperbarui.');
} catch (\Exception $e) {
DB::rollBack();
Log::error('Gagal memperbarui AngketSiswa: ' . $e->getMessage(), [
'siswa_id' => $siswa->id,
'request_data' => $request->all()
]);
return redirect()->back()->withInput()->withErrors('Gagal memperbarui hasil pemilihan: ' . $e->getMessage());
}
}
public function destroy(Siswa $siswa)
{
try {
AngketSiswa::where('siswa_id', $siswa->id)->delete();
return redirect()->route('admin.hasil.index')->with('success', 'Hasil pemilihan berhasil dihapus.');
} catch (\Exception $e) {
Log::error('Gagal menghapus AngketSiswa: ' . $e->getMessage(), ['siswa_id' => $siswa->id]);
return redirect()->back()->withErrors('Gagal menghapus hasil pemilihan: ' . $e->getMessage());
}
}
public function hitung(Request $request)
{
$paketMapels = PaketMapel::all();
$paketKuota = $paketMapels->pluck('kuota', 'id')->toArray();
$paketIsi = array_fill_keys(array_keys($paketKuota), []);
$ranking = NilaiTotalMapel::select('siswa_id', DB::raw('SUM(nilai_total) as total_nilai'))
->groupBy('siswa_id')
->orderByDesc('total_nilai')
->pluck('total_nilai', 'siswa_id')
->toArray();
$angketList = AngketSiswa::with('siswa')
->get()
->sortByDesc(fn($a) => $ranking[$a->siswa_id] ?? 0);
$hasilPilihanSiswa = [];
$siswaTanpaPaket = [];
foreach ($angketList as $angket) {
$siswaId = $angket->siswa_id;
$rankingSiswa = $ranking[$siswaId] ?? 0;
$pilihans = [
$angket->paket_pertama_id,
$angket->paket_kedua_id,
$angket->paket_ketiga_id,
];
$assigned = false;
foreach ($pilihans as $paketId) {
if (!$paketId || !array_key_exists($paketId, $paketKuota)) continue;
$isiSaatIni = $paketIsi[$paketId];
if (count($isiSaatIni) < $paketKuota[$paketId]) {
$paketIsi[$paketId][$siswaId] = $rankingSiswa;
$hasilPilihanSiswa[$siswaId] = $paketId;
$assigned = true;
break;
} else {
$lowest = collect($isiSaatIni)->sort()->keys()->first();
if ($rankingSiswa > $isiSaatIni[$lowest]) {
unset($paketIsi[$paketId][$lowest]);
$paketIsi[$paketId][$siswaId] = $rankingSiswa;
$hasilPilihanSiswa[$siswaId] = $paketId;
$assigned = true;
break;
}
}
}
if (!$assigned) {
$siswaTanpaPaket[] = $siswaId;
}
}
DB::beginTransaction();
try {
foreach ($angketList as $angket) {
$finalPaketId = $hasilPilihanSiswa[$angket->siswa_id] ?? null;
AngketSiswa::where('siswa_id', $angket->siswa_id)->update([
'paket_final_id' => $finalPaketId,
]);
}
DB::commit();
Log::info('Pembaruan alokasi paket final ke database berhasil.');
} catch (\Exception $e) {
DB::rollBack();
Log::error('Gagal memperbarui alokasi paket final: ' . $e->getMessage());
return redirect()->back()->withErrors('Gagal menyimpan hasil perhitungan: ' . $e->getMessage());
}
$finalAssignments = [];
foreach ($paketIsi as $paketId => $assigned) {
$finalAssignments[$paketId] = [
'paket' => $paketMapels->firstWhere('id', $paketId),
'siswas' => collect($assigned)->keys()->map(function ($siswaId) use ($angketList, $ranking) {
$angket = $angketList->firstWhere('siswa_id', $siswaId);
return [
'siswa' => $angket->siswa,
'ranking' => $ranking[$siswaId] ?? 0,
'cita_cita' => $angket->cita_cita,
'rencana_setelah_lulus' => $angket->rencana_setelah_lulus,
];
})->sortByDesc('ranking')->values()->all()
];
}
$unassignedStudents = Siswa::whereIn('id', $siswaTanpaPaket)
->with(['kelas', 'angket.paketPertama', 'angket.paketKedua', 'angket.paketKetiga'])
->get()
->sortByDesc(fn($siswa) => $ranking[$siswa->id] ?? 0);
return view('admin.angket.hasil.hitung', compact('finalAssignments', 'unassignedStudents', 'paketMapels'))
->with('success', 'Perhitungan alokasi paket mata pelajaran telah selesai.');
}
}