Files
alrahma_sunday_school_api/app/Services/Attendance/AttendanceDailySummaryService.php
root e0dfc3ec82
API CI/CD / Validate (composer + pint) (push) Successful in 3m15s
API CI/CD / Test (PHPUnit) (push) Failing after 5m4s
API CI/CD / Build frontend assets (push) Successful in 1m3s
API CI/CD / Security audit (push) Failing after 49s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
Fixed many feature failures around preferences, route coverage, administrator enrollment, assignment section names, attendance tracking controller access, finance PDF generation, and finance notification logging.
2026-07-07 21:26:47 -04:00

97 lines
3.0 KiB
PHP

<?php
namespace App\Services\Attendance;
use App\Services\EmailService;
use App\Services\Notifications\UserNotificationDispatchService;
use Illuminate\Support\Facades\DB;
class AttendanceDailySummaryService
{
public function __construct(
private UserNotificationDispatchService $notifier,
private EmailService $emailService
) {}
public function sendAbsenteesSummary(): int
{
$rows = $this->fetchTodaySummary('absent');
return $this->notifyParents($rows, 'absent');
}
public function sendLatesSummary(): int
{
$rows = $this->fetchTodaySummary('late');
return $this->notifyParents($rows, 'late');
}
private function fetchTodaySummary(string $type): array
{
$today = now()->toDateString();
$query = DB::table('attendance_data as ad')
->join('students as s', 's.id', '=', 'ad.student_id')
->leftJoin('users as u', 'u.id', '=', 's.parent_id')
->select(
'ad.date',
's.id as student_id',
's.firstname as student_firstname',
's.lastname as student_lastname',
'u.id as parent_id',
'u.email as parent_email',
'u.firstname as parent_firstname',
'u.lastname as parent_lastname'
)
->whereDate('ad.date', $today);
if ($type === 'absent') {
$query->where(function ($w) {
$w->whereIn(DB::raw('UPPER(TRIM(ad.status))'), ['ABSENT', 'ABS', 'A'])
->orWhereRaw("UPPER(TRIM(ad.status)) LIKE 'ABS%'");
});
} else {
$query->where(function ($w) {
$w->whereIn(DB::raw('UPPER(TRIM(ad.status))'), ['LATE', 'L'])
->orWhereRaw("UPPER(TRIM(ad.status)) LIKE 'LATE%'");
});
}
return $query->get()->map(fn ($row) => (array) $row)->all();
}
private function notifyParents(array $rows, string $type): int
{
$sent = 0;
foreach ($rows as $row) {
$parentId = (int) ($row['parent_id'] ?? 0);
if ($parentId <= 0) {
continue;
}
$studentName = trim((string) ($row['student_firstname'] ?? '').' '.(string) ($row['student_lastname'] ?? ''));
$date = substr((string) ($row['date'] ?? ''), 0, 10);
$message = sprintf(
'Daily Attendance Update: %s was marked %s on %s.',
$studentName !== '' ? $studentName : 'Your student',
$type,
$date
);
$this->notifier->notifyUser($parentId, 'Daily Attendance Update', $message, ['in_app'], 'attendance', 'parent');
$email = (string) ($row['parent_email'] ?? '');
if ($email !== '') {
$body = '<p>'.e($message).'</p>';
$this->emailService->send($email, 'Daily Attendance Update', $body, 'attendance');
}
$sent++;
}
return $sent;
}
}