first commit
This commit is contained in:
121
app/Http/Controllers/CheckinController.php
Normal file
121
app/Http/Controllers/CheckinController.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\KehadiranTaklimat;
|
||||
use App\Models\SesiTaklimat;
|
||||
use App\Models\Sppm\PetugasPermohonan;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CheckinController extends Controller
|
||||
{
|
||||
/**
|
||||
* Papar borang daftar kehadiran selepas petugas scan QR DUN.
|
||||
*/
|
||||
public function show(string $token)
|
||||
{
|
||||
$sesi = SesiTaklimat::where('qr_token', $token)->firstOrFail();
|
||||
$sesi->load('dun');
|
||||
|
||||
if (! $sesi->is_active) {
|
||||
return view('checkin.closed', compact('sesi'));
|
||||
}
|
||||
|
||||
return view('checkin.form', compact('sesi'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sahkan no KP dengan SPPM dan rekod kehadiran.
|
||||
*/
|
||||
public function submit(Request $request, string $token)
|
||||
{
|
||||
$sesi = SesiTaklimat::where('qr_token', $token)->firstOrFail();
|
||||
$sesi->load('dun');
|
||||
|
||||
if (! $sesi->is_active) {
|
||||
return view('checkin.closed', compact('sesi'));
|
||||
}
|
||||
|
||||
$request->validate(
|
||||
['no_kp' => ['required', 'string', 'max:20']],
|
||||
['no_kp.required' => 'Sila masukkan nombor kad pengenalan anda.'],
|
||||
);
|
||||
|
||||
$noKp = preg_replace('/[^0-9A-Za-z]/', '', $request->input('no_kp'));
|
||||
|
||||
// Semak dalam SPPM: no_kp padan + status 'assigned' + DUN yang betul
|
||||
$petugas = PetugasPermohonan::assignedUntukDun($sesi->dun_id)
|
||||
->whereRaw("REPLACE(REPLACE(no_kp, '-', ''), ' ', '') = ?", [$noKp])
|
||||
->with(['assignments' => fn ($q) => $q->orderBy('urutan')->with(['pusatMengundi', 'saluran', 'jawatan'])])
|
||||
->first();
|
||||
|
||||
if (! $petugas) {
|
||||
return back()->withErrors([
|
||||
'no_kp' => 'Maaf, rekod anda tidak ditemui sebagai petugas bertugas (assigned) untuk '
|
||||
. ($sesi->dun->nama ?? 'DUN ini')
|
||||
. '. Sila semak nombor kad pengenalan atau rujuk kaunter pendaftaran.',
|
||||
])->onlyInput('no_kp');
|
||||
}
|
||||
|
||||
// Jika sudah daftar dalam sesi ini, papar semula slip sedia ada
|
||||
$kehadiran = KehadiranTaklimat::where('sesi_taklimat_id', $sesi->id)
|
||||
->where('permohonan_id', $petugas->id)
|
||||
->first();
|
||||
|
||||
$sudahDaftar = (bool) $kehadiran;
|
||||
|
||||
if (! $kehadiran) {
|
||||
$kehadiran = $this->rekodKehadiran($sesi, $petugas, $noKp);
|
||||
}
|
||||
|
||||
return view('checkin.slip', [
|
||||
'sesi' => $sesi,
|
||||
'petugas' => $petugas,
|
||||
'kehadiran' => $kehadiran,
|
||||
'penempatan' => $petugas->butiranPenempatan(),
|
||||
'sudahDaftar' => $sudahDaftar,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jana nombor siri seterusnya dan simpan kehadiran secara atomik.
|
||||
*/
|
||||
private function rekodKehadiran(SesiTaklimat $sesi, PetugasPermohonan $petugas, string $noKp): KehadiranTaklimat
|
||||
{
|
||||
$attempts = 0;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
return DB::transaction(function () use ($sesi, $petugas, $noKp) {
|
||||
$nomborSeterusnya = (int) KehadiranTaklimat::where('sesi_taklimat_id', $sesi->id)
|
||||
->lockForUpdate()
|
||||
->max('nombor_siri') + 1;
|
||||
|
||||
return KehadiranTaklimat::create([
|
||||
'sesi_taklimat_id' => $sesi->id,
|
||||
'permohonan_id' => $petugas->id,
|
||||
'no_kp' => $noKp,
|
||||
'nombor_siri' => $nomborSeterusnya,
|
||||
'hadir_at' => now(),
|
||||
]);
|
||||
});
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
// Hantar berganda: rekod petugas ini mungkin sudah wujud
|
||||
$sediaAda = KehadiranTaklimat::where('sesi_taklimat_id', $sesi->id)
|
||||
->where('permohonan_id', $petugas->id)
|
||||
->first();
|
||||
|
||||
if ($sediaAda) {
|
||||
return $sediaAda;
|
||||
}
|
||||
|
||||
// Perlumbaan nombor siri — cuba semula sehingga 3 kali
|
||||
if (++$attempts >= 3) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user