add test batches

This commit is contained in:
root
2026-06-08 23:45:55 -04:00
parent c792b8be05
commit 8d4d610b82
1480 changed files with 22587 additions and 10762 deletions
@@ -101,28 +101,28 @@ class SchoolCalendarFormatterService
$parentName = (string) ($row['parent_name'] ?? 'Parent');
$studentName = (string) ($row['student_name'] ?? 'Student');
$time = trim((string) ($row['time'] ?? ''));
$timeLabel = $time !== '' ? (' '.$time) : '';
$timeLabel = $time !== '' ? (' ' . $time) : '';
$title = $audience === 'admin' ? 'Admin Meeting' : 'Parent Meeting';
$descParts = [];
$descParts[] = 'Student: '.$studentName;
$descParts[] = 'Parent: '.$parentName;
if (! empty($row['class_section_name'])) {
$descParts[] = 'Section: '.$row['class_section_name'];
$descParts[] = 'Student: ' . $studentName;
$descParts[] = 'Parent: ' . $parentName;
if (!empty($row['class_section_name'])) {
$descParts[] = 'Section: ' . $row['class_section_name'];
}
$descParts[] = 'Date/Time: '.($row['date'] ?? '').$timeLabel;
if (! empty($row['notes'])) {
$descParts[] = 'Notes: '.$row['notes'];
$descParts[] = 'Date/Time: ' . ($row['date'] ?? '') . $timeLabel;
if (!empty($row['notes'])) {
$descParts[] = 'Notes: ' . $row['notes'];
}
$start = (string) ($row['date'] ?? '');
if ($start !== '' && $time !== '') {
$start = $start.'T'.$time;
$start = $start . 'T' . $time;
}
return [
'id' => 'pm-'.(int) ($row['id'] ?? 0),
'id' => 'pm-' . (int) ($row['id'] ?? 0),
'title' => $title,
'start' => $start,
'description' => implode("\n", $descParts),
@@ -23,7 +23,7 @@ class SchoolCalendarMeetingService
if ($audience === 'parent' && $parentUserId) {
$studentIds = $this->getStudentIdsForParent($parentUserId);
if (! empty($studentIds)) {
if (!empty($studentIds)) {
$builder->where(function (Builder $q) use ($parentUserId, $studentIds) {
$q->where('parent_user_id', $parentUserId)
->orWhereIn('student_id', $studentIds);
@@ -34,7 +34,7 @@ class SchoolCalendarMeetingService
}
$rows = $builder->orderBy('date', 'ASC')->get()->toArray();
if (! empty($rows)) {
if (!empty($rows)) {
return $rows;
}
@@ -48,7 +48,7 @@ class SchoolCalendarMeetingService
if ($audience === 'parent' && $parentUserId) {
$studentIds = $this->getStudentIdsForParent($parentUserId);
if (! empty($studentIds)) {
if (!empty($studentIds)) {
$fallback->where(function (Builder $q) use ($parentUserId, $studentIds) {
$q->where('parent_user_id', $parentUserId)
->orWhereIn('student_id', $studentIds);
@@ -11,7 +11,8 @@ class SchoolCalendarMutationService
public function __construct(
private SchoolCalendarContextService $context,
private SchoolCalendarNotificationService $notificationService
) {}
) {
}
public function create(array $payload, array $targets = []): array
{
@@ -22,7 +23,7 @@ class SchoolCalendarMutationService
return CalendarEvent::query()->create($data);
});
} catch (\Throwable $e) {
Log::error('SchoolCalendar create failed: '.$e->getMessage());
Log::error('SchoolCalendar create failed: ' . $e->getMessage());
throw $e;
}
@@ -44,7 +45,7 @@ class SchoolCalendarMutationService
$event->save();
});
} catch (\Throwable $e) {
Log::error('SchoolCalendar update failed: '.$e->getMessage());
Log::error('SchoolCalendar update failed: ' . $e->getMessage());
throw $e;
}
@@ -64,7 +65,7 @@ class SchoolCalendarMutationService
$event->delete();
});
} catch (\Throwable $e) {
Log::error('SchoolCalendar delete failed: '.$e->getMessage());
Log::error('SchoolCalendar delete failed: ' . $e->getMessage());
throw $e;
}
}
@@ -76,15 +77,15 @@ class SchoolCalendarMutationService
'description' => $payload['description'] ?? null,
'event_type' => $payload['event_type'] ?? null,
'date' => $payload['date'] ?? $payload['start'] ?? null,
'notify_parent' => ! empty($payload['notify_parent']) ? 1 : 0,
'notify_teacher' => ! empty($payload['notify_teacher']) ? 1 : 0,
'notify_admin' => ! empty($payload['notify_admin']) ? 1 : 0,
'no_school' => ! empty($payload['no_school']) ? 1 : 0,
'notify_parent' => !empty($payload['notify_parent']) ? 1 : 0,
'notify_teacher' => !empty($payload['notify_teacher']) ? 1 : 0,
'notify_admin' => !empty($payload['notify_admin']) ? 1 : 0,
'no_school' => !empty($payload['no_school']) ? 1 : 0,
'school_year' => $payload['school_year'] ?? $this->context->defaultSchoolYear(),
'semester' => $payload['semester'] ?? $this->context->defaultSemester(),
];
if (! CalendarEvent::supportsEventType()) {
if (!CalendarEvent::supportsEventType()) {
unset($data['event_type']);
}
@@ -13,7 +13,8 @@ class SchoolCalendarNotificationService
public function __construct(
private EmailService $emailService,
private ApplicationUrlService $urls,
) {}
) {
}
public function notify(array $event, array $targets): array
{
@@ -26,7 +27,7 @@ class SchoolCalendarNotificationService
$results = [];
foreach ($targets as $group => $enabled) {
if (! $enabled) {
if (!$enabled) {
continue;
}
@@ -34,13 +35,12 @@ class SchoolCalendarNotificationService
if (empty($emails)) {
Log::warning("SchoolCalendar: no recipient emails for {$group}.");
$results[$group] = null;
continue;
}
$to = $emails[0] ?? '';
$ok = $this->emailService->send($to, $subject, $body, 'general', [], $emails);
if (! $ok) {
if (!$ok) {
Log::warning("SchoolCalendar: failed to send calendar notification to {$group}.");
}
$results[$group] = $ok;
@@ -52,9 +52,8 @@ class SchoolCalendarNotificationService
private function buildSubject(array $event): string
{
$title = trim((string) ($event['title'] ?? 'School Calendar Update'));
$typeSegment = ! empty($event['event_type']) ? ' ('.$event['event_type'].')' : '';
return 'School Calendar: '.$title.$typeSegment;
$typeSegment = !empty($event['event_type']) ? ' (' . $event['event_type'] . ')' : '';
return 'School Calendar: ' . $title . $typeSegment;
}
private function buildBody(array $event): string
@@ -64,12 +63,12 @@ class SchoolCalendarNotificationService
$date = (string) ($event['date'] ?? '');
$description = trim((string) ($event['description'] ?? ''));
$body = '<h3>'.e($title).'</h3>';
$body .= '<p><strong>Date:</strong> '.e($date).'</p>';
$body = '<h3>' . e($title) . '</h3>';
$body .= '<p><strong>Date:</strong> ' . e($date) . '</p>';
if ($description !== '') {
$body .= '<p>'.nl2br(e($description)).'</p>';
$body .= '<p>' . nl2br(e($description)) . '</p>';
}
$body .= '<p><a href="'.e($calendarUrl).'">View calendar</a></p>';
$body .= '<p><a href="' . e($calendarUrl) . '">View calendar</a></p>';
return $body;
}
@@ -89,19 +88,18 @@ class SchoolCalendarNotificationService
$emails = [];
foreach ($rows as $row) {
$email = trim((string) ($row['email'] ?? ''));
if ($email === '' || ! filter_var($email, FILTER_VALIDATE_EMAIL)) {
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
continue;
}
$emails[$email] = true;
}
return array_values(array_keys($emails));
}
private function fetchAdminRows(): array
{
$excluded = ['guest', 'teacher', 'teacher_assistant', 'parent'];
$escaped = array_map(static fn ($value) => "'".addslashes($value)."'", $excluded);
$escaped = array_map(static fn ($value) => "'" . addslashes($value) . "'", $excluded);
$excludedList = implode(', ', $escaped);
$builder = DB::table('users as u')
@@ -3,6 +3,7 @@
namespace App\Services\Settings\SchoolCalendar;
use App\Models\CalendarEvent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
class SchoolCalendarQueryService
@@ -35,7 +36,7 @@ class SchoolCalendarQueryService
public function filterEventsForAudience(Collection $events, ?string $audience): Collection
{
$audience = $audience !== null ? strtolower(trim($audience)) : null;
if (! in_array($audience, ['parent', 'teacher', 'admin'], true)) {
if (!in_array($audience, ['parent', 'teacher', 'admin'], true)) {
return $events;
}
@@ -50,7 +51,7 @@ class SchoolCalendarQueryService
return true;
}
if (! $hasAny) {
if (!$hasAny) {
return true;
}