Files
database-kesiswaan/app/Http/Controllers/PublicStudentSelfServiceController.php

252 lines
12 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Province;
use App\Models\Student;
use App\Models\StudentParent;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\View\View;
class PublicStudentSelfServiceController extends Controller
{
public function index(): View
{
return view('public.student-self-service.verify');
}
public function verify(Request $request): RedirectResponse
{
$data = $request->validate([
'identity_number' => ['required', 'string', 'max:30'],
'access_code' => ['required', 'string', 'max:20'],
], [
'identity_number.required' => 'NIS atau NISN wajib diisi.',
'access_code.required' => 'Kode akses wajib diisi.',
]);
$student = Student::query()
->where('self_service_access_code', strtoupper(trim($data['access_code'])))
->where(function ($query) use ($data) {
$query->where('student_number', $data['identity_number'])
->orWhere('nisn', $data['identity_number']);
})
->first();
if (! $student) {
return back()
->withInput()
->withErrors([
'identity_number' => 'Data siswa tidak ditemukan atau kode akses tidak cocok.',
]);
}
$request->session()->put('student_self_service.student_id', $student->id);
$request->session()->put('student_self_service.verified_at', now()->toIso8601String());
$student->forceFill([
'self_service_last_access_at' => now(),
'self_service_status' => $student->self_service_status === 'submitted' ? 'submitted' : 'draft',
])->save();
return redirect()->route('public.student-self-service.edit');
}
public function edit(Request $request): View|RedirectResponse
{
$student = $this->resolveVerifiedStudent($request);
if (! $student) {
return redirect()->route('public.student-self-service.index')
->withErrors([
'identity_number' => 'Sesi pelengkapan data tidak valid atau sudah berakhir. Silakan verifikasi ulang.',
]);
}
$student->load(['parents', 'academicYear', 'department', 'classRoom']);
return view('public.student-self-service.edit', [
'student' => $student,
'genders' => [
'L' => 'Laki-laki',
'P' => 'Perempuan',
],
'religions' => [
'Islam' => 'Islam',
'Kristen' => 'Kristen',
'Katolik' => 'Katolik',
'Hindu' => 'Hindu',
'Buddha' => 'Buddha',
'Khonghucu' => 'Khonghucu',
'Lainnya' => 'Lainnya',
],
'provinces' => Province::orderBy('name')->pluck('name', 'id'),
'parentRelationLabels' => [
'father' => 'Ayah',
'mother' => 'Ibu',
'guardian' => 'Wali',
],
'educationOptions' => [
'Tidak Sekolah' => 'Tidak Sekolah',
'Tidak Tamat SD' => 'Tidak Tamat SD',
'SD' => 'SD',
'SMP' => 'SMP',
'SLTA' => 'SLTA',
'D1' => 'D1',
'D2' => 'D2',
'D3' => 'D3',
'D4' => 'D4',
'S1' => 'S1',
'S2' => 'S2',
'S3' => 'S3',
'Lainnya' => 'Lainnya',
],
]);
}
public function update(Request $request): RedirectResponse
{
$student = $this->resolveVerifiedStudent($request);
if (! $student) {
return redirect()->route('public.student-self-service.index')
->withErrors([
'identity_number' => 'Sesi pelengkapan data tidak valid atau sudah berakhir. Silakan verifikasi ulang.',
]);
}
$data = $request->validate([
'full_name' => ['required', 'string', 'max:150'],
'gender' => ['required', Rule::in(['L', 'P'])],
'place_of_birth' => ['nullable', 'string', 'max:100'],
'date_of_birth' => ['nullable', 'date'],
'religion' => ['nullable', 'string', 'max:50'],
'nationality' => ['nullable', 'string', 'max:50'],
'nik' => ['nullable', 'string', 'max:30', Rule::unique('students', 'nik')->ignore($student->id)],
'family_card_number' => ['nullable', 'string', 'max:30'],
'child_order' => ['nullable', 'integer', 'min:1', 'max:50'],
'number_of_siblings' => ['nullable', 'integer', 'min:0', 'max:50'],
'phone_number' => ['nullable', 'string', 'max:30'],
'email' => ['nullable', 'email', 'max:100'],
'address' => ['nullable', 'string'],
'province_id' => ['nullable', 'exists:provinces,id'],
'regency_id' => ['nullable', 'exists:regencies,id'],
'district_id' => ['nullable', 'exists:districts,id'],
'village_id' => ['nullable', 'exists:villages,id'],
'postal_code' => ['nullable', 'string', 'max:10'],
'parents.father.name' => ['nullable', 'string', 'max:150'],
'parents.father.nik' => ['nullable', 'string', 'max:30'],
'parents.father.birth_year' => ['nullable', 'integer', 'min:1900', 'max:' . now()->year],
'parents.father.education' => ['nullable', Rule::in(['Tidak Sekolah', 'Tidak Tamat SD', 'SD', 'SMP', 'SLTA', 'D1', 'D2', 'D3', 'D4', 'S1', 'S2', 'S3', 'Lainnya'])],
'parents.father.occupation' => ['nullable', 'string', 'max:100'],
'parents.father.phone_number' => ['nullable', 'string', 'max:30'],
'parents.father.address' => ['nullable', 'string'],
'parents.father.is_alive' => ['nullable', 'boolean'],
'parents.mother.name' => ['nullable', 'string', 'max:150'],
'parents.mother.nik' => ['nullable', 'string', 'max:30'],
'parents.mother.birth_year' => ['nullable', 'integer', 'min:1900', 'max:' . now()->year],
'parents.mother.education' => ['nullable', Rule::in(['Tidak Sekolah', 'Tidak Tamat SD', 'SD', 'SMP', 'SLTA', 'D1', 'D2', 'D3', 'D4', 'S1', 'S2', 'S3', 'Lainnya'])],
'parents.mother.occupation' => ['nullable', 'string', 'max:100'],
'parents.mother.phone_number' => ['nullable', 'string', 'max:30'],
'parents.mother.address' => ['nullable', 'string'],
'parents.mother.is_alive' => ['nullable', 'boolean'],
'parents.guardian.name' => ['nullable', 'string', 'max:150'],
'parents.guardian.nik' => ['nullable', 'string', 'max:30'],
'parents.guardian.birth_year' => ['nullable', 'integer', 'min:1900', 'max:' . now()->year],
'parents.guardian.education' => ['nullable', Rule::in(['Tidak Sekolah', 'Tidak Tamat SD', 'SD', 'SMP', 'SLTA', 'D1', 'D2', 'D3', 'D4', 'S1', 'S2', 'S3', 'Lainnya'])],
'parents.guardian.occupation' => ['nullable', 'string', 'max:100'],
'parents.guardian.phone_number' => ['nullable', 'string', 'max:30'],
'parents.guardian.address' => ['nullable', 'string'],
'parents.guardian.is_alive' => ['nullable', 'boolean'],
'submit_action' => ['required', Rule::in(['draft', 'submit'])],
]);
DB::transaction(function () use ($student, $data) {
$student->fill([
'full_name' => $data['full_name'],
'gender' => $data['gender'],
'place_of_birth' => $data['place_of_birth'] ?? null,
'date_of_birth' => $data['date_of_birth'] ?? null,
'religion' => $data['religion'] ?? null,
'nationality' => $data['nationality'] ?? 'Indonesia',
'nik' => $data['nik'] ?? null,
'family_card_number' => $data['family_card_number'] ?? null,
'child_order' => $data['child_order'] ?? null,
'number_of_siblings' => $data['number_of_siblings'] ?? null,
'phone_number' => $data['phone_number'] ?? null,
'email' => $data['email'] ?? null,
'address' => $data['address'] ?? null,
'province_id' => $data['province_id'] ?? null,
'regency_id' => $data['regency_id'] ?? null,
'district_id' => $data['district_id'] ?? null,
'village_id' => $data['village_id'] ?? null,
'postal_code' => $data['postal_code'] ?? null,
'province' => ! empty($data['province_id']) ? DB::table('provinces')->where('id', $data['province_id'])->value('name') : null,
'city' => ! empty($data['regency_id']) ? DB::table('regencies')->where('id', $data['regency_id'])->value('name') : null,
'district' => ! empty($data['district_id']) ? DB::table('districts')->where('id', $data['district_id'])->value('name') : null,
'village' => ! empty($data['village_id']) ? DB::table('villages')->where('id', $data['village_id'])->value('name') : null,
'self_service_status' => $data['submit_action'] === 'submit' ? 'submitted' : 'draft',
'self_service_last_access_at' => now(),
'self_service_submitted_at' => $data['submit_action'] === 'submit' ? now() : null,
])->save();
foreach (['father', 'mother', 'guardian'] as $relationType) {
$parentData = $data['parents'][$relationType] ?? [];
$hasMeaningfulValue = collect($parentData)
->except('is_alive')
->filter(fn ($value) => filled($value))
->isNotEmpty();
$existingParent = $student->parents()->where('relation_type', $relationType)->first();
if (! $hasMeaningfulValue) {
if ($existingParent) {
$existingParent->delete();
}
continue;
}
$payload = [
'name' => $parentData['name'] ?? '-',
'nik' => $parentData['nik'] ?? null,
'birth_year' => $parentData['birth_year'] ?? null,
'education' => $parentData['education'] ?? null,
'occupation' => $parentData['occupation'] ?? null,
'phone_number' => $parentData['phone_number'] ?? null,
'address' => $parentData['address'] ?? null,
'is_alive' => (bool) ($parentData['is_alive'] ?? false),
];
if ($existingParent) {
$existingParent->update($payload);
} else {
$student->parents()->create([
'relation_type' => $relationType,
...$payload,
]);
}
}
});
return redirect()->route('public.student-self-service.edit')
->with('success', $data['submit_action'] === 'submit'
? 'Data berhasil dikirim. Silakan tunggu pemeriksaan admin sekolah.'
: 'Draft berhasil disimpan. Anda bisa melanjutkan lagi nanti selama sesi masih aktif.');
}
protected function resolveVerifiedStudent(Request $request): ?Student
{
$studentId = $request->session()->get('student_self_service.student_id');
if (! $studentId) {
return null;
}
return Student::find($studentId);
}
}