From 103f970110695a97000c409f10cfe5110904d0a0 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 22 Aug 2026 16:55:54 -0400 Subject: [PATCH] fix email body --- .../EnrollmentRegistrationEmailService.php | 24 ++++++++---- ...EnrollmentRegistrationEmailServiceTest.php | 38 +++++++++++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/app/Services/EnrollmentRegistrationEmailService.php b/app/Services/EnrollmentRegistrationEmailService.php index a3467f6..feb16dd 100644 --- a/app/Services/EnrollmentRegistrationEmailService.php +++ b/app/Services/EnrollmentRegistrationEmailService.php @@ -162,7 +162,7 @@ final class EnrollmentRegistrationEmailService } $evaluation = $this->transitionService->evaluate($studentId, $previousYear, $schoolYearName, 'parent'); - $studentRows[] = $this->studentRow($student, $evaluation, $opens, $deadline); + $studentRows[] = $this->studentRow($student, $evaluation, $opens, $deadline, $schoolYear); $studentIds[] = $studentId; $hasReEnrollmentEligibleStudent = $hasReEnrollmentEligibleStudent || $this->canCompleteParentReEnrollment($evaluation); } @@ -218,14 +218,14 @@ final class EnrollmentRegistrationEmailService . ''; } - private function studentRow(array $student, array $evaluation, string $opens, string $deadline): string + private function studentRow(array $student, array $evaluation, string $opens, string $deadline, array $schoolYear = []): string { $name = trim((string) ($student['firstname'] ?? '') . ' ' . (string) ($student['lastname'] ?? '')) ?: 'Student'; $decision = DeliberationDecision::display((string) ($evaluation['deliberation_decision'] ?? '')); $status = $this->registrationStatus($evaluation); $placement = $this->placementText($evaluation); $requiredAction = $this->requiredAction($evaluation, $deadline, $name); - $message = $this->decisionMessage($name, $evaluation, $opens, $deadline); + $message = $this->decisionMessage($name, $evaluation, $opens, $deadline, $schoolYear); $nextStepHtml = $this->decisionMessageHtml($message, (string) ($evaluation['deliberation_decision'] ?? '')); if ($requiredAction !== '') { $nextStepHtml .= '
' . esc($requiredAction) . ''; @@ -270,7 +270,7 @@ final class EnrollmentRegistrationEmailService return implode('
', $lines); } - private function decisionMessage(string $name, array $evaluation, string $opens, string $deadline): string + private function decisionMessage(string $name, array $evaluation, string $opens, string $deadline, array $schoolYear = []): string { if ((string) ($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::PASSED) { $grade = $this->currentGradeText($evaluation); @@ -284,16 +284,26 @@ final class EnrollmentRegistrationEmailService return match ((string) ($evaluation['deliberation_decision'] ?? '')) { DeliberationDecision::REPEAT_CLASS => 'The deliberation decision for ' . $name . ' is to repeat the current grade. After re-enrollment is completed, the student will remain in the same grade.', - DeliberationDecision::MAKE_UP_EXAM => 'The final academic decision for ' . $name . ' is currently pending the result of a make-up exam. This exam is scheduled for ' . $this->makeupExamDateText() . ' from 9:30 AM to 11:00 AM at ISGL.' + DeliberationDecision::MAKE_UP_EXAM => 'The final academic decision for ' . $name . ' is currently pending the result of a make-up exam. This exam is scheduled for ' . $this->makeupExamDateText($schoolYear) . ' from 9:30 AM to 11:00 AM at ISGL.' . "\n" . 'The exam result will determine whether the student advances to the next grade or repeats the current class. Failure to attend the make-up exam will automatically result in the student repeating the class, as no further retake opportunities will be available.' . "\n" . 'You must re-enroll ' . $name . ' before the make-up exam can be taken.', default => 'Please review the registration portal for the current enrollment status.', }; } - private function makeupExamDateText(): string + private function makeupExamDateText(array $schoolYear = []): string { - $raw = trim((string) (($this->configurationModel ?? new ConfigurationModel())->getConfig('make-up-exam') ?? '')); + $raw = trim((string) ($schoolYear['fall_makeup_exam_on'] ?? '')); + if ($raw === '') { + $configModel = $this->configurationModel ?? new ConfigurationModel(); + foreach (['make-up-exam', 'make_up_exam', 'makeup_exam_day'] as $key) { + $raw = trim((string) ($configModel->getConfig($key) ?? '')); + if ($raw !== '') { + break; + } + } + } + if ($raw === '') { return 'a date to be announced'; } diff --git a/tests/app/Services/EnrollmentRegistrationEmailServiceTest.php b/tests/app/Services/EnrollmentRegistrationEmailServiceTest.php index ba6895c..8453727 100644 --- a/tests/app/Services/EnrollmentRegistrationEmailServiceTest.php +++ b/tests/app/Services/EnrollmentRegistrationEmailServiceTest.php @@ -85,6 +85,44 @@ final class EnrollmentRegistrationEmailServiceTest extends TestCase $this->assertSame('', $action); } + public function testMakeupExamDecisionMessageUsesSchoolYearDateBeforeConfig(): void + { + $configModel = $this->createMock(ConfigurationModel::class); + $configModel->expects($this->never())->method('getConfig'); + + $service = $this->service(configModel: $configModel); + + $message = $this->invoke($service, 'decisionMessage', ['Student Name', [ + 'deliberation_decision' => DeliberationDecision::MAKE_UP_EXAM, + 'blockers' => [], + ], 'August 1, 2026', 'August 31, 2026', [ + 'fall_makeup_exam_on' => '2026-09-13', + ]]); + + $this->assertStringContainsString('This exam is scheduled for 09-13-2026 from 9:30 AM to 11:00 AM at ISGL.', $message); + $this->assertStringNotContainsString('a date to be announced', $message); + } + + public function testMakeupExamDecisionMessageFallsBackToSyncedConfigKeys(): void + { + $configModel = $this->createMock(ConfigurationModel::class); + $configModel->expects($this->exactly(2)) + ->method('getConfig') + ->willReturnMap([ + ['make-up-exam', ''], + ['make_up_exam', '2026-09-13'], + ]); + + $service = $this->service(configModel: $configModel); + + $message = $this->invoke($service, 'decisionMessage', ['Student Name', [ + 'deliberation_decision' => DeliberationDecision::MAKE_UP_EXAM, + 'blockers' => [], + ], 'August 1, 2026', 'August 31, 2026']); + + $this->assertStringContainsString('This exam is scheduled for 09-13-2026 from 9:30 AM to 11:00 AM at ISGL.', $message); + } + public function testMakeupExamStudentRowRendersMessageLineBreaks(): void { $configModel = $this->createMock(ConfigurationModel::class);