add tests batch 20

This commit is contained in:
root
2026-06-09 01:03:53 -04:00
parent 95efb9652e
commit 6be4875c5e
1502 changed files with 13797 additions and 11313 deletions
@@ -7,21 +7,17 @@ use App\Models\LateSlipLog;
use App\Models\Student;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class AttendanceManagementService
{
public const STATUS_PRESENT = 'present';
public const STATUS_ABSENT_PENDING = 'absent_pending_verification';
public const STATUS_ABSENT = 'absent';
public const STATUS_LATE = 'late';
public const STATUS_EARLY_DISMISSAL = 'early_dismissal';
public const STATUS_LATE_WITHOUT_SLIP = 'late_without_slip';
public function dashboard(array $filters = []): array
@@ -208,7 +204,6 @@ class AttendanceManagementService
if ($person['type'] === 'student' && $status === self::STATUS_LATE) {
$row['late_slip'] = $this->printLateSlip($row, $actor);
}
return $row;
}
@@ -258,7 +253,6 @@ class AttendanceManagementService
if (($data['exit_method'] ?? '') === 'manual_exit') {
$this->recordBadgeException((int) $id, $person, $exitAt, 'manual exit entry', $badgeExceptions, $actor, $data['notes'] ?? null);
}
return $row;
}
@@ -298,7 +292,6 @@ class AttendanceManagementService
];
$id = DB::table('attendance_management_events')->insertGetId($row);
$row['id'] = $id;
return $row;
}
@@ -319,7 +312,6 @@ class AttendanceManagementService
$update['report_status'] = $this->normalizeReportStatus($data['report_status']);
}
DB::table('attendance_management_events')->where('id', $id)->update($update);
return (array) DB::table('attendance_management_events')->where('id', $id)->first();
}
@@ -355,7 +347,6 @@ class AttendanceManagementService
'final_decision' => 'Late slip reprinted',
'updated_at' => now(),
]);
return $row;
}
@@ -376,24 +367,12 @@ class AttendanceManagementService
$student = null;
$user = null;
if ($type === 'student' && $id > 0) {
$student = Student::query()->find($id);
}
if (in_array($type, ['staff', 'user', 'teacher', 'administrator'], true) && $id > 0) {
$user = User::query()->find($id);
}
if (! $student && $badge !== '') {
$student = Student::query()->where('rfid_tag', $badge)->first();
}
if (! $student && ! $user && $badge !== '') {
$user = User::query()->where('rfid_tag', $badge)->first();
}
if (! $student && ! $user && $id > 0) {
$student = Student::query()->find($id);
}
if (! $student && ! $user && $id > 0) {
$user = User::query()->find($id);
}
if ($type === 'student' && $id > 0) $student = Student::query()->find($id);
if (in_array($type, ['staff', 'user', 'teacher', 'administrator'], true) && $id > 0) $user = User::query()->find($id);
if (! $student && $badge !== '') $student = Student::query()->where('rfid_tag', $badge)->first();
if (! $student && ! $user && $badge !== '') $user = User::query()->where('rfid_tag', $badge)->first();
if (! $student && ! $user && $id > 0) $student = Student::query()->find($id);
if (! $student && ! $user && $id > 0) $user = User::query()->find($id);
if ($student) {
return [
@@ -418,7 +397,6 @@ class AttendanceManagementService
if ($name === '') {
throw new \InvalidArgumentException('Person could not be resolved. Provide person_id, badge_id, or person_name.');
}
return [
'type' => $type !== '' ? $type : 'visitor',
'id' => $id > 0 ? $id : null,
@@ -441,7 +419,6 @@ class AttendanceManagementService
'admin_name' => $actor ? trim(($actor->firstname ?? '').' '.($actor->lastname ?? '')) : 'System',
];
$logged = LateSlipLog::logSlip($payload, $actor?->id);
return [
'printed' => $logged,
'slip_number' => 'AME-'.($event['id'] ?? time()),
@@ -481,16 +458,9 @@ class AttendanceManagementService
$absence = (clone $q)->where('attendance_status', self::STATUS_ABSENT)->count();
$late = (clone $q)->whereIn('attendance_status', [self::STATUS_LATE, self::STATUS_LATE_WITHOUT_SLIP])->count();
$ed = (clone $q)->where('attendance_status', self::STATUS_EARLY_DISMISSAL)->count();
if ($newStatus === self::STATUS_ABSENT) {
$absence++;
}
if (in_array($newStatus, [self::STATUS_LATE, self::STATUS_LATE_WITHOUT_SLIP], true)) {
$late++;
}
if ($newStatus === self::STATUS_EARLY_DISMISSAL) {
$ed++;
}
if ($newStatus === self::STATUS_ABSENT) $absence++;
if (in_array($newStatus, [self::STATUS_LATE, self::STATUS_LATE_WITHOUT_SLIP], true)) $late++;
if ($newStatus === self::STATUS_EARLY_DISMISSAL) $ed++;
return ['absence_count' => $absence, 'late_count' => $late, 'early_dismissal_count' => $ed];
}
@@ -558,7 +528,6 @@ class AttendanceManagementService
private function schoolStartFor(Carbon $date): Carbon
{
$configured = Configuration::getConfigValueByKey('school_start_time') ?: config('attendance.school_start_time', '09:00:00');
return Carbon::parse($date->toDateString().' '.$configured, $date->timezone);
}
@@ -647,20 +616,12 @@ class AttendanceManagementService
}));
}
private function dateTime($value): Carbon
{
return $value instanceof Carbon ? $value : Carbon::parse((string) $value);
}
private function dateOnly($value): string
{
return Carbon::parse((string) $value)->toDateString();
}
private function dateTime($value): Carbon { return $value instanceof Carbon ? $value : Carbon::parse((string) $value); }
private function dateOnly($value): string { return Carbon::parse((string) $value)->toDateString(); }
private function normalizeReportStatus($value): string
{
$v = strtolower(str_replace(['-', ' '], '_', trim((string) $value)));
return in_array($v, ['reported', 'not_reported', 'pending_clarification'], true) ? $v : 'pending_clarification';
}
@@ -680,61 +641,30 @@ class AttendanceManagementService
private function combinationCode(int $abs, int $late, int $ed, int $badge): string
{
$parts = [];
if ($abs > 0) {
$parts[] = min($abs, 5).'ABS';
}
if ($late > 0) {
$parts[] = min($late, 5).'Late';
}
if ($ed > 0) {
$parts[] = min($ed, 3).'ED';
}
if ($badge > 0) {
$parts[] = min($badge, 5).'Badge Exceptions';
}
if ($abs > 0) $parts[] = min($abs, 5).'ABS';
if ($late > 0) $parts[] = min($late, 5).'Late';
if ($ed > 0) $parts[] = min($ed, 3).'ED';
if ($badge > 0) $parts[] = min($badge, 5).'Badge Exceptions';
return $parts ? implode(' + ', $parts) : 'Clear';
}
private function riskLevel(int $abs, int $late, int $ed, int $badge): string
{
if ($abs >= 5 && $late >= 5) {
return 'severe';
}
if ($abs >= 5 || $late >= 5) {
return 'critical';
}
if ($abs + $late + $ed + $badge >= 6 || $abs >= 4 || $late >= 4) {
return 'very_high';
}
if ($abs + $late + $ed + $badge >= 4 || $abs >= 3 || $late >= 3 || $badge >= 4) {
return 'high';
}
if ($abs + $late + $ed + $badge >= 2 || $badge >= 2) {
return 'medium';
}
if ($abs >= 5 && $late >= 5) return 'severe';
if ($abs >= 5 || $late >= 5) return 'critical';
if ($abs + $late + $ed + $badge >= 6 || $abs >= 4 || $late >= 4) return 'very_high';
if ($abs + $late + $ed + $badge >= 4 || $abs >= 3 || $late >= 3 || $badge >= 4) return 'high';
if ($abs + $late + $ed + $badge >= 2 || $badge >= 2) return 'medium';
return 'low';
}
private function actionNeeded(string $status, string $reportStatus, int $badgeCount): string
{
if ($badgeCount >= 5) {
return 'Leadership review for badge compliance';
}
if ($badgeCount >= 4) {
return 'Formal badge follow-up required';
}
if ($status === self::STATUS_LATE && $reportStatus !== 'reported') {
return 'Print late slip and contact parent or staff';
}
if ($status === self::STATUS_ABSENT && $reportStatus !== 'reported') {
return 'Same-day contact required';
}
if ($status === self::STATUS_EARLY_DISMISSAL && $reportStatus !== 'reported') {
return 'Verify authorization and contact guardian/supervisor';
}
if ($badgeCount >= 5) return 'Leadership review for badge compliance';
if ($badgeCount >= 4) return 'Formal badge follow-up required';
if ($status === self::STATUS_LATE && $reportStatus !== 'reported') return 'Print late slip and contact parent or staff';
if ($status === self::STATUS_ABSENT && $reportStatus !== 'reported') return 'Same-day contact required';
if ($status === self::STATUS_EARLY_DISMISSAL && $reportStatus !== 'reported') return 'Verify authorization and contact guardian/supervisor';
return 'Record and monitor';
}