MIF_E31222658/app/Http/Controllers/PengajuanController.php

358 lines
14 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\PengajuanUkt;
use App\Models\Kriteria;
use App\Models\SubKriteria;
use App\Models\PengajuanDetail;
use App\Models\Penilaian;
use App\Models\Form;
use App\Models\Mahasiswa;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use App\Notifications\PengajuanDitolakNotification;
use App\Notifications\PengajuanDiterimaNotification;
use Illuminate\Support\Str;
class PengajuanController extends Controller
{
public function index()
{
// Get active forms
$formPenurunan = Form::where('jenis_form', 'penurunan')
->where('status', 'Dibuka')
->first();
$formPengangsuran = Form::where('jenis_form', 'pengangsuran')
->where('status', 'Dibuka')
->first();
$pengajuan = PengajuanUkt::with(['hasilPenilaian', 'dokumen', 'mahasiswa'])
->where('mahasiswa_id', Auth::id())
->latest()
->paginate(10);
$stats = $this->getPengajuanStats(Auth::id());
return view('mahasiswa.dashboard', compact(
'formPenurunan',
'formPengangsuran',
'pengajuan',
'stats'
));
}
public function create($jenis)
{
if (!in_array($jenis, ['penurunan', 'pengangsuran'])) {
abort(404);
}
$formSetting = Form::where('jenis_form', $jenis)
->where('status', 'Dibuka')
->first();
if (!$formSetting) {
return redirect()->route('pengajuan.index')
->with('error', 'Form pengajuan '.$jenis.' UKT saat ini tidak tersedia');
}
// Cek apakah mahasiswa sudah melakukan pengajuan jenis apapun (penurunan/pengangsuran) di semester ini
$existingSubmission = PengajuanUkt::where('mahasiswa_id', Auth::id())
->whereHas('form', function($query) use ($formSetting) {
$query->where('semester', $formSetting->semester)
->where('tahun', $formSetting->tahun);
})
->first();
// Hanya izinkan buat ulang jika status sebelumnya 'tidak valid'
if ($existingSubmission && $existingSubmission->status_validasi !== 'tidak valid') {
$message = match($existingSubmission->status_validasi) {
'menunggu' => 'Anda sudah mengajukan '.$existingSubmission->jenis_pengajuan.' UKT untuk semester '.$formSetting->semester.' '.$formSetting->tahun.' dan masih dalam proses verifikasi',
'valid' => 'Pengajuan '.$existingSubmission->jenis_pengajuan.' UKT Anda untuk semester '.$formSetting->semester.' '.$formSetting->tahun.' sudah divalidasi',
default => 'Anda tidak dapat mengajukan form ini'
};
return redirect()->route('pengajuan.index')->with('error', $message);
}
$kriteria = Kriteria::with('subKriteria')->get();
$mahasiswa = Auth::user()->mahasiswa;
return view('form.'.$jenis, compact('jenis', 'kriteria', 'mahasiswa', 'formSetting'));
}
public function store(Request $request, $jenis)
{
if (!in_array($jenis, ['penurunan', 'pengangsuran'])) {
abort(404);
}
$user = Auth::user();
if (!$user->mahasiswa) {
return back()->with('error', 'Anda tidak terdaftar sebagai mahasiswa.');
}
$mahasiswa = $user->mahasiswa;
$form = Form::where('jenis_form', $jenis)
->where('status', 'Dibuka')
->firstOrFail();
$existingSubmission = PengajuanUkt::where('mahasiswa_id', $mahasiswa->user_id)
->whereHas('form', function($query) use ($form) {
$query->where('semester', $form->semester)
->where('tahun', $form->tahun);
})
->whereIn('status_validasi', ['menunggu', 'valid'])
->first();
if ($existingSubmission && $existingSubmission->status_validasi !== 'tidak valid') {
return back()->with('error', 'Anda sudah pernah mengajukan '.$existingSubmission->jenis_pengajuan.' UKT untuk semester '.$form->semester.' '.$form->tahun.'. Anda hanya bisa mengajukan satu form per semester.');
}
$validated = $request->validate([
'ukt_saat_ini' => 'required|numeric|min:500000',
'alasan_pengajuan' => 'required|string|min:20|max:500',
'penghasilan' => 'required|in:< 2 juta,2 - 3 juta,3 - 4 juta,> 5 juta',
'file_penghasilan' => 'required|mimes:pdf|max:1536',
'pekerjaan' => 'required|in:Bekerja Tetap,Bekerja Tidak Tetap,Tidak Bekerja',
'file_pekerjaan' => 'required|mimes:pdf|max:1536',
'tanggungan' => 'required|in:1 Orang,2 - 4 Orang,> 4 Orang',
'file_tanggungan' => 'required|mimes:pdf|max:1536',
'status_ortu' => 'required|in:Lengkap,Cerai/Yatim/Piatu,Yatim Piatu',
'file_status_ortu' => 'required|mimes:pdf|max:1536',
'hunian' => 'required|in:Milik Sendiri,Sewa/Kontrak,Menumpang',
'file_hunian' => 'required|mimes:pdf|max:1536',
'kendaraan' => 'required|in:Tidak Punya,Motor,Mobil,Motor dan Mobil',
'file_kendaraan' => ($request->kendaraan !== 'Tidak Punya' ? 'required|' : '') . 'mimes:pdf|max:1536',
'semester' => 'required|in:1,2,3,4,5,>6',
'ipk' => 'required|in:< 2.75,2.75 - 3.00,3.00 - 3.50,> 3.50',
'file_khs' => 'required|file|mimes:pdf|max:1536',
'file_ukt' => 'required|mimes:pdf|max:1536',
'file_pendukung' => 'nullable|mimes:pdf|max:1536'
], [
'ukt_saat_ini.required' => 'Nominal UKT saat ini wajib diisi',
'file_ukt' => 'required|mimes:pdf|max:1536',
'required' => 'Field :attribute wajib diisi',
'file_khs.required' => 'File bukti khs wajib diupload',
'in' => 'Pilihan :attribute tidak valid',
'mimes' => 'File harus berupa PDF',
'max' => 'Ukuran file maksimal 1.5MB',
'alasan_pengajuan.required' => 'Harap jelaskan alasan pengajuan Anda',
]);
DB::beginTransaction();
try {
$cleanUktValue = (int) str_replace('.', '', $request->ukt_saat_ini);
// Store UKT file
$fileUktPath = $request->file('file_ukt')->store('pengajuan/dokumen', 'public');
// Store KHS file (will be used for both IPK and Semester)
$fileKhsPath = $request->file('file_khs')->store('pengajuan/dokumen', 'public');
$pengajuan = PengajuanUkt::create([
'mahasiswa_id' => $mahasiswa->user_id,
'jenis_pengajuan' => $jenis,
'status_validasi' => 'menunggu',
'status_form_id' => $form->id,
'alasan_penolakan' => '',
'ukt_saat_ini' => $cleanUktValue,
'alasan_pengajuan' => $request->input('alasan_pengajuan', ''),
'file_ukt' => $fileUktPath
]);
PengajuanDetail::create([
'pengajuan_ukt_id' => $pengajuan->id,
'kriteria' => 'Slip Pembayaran UKT',
'kriteria_id' => null,
'sub_kriteria_id' => null,
'subkriteria_text' => 'Nominal: Rp '.number_format($cleanUktValue, 0, ',', '.'),
'file_dokumen' => $fileUktPath,
'verified' => false
]);
$kriteriaMap = [
'penghasilan' => 'Penghasilan Orang Tua',
'pekerjaan' => 'Pekerjaan Orang Tua',
'tanggungan' => 'Tanggungan Orang Tua',
'status_ortu' => 'Status Orang Tua',
'hunian' => 'Hunian',
'kendaraan' => 'Kendaraan',
'semester' => 'Semester',
'ipk' => 'IPK'
];
$allKriteria = Kriteria::whereIn('nama_kriteria', array_values($kriteriaMap))->get();
if ($allKriteria->count() !== count($kriteriaMap)) {
throw new \Exception("Beberapa kriteria tidak ditemukan dalam database");
}
$allSubKriteria = SubKriteria::whereIn('kriteria_id', $allKriteria->pluck('id'))->get()->groupBy('kriteria_id');
$detailsToInsert = [];
// Process all criteria except IPK and Semester
foreach ($kriteriaMap as $inputName => $kriteriaName) {
if (in_array($inputName, ['semester', 'ipk'])) continue;
$kriteria = $allKriteria->firstWhere('nama_kriteria', $kriteriaName);
$subkriteriaValue = $request->$inputName;
$subKriteria = isset($allSubKriteria[$kriteria->id])
? $allSubKriteria[$kriteria->id]->firstWhere('nama_subkriteria', $subkriteriaValue)
: null;
// Handle file upload
$fileInputName = 'file_' . $inputName;
$filePath = null;
if ($request->hasFile($fileInputName)) {
$filePath = $request->file($fileInputName)->store('pengajuan/dokumen', 'public');
}
// Special handling for Kendaraan
if ($kriteriaName === 'Kendaraan' && $subkriteriaValue === 'Tidak Punya') {
$filePath = null;
}
$detailsToInsert[] = [
'pengajuan_ukt_id' => $pengajuan->id,
'kriteria' => $kriteriaName,
'kriteria_id' => $kriteria->id,
'sub_kriteria_id' => $subKriteria ? $subKriteria->id : null,
'subkriteria_text' => $subkriteriaValue,
'file_dokumen' => $filePath,
'verified' => false,
'created_at' => now(),
'updated_at' => now()
];
}
// Add Semester criteria with KHS file
$semesterKriteria = $allKriteria->firstWhere('nama_kriteria', 'Semester');
$semesterSubKriteria = $allSubKriteria[$semesterKriteria->id]
->firstWhere('nama_subkriteria', $request->semester);
$detailsToInsert[] = [
'pengajuan_ukt_id' => $pengajuan->id,
'kriteria' => 'Semester',
'kriteria_id' => $semesterKriteria->id,
'sub_kriteria_id' => $semesterSubKriteria->id,
'subkriteria_text' => $request->semester,
'file_dokumen' => $fileKhsPath,
'verified' => false,
'created_at' => now(),
'updated_at' => now()
];
// Add IPK criteria with same KHS file
$ipkKriteria = $allKriteria->firstWhere('nama_kriteria', 'IPK');
$ipkSubKriteria = $allSubKriteria[$ipkKriteria->id]
->firstWhere('nama_subkriteria', $request->ipk);
$detailsToInsert[] = [
'pengajuan_ukt_id' => $pengajuan->id,
'kriteria' => 'IPK',
'kriteria_id' => $ipkKriteria->id,
'sub_kriteria_id' => $ipkSubKriteria->id,
'subkriteria_text' => $request->ipk,
'file_dokumen' => $fileKhsPath,
'verified' => false,
'created_at' => now(),
'updated_at' => now()
];
// Insert all details at once
PengajuanDetail::insert($detailsToInsert);
// Handle optional supporting document
if ($request->hasFile('file_pendukung')) {
$filePendukungPath = $request->file('file_pendukung')->store('pengajuan/dokumen', 'public');
$pengajuan->update(['file_pendukung' => $filePendukungPath]);
}
DB::commit();
return response()->json([
'success' => true,
'message' => 'Pengajuan berhasil dikirim',
'redirect' => route('pengajuan.index')
]);
} catch (\Exception $e) {
DB::rollBack();
Log::error('Pengajuan error: '.$e->getMessage());
return response()->json([
'success' => false,
'message' => 'Gagal mengirim pengajuan: '.$e->getMessage(),
'errors' => $e->getMessage()
], 500);
}
}
private function getDefaultBobot($kriteriaName)
{
$totalKriteria = 8;
return round(1 / $totalKriteria, 3);
}
public function show(PengajuanUkt $pengajuan)
{
if ($pengajuan->mahasiswa_id != auth()->id()) {
abort(403);
}
return redirect()->route('dashboard.mahasiswa')->with('success', 'Pengajuan berhasil diproses');
}
public function viewDocument($pengajuanId, $docType)
{
if (!in_array(auth()->user()->role, ['admin', 'karyawan'])) {
abort(403, 'Akses ditolak!');
}
$pengajuan = PengajuanUkt::findOrFail($pengajuanId);
$docType = str_replace('-', ' ', $docType);
$detail = $pengajuan->details()
->where('kriteria', $docType)
->firstOrFail();
if (!$detail->file_dokumen) {
abort(404, 'File tidak ditemukan');
}
$fullPath = storage_path('app/public/'.$detail->file_dokumen);
if (!file_exists($fullPath)) {
abort(404, 'File tidak ditemukan di storage');
}
return response()->file($fullPath);
}
private function cleanFileName($name)
{
return preg_replace('/[^A-Za-z0-9\-]/', '', str_replace(' ', '_', $name));
}
private function getPengajuanStats($mahasiswaId)
{
return [
'total' => PengajuanUkt::where('mahasiswa_id', $mahasiswaId)->count(),
'diterima' => PengajuanUkt::where('mahasiswa_id', $mahasiswaId)
->where('status_validasi', 'valid')->count(),
'ditolak' => PengajuanUkt::where('mahasiswa_id', $mahasiswaId)
->where('status_validasi', 'tidak valid')->count(),
'menunggu' => PengajuanUkt::where('mahasiswa_id', $mahasiswaId)
->where('status_validasi', 'menunggu')->count()
];
}
}