252 lines
12 KiB
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);
|
|
}
|
|
}
|