MIF_E31222658/app/Http/Controllers/RankingController.php

354 lines
13 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Exports\HasilPerhitunganPdf;
use App\Models\HasilPenilaian;
use App\Models\PengajuanUkt;
use App\Models\Form;
use App\Services\SawCalculationService;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
class RankingController extends Controller
{
public function index(Request $request)
{
$forms = Form::orderBy('tahun', 'desc')
->orderBy('semester', 'desc')
->get();
// Get active form (either from request or first active form)
$activeForm = $request->filled('status_form_id')
? $forms->where('id', $request->status_form_id)->first()
: $forms->where('status', 'Dibuka')->first();
$baseQuery = HasilPenilaian::with(['pengajuan.mahasiswa.user', 'pengajuan.form'])
->whereHas('pengajuan', function ($q) use ($request) {
$q->where('status_validasi', 'valid');
if ($request->filled('status_form_id')) {
$q->where('status_form_id', $request->status_form_id);
}
if ($request->filled('jenis_form')) {
$q->whereHas('form', function ($formQuery) use ($request) {
$formQuery->where('jenis_form', $request->jenis_form);
});
}
})
->orderBy('nilai_preferensi', 'desc');
// Get all results first to determine ranking and quota status
$allResults = $baseQuery->get();
$selectedFormId = $activeForm->id ?? null;
$form = $activeForm;
$quota = $activeForm->kuota ?? 0;
$withinQuotaIds = [];
// Calculate global ranking and quota status for all results
if ($request->filled('status_form_id')) {
$selectedFormId = $request->status_form_id;
$form = Form::find($selectedFormId);
$quota = $form->kuota ?? 0;
// Get rankings for this specific form
$formResults = $allResults->filter(function ($item) use ($selectedFormId) {
return optional($item->pengajuan)->status_form_id == $selectedFormId;
})->sortByDesc('nilai_preferensi')->values();
// Determine which results are within quota
$withinQuotaIds = $formResults->take($quota)->pluck('id')->toArray();
// Add quota status to all results
foreach ($allResults as $result) {
if (optional($result->pengajuan)->status_form_id == $selectedFormId) {
$rank = $formResults->search(function ($item) use ($result) {
return $item->id === $result->id;
}) + 1;
$result->current_rank = $rank;
$result->is_beyond_quota = $rank > $quota && $quota > 0;
}
}
}
// Apply quota filter if requested
if ($request->filled('kuota_filter') && $request->filled('status_form_id')) {
if ($request->kuota_filter == 'available') {
$baseQuery->whereIn('id', $withinQuotaIds);
} elseif ($request->kuota_filter == 'exceeded') {
$baseQuery->whereNotIn('id', $withinQuotaIds)
->whereHas('pengajuan', function($q) use ($selectedFormId) {
$q->where('status_form_id', $selectedFormId);
});
}
}
// Get paginated results
$rankings = $baseQuery->paginate(20);
// Mark which results are beyond quota for display
foreach ($rankings as $ranking) {
if ($selectedFormId && optional($ranking->pengajuan)->status_form_id == $selectedFormId) {
$ranking->is_beyond_quota = !in_array($ranking->id, $withinQuotaIds);
}
}
// Initialize semester reports
$semesterReports = [];
// Group forms by unique semester-year combinations
$uniqueSemesters = $forms->unique(function ($item) {
return $item->semester.$item->tahun;
});
foreach ($uniqueSemesters as $form) {
$key = $form->semester.'_'.$form->tahun;
$semesterReports[$key] = [
'semester' => $form->semester,
'tahun' => $form->tahun,
'forms' => [],
'total_ukt_saat_ini' => 0,
'total_ukt_penyesuaian' => 0,
'total_mahasiswa' => 0,
'kuota_total' => 0,
'kuota_terpakai' => 0,
'total_average' => 0,
'total_selisih' => 0,
'persentase_terpakai' => 0
];
}
// Calculate statistics for each semester
foreach ($semesterReports as $key => &$report) {
$formsInSemester = $forms->where('semester', $report['semester'])
->where('tahun', $report['tahun']);
foreach ($formsInSemester as $form) {
$formResults = $allResults->filter(function ($item) use ($form) {
return optional($item->pengajuan)->form_id == $form->id;
});
$formData = [
'id' => $form->id,
'nama_form' => $form->nama_form,
'jenis_form' => $form->jenis_form,
'ukt_saat_ini' => $formResults->sum(function ($item) {
return optional($item->pengajuan)->ukt_saat_ini ?? 0;
}),
'ukt_penyesuaian' => $formResults->sum(function ($item) {
return $item->ukt_penyesuaian ?? 0;
}),
'jumlah_mahasiswa' => $formResults->count(),
'kuota' => $form->kuota,
'kuota_terpakai' => $formResults->count(),
'average' => 0,
'selisih' => 0
];
// Calculate averages and differences
if ($formData['jumlah_mahasiswa'] > 0) {
$formData['average'] = $formData['ukt_penyesuaian'] / $formData['jumlah_mahasiswa'];
}
$formData['selisih'] = $formData['ukt_saat_ini'] - $formData['ukt_penyesuaian'];
$report['forms'][] = $formData;
// Aggregate semester totals
$report['total_ukt_saat_ini'] += $formData['ukt_saat_ini'];
$report['total_ukt_penyesuaian'] += $formData['ukt_penyesuaian'];
$report['total_mahasiswa'] += $formData['jumlah_mahasiswa'];
$report['kuota_total'] += $formData['kuota'];
$report['kuota_terpakai'] += $formData['kuota_terpakai'];
}
// Calculate semester-level metrics
$report['total_average'] = $report['total_mahasiswa'] > 0
? $report['total_ukt_penyesuaian'] / $report['total_mahasiswa']
: 0;
$report['total_selisih'] = $report['total_ukt_saat_ini'] - $report['total_ukt_penyesuaian'];
$report['persentase_terpakai'] = $report['kuota_total'] > 0
? ($report['kuota_terpakai'] / $report['kuota_total']) * 100
: 0;
}
// Convert associative array to indexed array and sort
$semesterReports = array_values($semesterReports);
// Sort semester reports by year (descending) and semester (Ganjil first)
usort($semesterReports, function ($a, $b) {
if ($a['tahun'] == $b['tahun']) {
return $a['semester'] == 'Ganjil' ? -1 : 1;
}
return $b['tahun'] - $a['tahun'];
});
// Overall statistics
$totalUktSaatIni = $allResults->sum(function($item) {
return optional($item->pengajuan)->ukt_saat_ini ?? 0;
});
$totalUktPenyesuaian = $allResults->sum(function($item) {
return $item->ukt_penyesuaian ?? 0;
});
$averageUktPenyesuaian = $allResults->count() > 0
? $totalUktPenyesuaian / $allResults->count()
: 0;
$selisihUkt = $totalUktSaatIni - $totalUktPenyesuaian;
$countMahasiswa = $allResults->count();
// Budget calculations
$budget = HasilPenilaian::getCurrentBudget();
$budgetDifference = $budget - $totalUktPenyesuaian;
return view('admin.ranking.index', compact(
'rankings',
'forms',
'semesterReports',
'totalUktSaatIni',
'totalUktPenyesuaian',
'averageUktPenyesuaian',
'selisihUkt',
'countMahasiswa',
'budget',
'budgetDifference'
));
}
public function setBudget(Request $request)
{
$request->validate([
'budget' => 'required'
]);
try {
$budget = str_replace('.', '', $request->budget);
HasilPenilaian::updateBudget((int)$budget);
return back()->with('success', 'Budget berhasil disimpan!');
} catch (\Exception $e) {
return back()->with('error', 'Gagal menyimpan budget: '.$e->getMessage());
}
}
public function setActiveBudget(Request $request)
{
$request->validate([
'status_form_id' => 'required|exists:forms,id',
'budget' => 'required'
]);
try {
$budget = str_replace('.', '', $request->budget);
$form = Form::findOrFail($request->status_form_id);
// Update budget in keterangan column for all results of this form
HasilPenilaian::whereHas('pengajuan', function($q) use ($request) {
$q->where('status_form_id', $request->status_form_id);
})->update(['keterangan' => $budget]);
return back()->with('success', 'Budget untuk form aktif berhasil disimpan!');
} catch (\Exception $e) {
return back()->with('error', 'Gagal menyimpan budget: '.$e->getMessage());
}
}
public function export(Request $request)
{
try {
$request->validate([
'status_form_id' => 'required|exists:forms,id'
]);
$form = Form::findOrFail($request->status_form_id);
$rankings = HasilPenilaian::with([
'pengajuan:id,mahasiswa_id,form_id,ukt_saat_ini,status_validasi',
'pengajuan.mahasiswa:id,user_id,nim,program_studi',
'pengajuan.mahasiswa.user:id,name'
])
->whereHas('pengajuan', function($q) use ($request) {
$q->where('status_validasi', 'valid')
->where('status_form_id', $request->status_form_id);
})
->orderBy('nilai_preferensi', 'desc')
->get();
if ($rankings->isEmpty()) {
return back()->with('error', 'Tidak ada data yang dapat diexport untuk form ini');
}
$judul = strtoupper($form->jenis_form) . ' UKT MAHASISWA ' .
$form->semester . ' POLITEKNIK NEGERI JEMBER TAHUN AKADEMIK ' . $form->tahun;
// Debug: Check if view exists
if (!view()->exists('admin.ranking.export')) {
throw new \Exception("View 'admin.ranking.export' not found");
}
$pdf = PDF::loadView('admin.ranking.export', [
'judul' => $judul,
'form' => $form,
'mahasiswa' => $rankings
]);
return $pdf->download('ranking-ukt-' . strtolower($form->jenis_form) . '-' .
$form->semester . '-' . $form->tahun . '.pdf');
} catch (\Exception $e) {
\Log::error('PDF Export Error', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'request' => $request->all()
]);
return back()->with('error', 'Gagal export PDF: ' . $e->getMessage());
}
}
public function recalculateAll(SawCalculationService $sawService)
{
try {
$validIds = PengajuanUkt::where('status_validasi', 'valid')
->pluck('id')
->toArray();
$result = $sawService->processBatch($validIds);
return back()->with([
'status' => $result['status'],
'message' => $result['message']
]);
} catch (\Exception $e) {
return back()->with('error', 'Gagal memproses: '.$e->getMessage());
}
}
public function updateUkt(Request $request, $id)
{
$request->validate([
'ukt_penyesuaian' => 'required'
]);
try {
// Remove formatting and convert to integer
$uktValue = str_replace('.', '', $request->ukt_penyesuaian);
$uktValue = (int)$uktValue;
$ranking = HasilPenilaian::findOrFail($id);
$ranking->update([
'ukt_penyesuaian' => $uktValue,
'status_penyesuaian' => 'sudah dilakukan penyesuaian'
]);
return back()->with('success', 'UKT Penyesuaian berhasil diperbarui!');
} catch (\Exception $e) {
return back()->with('error', 'Gagal memperbarui UKT: '.$e->getMessage());
}
}}