Files
aplikasi-ketertiban/app/Http/Controllers/StudentReportController.php
T
Bro 8529a49174 feat: penanganan pelanggaran (handling system)
- Migration: handling_status, handled_at, handled_by ke violations
- Migration: tabel violation_handlings, handling_participants
- Model: ViolationHandling, HandlingParticipant + relasi
- Routes: storeHandling, resolveHandling, destroyHandling, calendar data
- ViolationController: CRUD penanganan + filter status handling
- DashboardController: data handling stats + calendar endpoint
- Dashboard view: kalender pelanggaran interaktif (Alpine.js)
- Violations index: filter status penanganan + kolom status
- Violations show: stat card penanganan + timeline + modal tambah
- Menambahkan handling_status filter di index
2026-07-22 22:19:19 +07:00

117 lines
4.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Student;
use Illuminate\Http\RedirectResponse;
use App\Models\SpLetter;
use App\Models\SpThreshold;
use App\Models\Violation;
use Illuminate\Http\Request;
use Illuminate\View\View;
class StudentReportController extends Controller
{
public function index(Request $request): View
{
$query = Student::where('is_active', true);
if ($request->filled('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('full_name', 'like', "%{$search}%")
->orWhere('nisn', 'like', "%{$search}%")
->orWhere('student_number', 'like', "%{$search}%");
});
}
if ($request->filled('class_level')) {
$query->where('class_level', $request->class_level);
}
if ($request->filled('class_name')) {
$query->where('class_name', $request->class_name);
}
if ($request->filled('department')) {
$query->where('department_code', $request->department);
}
$students = $query->withCount(['violations' => fn($q) => $q->whereNull('deleted_at')])
->orderBy('class_name')
->orderBy('full_name')
->paginate(20);
// Data untuk dropdown filter
$classLevels = Student::where('is_active', true)->distinct()->pluck('class_level')->sort()->values();
$classNames = Student::where('is_active', true)->distinct()->pluck('class_name')->sort()->values();
$departments = Student::where('is_active', true)
->selectRaw('DISTINCT department_code, department_name')
->whereNotNull('department_code')
->where('department_code', '!=', '')
->get()
->pluck('department_name', 'department_code');
return view('students.index', compact('students', 'classLevels', 'classNames', 'departments'));
}
public function show(Student $student): View
{
$student->load(['violations' => function ($q) {
$q->with(['violationType.category', 'recorder', 'evidences'])
->latest()
->take(50);
}, 'spLetters' => function ($q) {
$q->with('spThreshold')->latest();
}]);
$totalPoints = $student->total_points;
$violationCount = $student->violations()->whereNull('deleted_at')->count();
$lastViolation = $student->violations()->whereNull('deleted_at')->latest()->first();
$spThresholds = SpThreshold::where('is_active', true)->orderBy('min_points')->get();
// Cari SP threshold yang sudah tercapai
$currentSpLevel = null;
$nextSpThreshold = null;
foreach ($spThresholds as $threshold) {
if ($totalPoints >= $threshold->min_points) {
$currentSpLevel = $threshold;
} elseif (!$nextSpThreshold) {
$nextSpThreshold = $threshold;
}
}
// SP yang sudah terbit
$activeSpLetters = $student->spLetters()->whereIn('status', ['draft', 'issued'])->count();
return view('students.show', compact(
'student', 'totalPoints', 'violationCount', 'lastViolation',
'spThresholds', 'currentSpLevel', 'nextSpThreshold', 'activeSpLetters'
));
}
public function update(Request $request, Student $student): RedirectResponse
{
$validated = $request->validate([
'full_name' => ['required', 'string', 'max:255'],
'nisn' => ['nullable', 'string', 'max:50'],
'student_number' => ['nullable', 'string', 'max:50'],
'gender' => ['nullable', 'in:L,P'],
'place_of_birth' => ['nullable', 'string', 'max:255'],
'date_of_birth' => ['nullable', 'date'],
'address' => ['nullable', 'string', 'max:500'],
'phone_number' => ['nullable', 'string', 'max:30'],
'email' => ['nullable', 'string', 'email', 'max:255'],
'class_name' => ['nullable', 'string', 'max:100'],
'class_level' => ['nullable', 'string', 'max:20'],
'department_code' => ['nullable', 'string', 'max:20'],
'department_name' => ['nullable', 'string', 'max:100'],
]);
$student->update($validated);
return redirect()->route('students.show', $student->id)
->with('success', 'Data siswa berhasil diperbarui.');
}
}