fix gitlab tests

This commit is contained in:
root
2026-06-09 02:32:58 -04:00
parent 20a0b6c4e5
commit 6def9993da
1489 changed files with 10449 additions and 11356 deletions
@@ -2,7 +2,6 @@
namespace App\Services\Parents;
use App\Controllers\View\AuthorizedUsersController;
use App\Models\AuthorizedUser;
use App\Models\User;
use App\Services\ApplicationUrlService;
@@ -10,7 +9,7 @@ use App\Services\Email\EmailDispatchService;
use Illuminate\Support\Facades\DB;
/**
* legacy {@see AuthorizedUsersController} parity.
* legacy {@see \App\Controllers\View\AuthorizedUsersController} parity.
*/
class AuthorizedUsersManagementService
{
@@ -6,7 +6,9 @@ use Illuminate\Support\Facades\DB;
class ParentAttendanceReportCalendarService
{
public function __construct(private ParentConfigService $configService) {}
public function __construct(private ParentConfigService $configService)
{
}
/**
* @return array{0: array<int, array{value:string,label:string}>, 1: string}
@@ -31,7 +33,7 @@ class ParentAttendanceReportCalendarService
$dates = [];
for ($i = $weeksBefore; $i >= 1; $i--) {
$dates[] = $thisSunday->copy()->modify('-'.$i.' week');
$dates[] = $thisSunday->copy()->modify('-' . $i . ' week');
}
$cursor = $thisSunday->copy();
@@ -70,13 +72,13 @@ class ParentAttendanceReportCalendarService
$filtered = [];
foreach ($dates as $d) {
$ymd = $d->format('Y-m-d');
if (! isset($noSchool[$ymd]) && $d >= $today && $d <= $cap) {
if (!isset($noSchool[$ymd]) && $d >= $today && $d <= $cap) {
$filtered[] = $d;
}
}
$defaultYmd = $default->format('Y-m-d');
if (! empty($filtered)) {
if (!empty($filtered)) {
$defaultYmd = $filtered[0]->format('Y-m-d');
}
@@ -99,10 +101,8 @@ class ParentAttendanceReportCalendarService
}
if (preg_match('/^(\\d{1,2}):(\\d{2})$/', $raw, $m)) {
$hh = str_pad((string) ((int) $m[1]), 2, '0', STR_PAD_LEFT);
return $hh.':'.$m[2];
return $hh . ':' . $m[2];
}
return $default;
}
@@ -2,14 +2,12 @@
namespace App\Services\Parents;
use App\Controllers\View\ParentAttendanceReportController;
use App\Http\Controllers\Api\Reports\FilesController;
use App\Models\AttendanceData;
use App\Models\AttendanceRecord;
use App\Models\ClassSection;
use App\Models\EarlyDismissalSignature;
use App\Models\ParentAttendanceReport;
use App\Models\Student;
use App\Models\ClassSection;
use App\Services\SemesterRangeService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
@@ -20,7 +18,8 @@ class ParentAttendanceReportService
private ParentConfigService $configService,
private ParentAttendanceReportCalendarService $calendarService,
private SemesterRangeService $semesterRangeService
) {}
) {
}
public function formData(int $parentId): array
{
@@ -91,7 +90,7 @@ class ParentAttendanceReportService
}
$type = (string) ($payload['type'] ?? '');
if (! in_array($type, ['absent', 'late', 'early_dismissal'], true)) {
if (!in_array($type, ['absent', 'late', 'early_dismissal'], true)) {
throw new \RuntimeException('Invalid report type.');
}
@@ -105,8 +104,8 @@ class ParentAttendanceReportService
foreach ($rawDates as $entry) {
$dt = \DateTime::createFromFormat('Y-m-d', $entry);
if (! $dt) {
throw new \RuntimeException('Invalid date selected: '.$entry);
if (!$dt) {
throw new \RuntimeException('Invalid date selected: ' . $entry);
}
if ((int) $dt->format('w') !== 0) {
throw new \RuntimeException('Please select Sunday dates only.');
@@ -120,10 +119,10 @@ class ParentAttendanceReportService
$validDates[$entry] = $dt;
}
if ($type === 'late' && (! is_string($arrivalTime) || $arrivalTime === '')) {
if ($type === 'late' && (!is_string($arrivalTime) || $arrivalTime === '')) {
throw new \RuntimeException('Please provide an expected arrival time for late reporting.');
}
if ($type === 'early_dismissal' && (! is_string($dismissTime) || $dismissTime === '')) {
if ($type === 'early_dismissal' && (!is_string($dismissTime) || $dismissTime === '')) {
throw new \RuntimeException('Please provide a dismissal time for early dismissal.');
}
if ($type !== 'early_dismissal') {
@@ -148,7 +147,7 @@ class ParentAttendanceReportService
->first();
$classSectionId = $sectionRow->class_section_id ?? null;
$student = Student::query()->select('firstname', 'lastname')->find($sid);
$studentName = $student ? trim($student->firstname.' '.$student->lastname) : ('Student #'.$sid);
$studentName = $student ? trim($student->firstname . ' ' . $student->lastname) : ('Student #' . $sid);
$classLabel = $this->resolveClassSectionLabel($classSectionId);
foreach ($validDates as $reportDate => $_dt) {
@@ -164,7 +163,7 @@ class ParentAttendanceReportService
->whereIn('type', ['absent', 'late'])
->first();
if ($existingAL) {
$blocked[] = $studentName.' ('.$reportDate.')';
$blocked[] = $studentName . ' (' . $reportDate . ')';
} else {
$existingED = (clone $qb)->where('type', 'early_dismissal')->first();
if ($existingED) {
@@ -196,7 +195,7 @@ class ParentAttendanceReportService
->whereIn('type', ['absent', 'late', 'early_dismissal'])
->first();
if ($existingAny) {
$blocked[] = $studentName.' ('.$reportDate.')';
$blocked[] = $studentName . ' (' . $reportDate . ')';
} else {
ParentAttendanceReport::query()->create([
'parent_id' => $parentId,
@@ -243,8 +242,8 @@ class ParentAttendanceReportService
}
if ($inserted <= 0) {
$err = ! empty($blocked)
? ('Already submitted and cannot be changed for: '.implode(', ', array_slice($blocked, 0, 5)).(count($blocked) > 5 ? '…' : ''))
$err = !empty($blocked)
? ('Already submitted and cannot be changed for: ' . implode(', ', array_slice($blocked, 0, 5)) . (count($blocked) > 5 ? '…' : ''))
: 'Could not save your report. Please try again.';
throw new \RuntimeException($err);
}
@@ -279,7 +278,7 @@ class ParentAttendanceReportService
})));
$type = (string) ($payload['type'] ?? '');
if (empty($dateValues) || ! in_array($type, ['absent', 'late', 'early_dismissal'], true)) {
if (empty($dateValues) || !in_array($type, ['absent', 'late', 'early_dismissal'], true)) {
throw new \RuntimeException('Invalid date or type.');
}
@@ -313,7 +312,7 @@ class ParentAttendanceReportService
if ($sid <= 0) {
continue;
}
if (! isset($map[$sid])) {
if (!isset($map[$sid])) {
$map[$sid] = [
'student_id' => $sid,
'firstname' => (string) ($row['firstname'] ?? ''),
@@ -327,7 +326,7 @@ class ParentAttendanceReportService
}
$map[$sid]['dates'][$dVal] = $map[$sid]['dates'][$dVal] ?? [];
$t = (string) ($row['type'] ?? '');
if ($t !== '' && ! in_array($t, $map[$sid]['dates'][$dVal], true)) {
if ($t !== '' && !in_array($t, $map[$sid]['dates'][$dVal], true)) {
$map[$sid]['dates'][$dVal][] = $t;
}
}
@@ -338,7 +337,7 @@ class ParentAttendanceReportService
public function updateReport(int $parentId, int $reportId, array $payload): void
{
$row = ParentAttendanceReport::query()->find($reportId);
if (! $row || (int) $row->parent_id !== $parentId) {
if (!$row || (int) $row->parent_id !== $parentId) {
throw new \RuntimeException('Report not found.');
}
@@ -348,7 +347,7 @@ class ParentAttendanceReportService
$tzName = (string) (config('School')->attendance['timezone'] ?? 'UTC');
$tz = new \DateTimeZone($tzName ?: 'UTC');
$cutoff = new \DateTime($row->report_date.' 09:00:00', $tz);
$cutoff = new \DateTime($row->report_date . ' 09:00:00', $tz);
$now = new \DateTime('now', $tz);
if ($now >= $cutoff) {
throw new \RuntimeException('Editing window closed at 9:00 AM on the report date.');
@@ -364,13 +363,13 @@ class ParentAttendanceReportService
];
if ($type === 'late' && $arrival !== '') {
if (! preg_match('/^\\d{2}:\\d{2}(:\\d{2})?$/', $arrival)) {
if (!preg_match('/^\\d{2}:\\d{2}(:\\d{2})?$/', $arrival)) {
throw new \RuntimeException('Invalid arrival time format.');
}
$update['arrival_time'] = $arrival;
}
if ($type === 'early_dismissal' && $dismiss !== '') {
if (! preg_match('/^\\d{2}:\\d{2}(:\\d{2})?$/', $dismiss)) {
if (!preg_match('/^\\d{2}:\\d{2}(:\\d{2})?$/', $dismiss)) {
throw new \RuntimeException('Invalid dismissal time format.');
}
$update['dismiss_time'] = $dismiss;
@@ -386,7 +385,7 @@ class ParentAttendanceReportService
/**
* Staff index: early dismissal rows grouped by date (+ signature metadata per date).
*
* Parity with legacy {@see ParentAttendanceReportController::earlyDismissals}.
* Parity with legacy {@see \App\Controllers\View\ParentAttendanceReportController::earlyDismissals}.
*
* @return array{groups: array<string, array<int, array<string, mixed>>>, school_year: string, semester: string, signature_by_date: array<string, array<string, mixed>>}
*/
@@ -468,7 +467,7 @@ class ParentAttendanceReportService
}
/**
* Parity with legacy {@see ParentAttendanceReportController::addEarlyDismissalForm}.
* Parity with legacy {@see \App\Controllers\View\ParentAttendanceReportController::addEarlyDismissalForm}.
*
* @return array{students: array<int, array<string, mixed>>, default_date: string, school_year: string, semester: string}
*/
@@ -506,7 +505,7 @@ class ParentAttendanceReportService
}
/**
* Parity with legacy {@see ParentAttendanceReportController::saveEarlyDismissal}.
* Parity with legacy {@see \App\Controllers\View\ParentAttendanceReportController::saveEarlyDismissal}.
*/
public function saveStaffEarlyDismissal(int $studentId, string $reportDate, string $dismissTime, string $reason): void
{
@@ -574,8 +573,8 @@ class ParentAttendanceReportService
}
/**
* Parity with legacy {@see ParentAttendanceReportController::uploadEarlyDismissalSignature}.
* Files live under {@see storage_path('uploads/early_dismissal_signatures')} (same as {@see FilesController::earlyDismissalSignature}).
* Parity with legacy {@see \App\Controllers\View\ParentAttendanceReportController::uploadEarlyDismissalSignature}.
* Files live under {@see storage_path('uploads/early_dismissal_signatures')} (same as {@see \App\Http\Controllers\Api\Reports\FilesController::earlyDismissalSignature}).
*/
public function storeEarlyDismissalSignature(
UploadedFile $file,
@@ -645,7 +644,7 @@ class ParentAttendanceReportService
$oldFile = (string) ($existing->filename ?? '');
$existing->update($payload);
if ($oldFile !== '' && $oldFile !== $filename) {
@unlink($targetDir.DIRECTORY_SEPARATOR.$oldFile);
@unlink($targetDir . DIRECTORY_SEPARATOR . $oldFile);
}
} else {
EarlyDismissalSignature::query()->create($payload);
@@ -681,7 +680,7 @@ class ParentAttendanceReportService
return;
}
if (! $classSectionId) {
if (!$classSectionId) {
$row = DB::table('student_class')
->select('class_section_id')
->where('student_id', $studentId)
@@ -704,19 +703,19 @@ class ParentAttendanceReportService
$reasonParts = ['Parent-reported'];
if ($type === 'late' && $arrivalTime) {
$reasonParts[] = 'ETA '.substr($arrivalTime, 0, 5);
$reasonParts[] = 'ETA ' . substr($arrivalTime, 0, 5);
}
if (! empty($reason)) {
if (!empty($reason)) {
$reasonParts[] = trim($reason);
}
$reasonText = implode(' — ', $reasonParts);
if (! $existing) {
if (!$existing) {
$classId = ClassSection::query()
->where('class_section_id', $classSectionId)
->value('class_id');
$schoolId = Student::query()->whereKey($studentId)->value('school_id');
if (! $classId || ! $schoolId) {
if (!$classId || !$schoolId) {
return;
}
AttendanceData::query()->create([
@@ -731,7 +730,6 @@ class ParentAttendanceReportService
'school_year' => $schoolYear,
]);
$this->bumpAttendanceRecord($studentId, $classSectionId, $schoolId, $status, $semester, $schoolYear);
return;
}
@@ -773,7 +771,6 @@ class ParentAttendanceReportService
$updates['total_late']++;
}
$record->update($updates);
return;
}
@@ -6,7 +6,9 @@ use Illuminate\Support\Facades\DB;
class ParentAttendanceService
{
public function __construct(private ParentConfigService $configService) {}
public function __construct(private ParentConfigService $configService)
{
}
public function listAttendance(int $parentId, ?string $schoolYear = null): array
{
@@ -10,7 +10,8 @@ class ParentEmergencyContactService
public function __construct(
private ParentConfigService $configService,
private PhoneFormatterService $phoneFormatter
) {}
) {
}
public function list(int $parentId): array
{
@@ -10,7 +10,9 @@ use Illuminate\Support\Facades\DB;
class ParentEnrollmentService
{
public function __construct(private ParentConfigService $configService) {}
public function __construct(private ParentConfigService $configService)
{
}
public function overview(int $parentId, ?string $schoolYear = null): array
{
@@ -24,11 +26,11 @@ class ParentEnrollmentService
->get()
->map(function ($student) use ($selectedYear) {
$classSections = StudentClass::getClassSectionsByStudentId($student->id, $selectedYear, true);
$student->class_section = ! empty($classSections)
$student->class_section = !empty($classSections)
? implode(', ', $classSections)
: 'Class not Assigned';
$isArabicClass = ! empty($classSections) && array_reduce(
$isArabicClass = !empty($classSections) && array_reduce(
$classSections,
static fn ($carry, $name) => $carry || (is_string($name) && stripos($name, 'arabic') === 0),
false
@@ -179,7 +181,7 @@ class ParentEnrollmentService
->where('is_withdrawn', 0)
->first();
if (! $enrollment) {
if (!$enrollment) {
continue;
}
@@ -204,7 +206,7 @@ class ParentEnrollmentService
if ($refund) {
$refund->update([
'reason' => 'Withdrawal under review for student ID '.$studentId,
'reason' => 'Withdrawal under review for student ID ' . $studentId,
'note' => null,
'updated_by' => $parentId,
]);
@@ -215,7 +217,7 @@ class ParentEnrollmentService
'requested_at' => now(),
'school_year' => $schoolYear,
'status' => Refund::STATUS_PENDING,
'reason' => 'Withdrawal under review for student ID '.$studentId,
'reason' => 'Withdrawal under review for student ID ' . $studentId,
'request' => 'new',
'semester' => $semester,
'refund_paid_amount' => 0.0,
@@ -2,9 +2,9 @@
namespace App\Services\Parents;
use App\Models\Enrollment;
use App\Models\Event;
use App\Models\EventCharges;
use App\Models\Enrollment;
use App\Models\Student;
use App\Services\Invoices\InvoiceGenerationService;
@@ -13,7 +13,8 @@ class ParentEventParticipationService
public function __construct(
private ParentConfigService $configService,
private InvoiceGenerationService $invoiceGeneration
) {}
) {
}
public function overview(int $parentId): array
{
@@ -26,7 +27,7 @@ class ParentEventParticipationService
$charges = [];
foreach ($chargesList as $charge) {
$key = $charge['student_id'].':'.$charge['event_id'];
$key = $charge['student_id'] . ':' . $charge['event_id'];
$charges[$key] = [
'participation' => $charge['participation'],
'date' => $charge['updated_at'] ?? $charge['created_at'],
@@ -106,7 +107,6 @@ class ParentEventParticipationService
if ($existing) {
$existing->delete();
}
continue;
}
@@ -9,7 +9,6 @@ class ParentProfileService
public function getProfile(int $parentId): ?array
{
$user = User::query()->find($parentId);
return $user ? $user->toArray() : null;
}
@@ -2,16 +2,13 @@
namespace App\Services\Parents;
use App\Controllers\ParentProgressController;
use App\Http\Resources\ClassProgress\ClassProgressReportResource;
use App\Models\ClassProgressReport;
use App\Services\ClassProgress\ClassProgressQueryService;
use Carbon\CarbonInterface;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
/**
* legacy {@see ParentProgressController} read-side logic.
* legacy {@see \App\Controllers\ParentProgressController} read-side logic.
*/
class ParentProgressQueryService
{
@@ -136,7 +133,7 @@ class ParentProgressQueryService
$statusLabel = $statusOptions[$row->status] ?? 'Unknown';
$row->setAttribute('status_label', $statusLabel);
$weekStart = $row->week_start instanceof CarbonInterface
$weekStart = $row->week_start instanceof \Carbon\CarbonInterface
? $row->week_start->format('Y-m-d')
: (string) $row->week_start;
$sectionId = (int) $row->class_section_id;
@@ -148,7 +145,7 @@ class ParentProgressQueryService
if (! isset($reportGroups[$key])) {
$reportGroups[$key] = [
'week_start' => $weekStart,
'week_end' => $row->week_end instanceof CarbonInterface
'week_end' => $row->week_end instanceof \Carbon\CarbonInterface
? $row->week_end->format('Y-m-d')
: (string) ($row->week_end ?? ''),
'class_section_name' => $row->class_section_name ?? '',
@@ -162,7 +159,7 @@ class ParentProgressQueryService
continue;
}
$reportGroups[$key]['reports'][$subject] = (new ClassProgressReportResource($row))->toArray(request());
$reportGroups[$key]['reports'][$subject] = (new \App\Http\Resources\ClassProgress\ClassProgressReportResource($row))->toArray(request());
}
return $reportGroups;
@@ -15,7 +15,8 @@ class ParentRegistrationService
public function __construct(
private ParentConfigService $configService,
private SchoolIdService $schoolIdService
) {}
) {
}
public function overview(int $parentId): array
{
@@ -38,7 +39,6 @@ class ParentRegistrationService
$kids = $kids->map(function ($kid) use ($allergies, $conditions) {
$kid->allergies = ($allergies[$kid->id] ?? collect())->pluck('allergy')->all();
$kid->medical_conditions = ($conditions[$kid->id] ?? collect())->pluck('condition_name')->all();
return $kid->toArray();
})->all();
@@ -105,7 +105,6 @@ class ParentRegistrationService
'dob' => $student['dob'],
'reason' => 'already_registered',
];
continue;
}
@@ -116,7 +115,7 @@ class ParentRegistrationService
'age' => $this->calculateAge($student['dob'], $ageReference),
'gender' => $student['gender'],
'registration_grade' => $student['registration_grade'] ?? null,
'photo_consent' => ! empty($student['photo_consent']) ? 1 : 0,
'photo_consent' => !empty($student['photo_consent']) ? 1 : 0,
'parent_id' => $parentId,
'year_of_registration' => (string) date('Y'),
'school_year' => $schoolYear,
@@ -187,7 +186,7 @@ class ParentRegistrationService
'age' => $this->calculateAge($payload['dob'], $ageReference),
'gender' => $payload['gender'],
'registration_grade' => $payload['registration_grade'] ?? null,
'photo_consent' => ! empty($payload['photo_consent']) ? 1 : 0,
'photo_consent' => !empty($payload['photo_consent']) ? 1 : 0,
]);
StudentMedicalCondition::query()->where('student_id', $studentId)->delete();
@@ -235,7 +234,6 @@ class ParentRegistrationService
try {
$dobObj = new \DateTimeImmutable($dob);
$refObj = new \DateTimeImmutable($referenceDate);
return (int) $dobObj->diff($refObj)->y;
} catch (\Throwable $e) {
return 0;
@@ -2,15 +2,14 @@
namespace App\Services\Parents;
use App\Controllers\ParentReportCardController;
use App\Models\Configuration;
use App\Services\ApplicationUrlService;
use App\Models\ReportCardAcknowledgement;
use App\Models\User;
use App\Services\ApplicationUrlService;
use Illuminate\Support\Facades\DB;
/**
* legacy {@see ParentReportCardController} parity (read + acknowledgement).
* legacy {@see \App\Controllers\ParentReportCardController} parity (read + acknowledgement).
*/
class ParentReportCardService
{
@@ -86,7 +85,7 @@ class ParentReportCardService
}
/**
* @param list<int> $studentIds
* @param list<int> $studentIds
* @return array<int, array<string, mixed>>
*/
public function acknowledgementMap(int $primaryParentUserId, array $studentIds, string $schoolYear, string $semester): array
@@ -118,7 +117,7 @@ class ParentReportCardService
}
/**
* @param array<string, mixed> $values viewed_at, signed_at, signed_name, signer_ip, …
* @param array<string, mixed> $values viewed_at, signed_at, signed_name, signer_ip, …
*/
public function touchAcknowledgement(
int $primaryParentUserId,
@@ -2,15 +2,13 @@
namespace App\Services\Parents;
use App\Controllers\ParentReportCardController;
use App\Models\Student;
use App\Models\User;
use Illuminate\Support\Facades\DB;
/**
* Maps the logged-in parent-family account to the primary parent's user id
* (stored on {@see Student::$parent_id}), matching legacy
* {@see ParentReportCardController::resolvePrimaryParentId}.
* (stored on {@see \App\Models\Student::$parent_id}), matching legacy
* {@see \App\Controllers\ParentReportCardController::resolvePrimaryParentId}.
*/
final class PrimaryParentUserResolver
{
@@ -24,7 +22,7 @@ final class PrimaryParentUserResolver
}
/**
* @param int $userId Session user id (may be secondary/tertiary login).
* @param int $userId Session user id (may be secondary/tertiary login).
*/
public function resolveFromCredentials(int $userId, string $userType): ?int
{