358 lines
14 KiB
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()
|
|
];
|
|
}
|
|
} |