354 lines
13 KiB
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());
|
|
}
|
|
}} |