Files
alrahma_sunday_school_api/app/Services/School/EnrollmentEventService.php
T
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

429 lines
15 KiB
PHP

<?php
namespace App\Services\School;
use App\Services\ApplicationUrlService;
use App\Services\EmailService;
use App\Services\Notifications\UserNotificationDispatchService;
use Illuminate\Support\Facades\Log;
class EnrollmentEventService
{
private ApplicationUrlService $urls;
public function __construct(
private EmailService $emailService,
private UserNotificationDispatchService $notifier,
?ApplicationUrlService $urls = null,
) {
$this->urls = $urls ?? app(ApplicationUrlService::class);
}
public function admissionUnderReview(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameData($students, $parentData);
$emailData = [
'parentName' => $parentName,
'studentName' => $studentName,
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Admission Application Under Review',
];
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Admission Under Review',
'Your admission application is under review. We will notify you once it is approved.',
'registration'
);
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Admission Application Under Review',
$this->renderEmail('emails/status_admission_review', $emailData, 'Admission Application Under Review'),
'registration'
);
}
public function paymentPending(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameSentence($students, $parentData['student_name'] ?? 'your student');
$emailData = [
'parentName' => $parentName,
'studentName' => $studentName,
'amountDue' => $parentData['amount'] ?? '',
'dueDate' => $parentData['due_date'] ?? '',
'portalLink' => $parentData['paymentLink'] ?? ($parentData['portalLink'] ?? $this->urls->webLoginUrl()),
'title' => 'Admission Decision',
];
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Payment Pending',
'Your payment is pending. Please check your email for details.',
'payment'
);
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Admission Decision',
$this->renderEmail('emails/status_payment_pending', $emailData, 'Admission Decision'),
'payment'
);
}
public function studentEnrolled(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentsDetails = $this->studentDetails($students);
$studentNameData = $this->studentNameData($students, $parentData);
$first = $studentsDetails[0] ?? [];
$emailData = [
'parentName' => $parentName,
'studentName' => $parentData['student_name'] ?? $studentNameData,
'schoolYear' => $parentData['school_year'] ?? date('Y'),
'studentId' => $parentData['student_id'] ?? ($first['studentId'] ?? ''),
'gradeLevel' => $parentData['grade_level'] ?? ($first['gradeLevel'] ?? ''),
'teacherName' => $parentData['teacher_name'] ?? ($first['teacherName'] ?? ''),
'startDate' => $parentData['start_date'] ?? ($first['startDate'] ?? ''),
'students' => count($studentsDetails) > 1 ? $studentsDetails : null,
'portalLink' => $this->urls->webLoginUrl(),
'title' => 'Enrollment Confirmation',
];
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Enrollment Confirmed',
'Enrollment confirmed. Please check your email for details.',
'registration'
);
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Enrollment Confirmation',
$this->renderEmail('emails/status_enrolled', $emailData, 'Enrollment Confirmation'),
'registration'
);
}
public function withdrawUnderReview(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameData($students, $parentData);
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Withdrawal Request Received',
'Your withdrawal request is under review. Please check your email for details.',
'registration'
);
$emailData = [
'parentName' => $parentName,
'studentName' => $parentData['student_name'] ?? $studentName,
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Withdrawal Under Review',
];
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Withdrawal Request Under Review',
$this->renderEmail('emails/status_withdraw_review', $emailData, 'Withdrawal Request Under Review'),
'registration'
);
}
public function refundPending(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameData($students, $parentData);
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Refund Pending',
'A refund is being processed. Please check your email for details.',
'payment'
);
$emailData = [
'parentName' => $parentName,
'studentName' => $studentName,
'refundAmount' => $parentData['amount'] ?? '',
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Refund Pending',
];
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Refund Pending',
$this->renderEmail('emails/status_refund_pending', $emailData, 'Refund Pending'),
'payment'
);
}
public function withdrawn(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameData($students, $parentData);
$withdrawals = $this->withdrawalsList($students);
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Withdrawal Confirmed',
'Your withdrawal has been completed. Please check your email for details.',
'registration'
);
$emailData = [
'parentName' => $parentName,
'studentName' => $studentName,
'withdrawalDate' => $parentData['withdrawal_date'] ?? ($parentData['date'] ?? ''),
'withdrawals' => ! empty($withdrawals) ? $withdrawals : null,
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Withdrawal Confirmed',
];
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Withdrawal Confirmed',
$this->renderEmail('emails/status_withdrawn', $emailData, 'Withdrawal Confirmed'),
'registration'
);
}
public function denied(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameData($students, $parentData);
$studentsWithReasons = $this->studentsWithReasons($students);
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Admission Decision',
'We\'ve emailed you an update regarding your admission decision.',
'registration'
);
$emailData = [
'parentName' => $parentName,
'studentName' => $studentName,
'students' => $studentsWithReasons ?: null,
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Admission Decision',
];
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Admission Decision',
$this->renderEmail('emails/status_denied', $emailData, 'Admission Decision'),
'registration'
);
}
public function waitlist(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$studentName = $this->studentNameData($students, $parentData);
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Waitlist Update',
'Your application is currently on the waitlist. Please check your email for details.',
'registration'
);
$emailData = [
'parentName' => $parentName,
'studentName' => $studentName,
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Waitlist Update',
];
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Admission Decision',
$this->renderEmail('emails/status_waitlist', $emailData, 'Admission Decision'),
'registration'
);
}
public function enrollmentStatusChanged(array $parentData, array $students): array
{
$parentName = $this->parentName($parentData);
$emailData = [
'parentName' => $parentName,
'schoolYear' => $parentData['school_year'] ?? '',
'changes' => $parentData['changes'] ?? [],
'portalLink' => $parentData['portalLink'] ?? $this->urls->webLoginUrl(),
'title' => 'Enrollment Status Update',
];
$summaryCount = count($emailData['changes']);
$this->notifyParent(
(int) ($parentData['user_id'] ?? 0),
'Enrollment Status Updated',
"Enrollment status updated for {$summaryCount} student(s). Check your email for details.",
'registration'
);
return $this->sendEmail(
(string) ($parentData['email'] ?? ''),
'Enrollment Status Update',
$this->renderEmail('emails/status_enrollment_batch', $emailData, 'Enrollment Status Update'),
'registration'
);
}
private function parentName(array $parentData): string
{
return trim((string) ($parentData['firstname'] ?? '').' '.(string) ($parentData['lastname'] ?? ''));
}
private function studentNameData(array $studentdata, array $parentData)
{
$names = [];
foreach ($studentdata as $s) {
$nm = ! empty($s['name'])
? trim((string) $s['name'])
: trim((string) ($s['firstname'] ?? '').' '.(string) ($s['lastname'] ?? ''));
if ($nm !== '') {
$names[] = $nm;
}
}
if (empty($names)) {
return $parentData['student_name'] ?? 'your student';
}
if (count($names) === 1) {
return $names[0];
}
return $names;
}
private function studentNameSentence(array $studentdata, string $fallback): string
{
$names = [];
foreach ($studentdata as $s) {
$nm = ! empty($s['name'])
? trim((string) $s['name'])
: trim((string) ($s['firstname'] ?? '').' '.(string) ($s['lastname'] ?? ''));
if ($nm !== '') {
$names[] = $nm;
}
}
if (count($names) === 0) {
return $fallback;
}
if (count($names) === 1) {
return $names[0];
}
if (count($names) === 2) {
return $names[0].' and '.$names[1];
}
$last = array_pop($names);
return implode(', ', $names).', and '.$last;
}
private function studentDetails(array $studentdata): array
{
$details = [];
foreach ($studentdata as $s) {
$nm = ! empty($s['name'])
? trim((string) $s['name'])
: trim((string) ($s['firstname'] ?? '').' '.(string) ($s['lastname'] ?? ''));
if ($nm === '') {
continue;
}
$details[] = [
'name' => $nm,
'studentId' => $s['student_id'] ?? $s['id'] ?? '',
'gradeLevel' => $s['grade_level'] ?? $s['grade'] ?? '',
'teacherName' => $s['teacher_name'] ?? $s['teacher'] ?? '',
'startDate' => $s['start_date'] ?? '',
];
}
return $details;
}
private function withdrawalsList(array $studentdata): array
{
$withdrawals = [];
foreach ($studentdata as $s) {
$nm = ! empty($s['name'])
? trim((string) $s['name'])
: trim((string) ($s['firstname'] ?? '').' '.(string) ($s['lastname'] ?? ''));
if ($nm === '') {
continue;
}
$wd = $s['withdrawal_date'] ?? $s['date'] ?? null;
if ($wd) {
$withdrawals[] = [
'name' => $nm,
'withdrawalDate' => $wd,
];
}
}
return $withdrawals;
}
private function studentsWithReasons(array $studentdata): array
{
$rows = [];
foreach ($studentdata as $s) {
$nm = ! empty($s['name'])
? trim((string) $s['name'])
: trim((string) ($s['firstname'] ?? '').' '.(string) ($s['lastname'] ?? ''));
if ($nm === '') {
continue;
}
$rows[] = [
'name' => $nm,
'reason' => $s['reason'] ?? null,
];
}
return $rows;
}
private function notifyParent(int $userId, string $title, string $message, string $topic): void
{
if ($userId <= 0) {
return;
}
$this->notifier->notifyUser($userId, $title, $message, ['in_app'], $topic, 'parent');
}
private function sendEmail(string $to, string $subject, string $html, string $fromKey): array
{
if ($to === '') {
Log::warning('Enrollment event: missing recipient email', ['subject' => $subject]);
return ['ok' => false, 'message' => 'Missing recipient email.'];
}
$ok = $this->emailService->send($to, $subject, $html, $fromKey);
if (! $ok) {
Log::error('Enrollment event email failed', ['to' => $to, 'subject' => $subject]);
}
return ['ok' => $ok];
}
private function renderEmail(string $viewName, array $data, string $fallbackTitle): string
{
Log::debug('Skipping Blade email template', ['view' => $viewName]);
return '<p>'.e($fallbackTitle).'</p>';
}
}