fix logo circle, start email body
This commit is contained in:
@@ -2,18 +2,20 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ConfigurationModel;
|
||||
use App\Support\Enrollment\DeliberationDecision;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class EnrollmentRegistrationEmailService
|
||||
{
|
||||
public const TEMPLATE_VERSION = 'phase5_consolidated_v2';
|
||||
public const TEMPLATE_VERSION = 'phase5_consolidated_v3';
|
||||
|
||||
public function __construct(
|
||||
private readonly BaseConnection $db,
|
||||
private readonly EnrollmentTransitionService $transitionService,
|
||||
private readonly EmailService $emailService,
|
||||
private readonly ?ConfigurationModel $configurationModel = null,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -151,6 +153,7 @@ final class EnrollmentRegistrationEmailService
|
||||
$opens = $this->dateText($schoolYear['registration_opens_at'] ?? $schoolYear['registration_starts_on'] ?? null);
|
||||
$studentRows = [];
|
||||
$studentIds = [];
|
||||
$hasReEnrollmentEligibleStudent = false;
|
||||
|
||||
foreach ($family['students'] as $student) {
|
||||
$studentId = (int) ($student['id'] ?? 0);
|
||||
@@ -161,18 +164,16 @@ final class EnrollmentRegistrationEmailService
|
||||
$evaluation = $this->transitionService->evaluate($studentId, $previousYear, $schoolYearName, 'parent');
|
||||
$studentRows[] = $this->studentRow($student, $evaluation, $opens, $deadline);
|
||||
$studentIds[] = $studentId;
|
||||
$hasReEnrollmentEligibleStudent = $hasReEnrollmentEligibleStudent || $this->canCompleteParentReEnrollment($evaluation);
|
||||
}
|
||||
|
||||
$financial = $this->financialSection((int) $family['parent_user_id'], $schoolYear, $previousYear);
|
||||
$subject = 'Registration for ' . $schoolYearName . ' Is Now Open';
|
||||
$bodyHtml = '<p>Dear ' . esc($family['name']) . ',</p>'
|
||||
. '<p>Registration for the ' . esc($schoolYearName) . ' school year is now open. Please review the student summary below and complete the portal steps before ' . esc($deadline) . '.</p>'
|
||||
. '<p>Registration for the ' . esc($schoolYearName) . ' school year is now open. Please review the student(s) summary below and complete the portal steps before ' . esc($deadline) . '.</p>'
|
||||
. $this->studentsTable($studentRows)
|
||||
. $financial
|
||||
. '<h3>Registration Steps</h3>'
|
||||
. '<p>Re-enrollment opens on ' . esc($opens) . ' and closes on ' . esc($deadline) . '. Complete re-enrollment for each eligible student before the deadline to secure their enrollment for the upcoming school year.</p>'
|
||||
. '<ol><li>Sign in to the parent portal.</li><li>Review student information and upload any required documents.</li><li>Acknowledge school policies.</li><li>Review tuition, fees, and any carry-over balance.</li><li>Submit Enrollment.</li></ol>'
|
||||
. '<p>Registration portal: <a href="' . esc(site_url('parent/enroll_classes')) . '">' . esc(site_url('parent/enroll_classes')) . '</a></p>'
|
||||
. $this->registrationStepsSection($opens, $deadline, $hasReEnrollmentEligibleStudent)
|
||||
. '<p>For assistance, please contact the school administration.</p>'
|
||||
. '<p>Sincerely,<br>Al Rahma Sunday School<br>School Administration</p>';
|
||||
|
||||
@@ -189,16 +190,32 @@ final class EnrollmentRegistrationEmailService
|
||||
];
|
||||
}
|
||||
|
||||
private function canCompleteParentReEnrollment(array $evaluation): bool
|
||||
{
|
||||
return (bool) ($evaluation['parent_enrollment_allowed'] ?? false);
|
||||
}
|
||||
|
||||
private function registrationStepsSection(string $opens, string $deadline, bool $include): string
|
||||
{
|
||||
if (! $include) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '<h3>Re-enrollment Steps</h3>'
|
||||
. '<p>Re-enrollment opens on ' . esc($opens) . ' and closes on ' . esc($deadline) . '. Complete re-enrollment for each eligible student before the deadline to secure their enrollment for the upcoming school year.</p>'
|
||||
. '<ol><li>Sign in to the parent portal.</li><li>Review/update student and contact information.</li><li>Acknowledge school policies.</li><li>Review tuition, fees and any carry-over balance.</li><li>Submit Enrollment.</li></ol>'
|
||||
. '<p>Registration portal: <a href="' . esc(site_url('parent/enroll_classes')) . '">' . esc(site_url('parent/enroll_classes')) . '</a></p>';
|
||||
}
|
||||
|
||||
private function studentsTable(array $studentRows): string
|
||||
{
|
||||
if ($studentRows === []) {
|
||||
return '<p>No eligible linked students were found for this email.</p>';
|
||||
}
|
||||
|
||||
return '<table style="width:100%; border-collapse:collapse; margin:12px 0 18px; font-size:14px;">'
|
||||
. '<tbody>'
|
||||
return '<div style="margin:12px 0 18px;">'
|
||||
. implode('', $studentRows)
|
||||
. '</tbody></table>';
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
private function studentRow(array $student, array $evaluation, string $opens, string $deadline): string
|
||||
@@ -207,17 +224,52 @@ final class EnrollmentRegistrationEmailService
|
||||
$decision = DeliberationDecision::display((string) ($evaluation['deliberation_decision'] ?? ''));
|
||||
$status = $this->registrationStatus($evaluation);
|
||||
$placement = $this->placementText($evaluation);
|
||||
$requiredAction = $this->requiredAction($evaluation, $deadline);
|
||||
$requiredAction = $this->requiredAction($evaluation, $deadline, $name);
|
||||
$message = $this->decisionMessage($name, $evaluation, $opens, $deadline);
|
||||
$nextStepHtml = $this->decisionMessageHtml($message, (string) ($evaluation['deliberation_decision'] ?? ''));
|
||||
if ($requiredAction !== '') {
|
||||
$nextStepHtml .= '<br><strong>' . esc($requiredAction) . '</strong>';
|
||||
}
|
||||
|
||||
return '<table role="presentation" cellpadding="0" cellspacing="0" style="width:100%; border:1px solid #d9e2ec; border-collapse:collapse; margin:0 0 12px; font-size:14px; line-height:1.45;">'
|
||||
. '<tbody>'
|
||||
. '<tr>'
|
||||
. '<td style="background:#f4f8fb; border-bottom:1px solid #d9e2ec; padding:10px 12px; vertical-align:top; word-break:break-word;">'
|
||||
. '<strong style="font-size:16px; color:#1f2937;">' . esc($name) . '</strong>'
|
||||
. '</td>'
|
||||
. '</tr>'
|
||||
. $this->studentDetailRow('Decision', esc($decision ?: 'Pending'))
|
||||
. $this->studentDetailRow('Registration Status', '<strong>' . esc($status) . '</strong><br>' . esc($placement))
|
||||
. $this->studentDetailRow('Next Step', $nextStepHtml)
|
||||
. '</tbody></table>';
|
||||
}
|
||||
|
||||
private function studentDetailRow(string $label, string $valueHtml): string
|
||||
{
|
||||
return '<tr>'
|
||||
. '<td style="border:1px solid #ddd; padding:8px; vertical-align:top;">' . esc($name) . '</td>'
|
||||
. '<td style="border:1px solid #ddd; padding:8px; vertical-align:top;">' . esc($decision ?: 'Pending') . '</td>'
|
||||
. '<td style="border:1px solid #ddd; padding:8px; vertical-align:top;"><strong>' . esc($status) . '</strong><br>' . esc($placement) . '</td>'
|
||||
. '<td style="border:1px solid #ddd; padding:8px; vertical-align:top;">' . esc($message) . '<br><strong>' . esc($requiredAction) . '</strong></td>'
|
||||
. '<td style="border-bottom:1px solid #edf2f7; padding:10px 12px; vertical-align:top; word-break:break-word;">'
|
||||
. '<div style="font-size:12px; line-height:1.3; color:#64748b; text-transform:uppercase; font-weight:bold; margin:0 0 4px;">' . esc($label) . '</div>'
|
||||
. '<div style="color:#1f2937;">' . $valueHtml . '</div>'
|
||||
. '</td>'
|
||||
. '</tr>';
|
||||
}
|
||||
|
||||
private function decisionMessageHtml(string $message, string $decision): string
|
||||
{
|
||||
if ($decision !== DeliberationDecision::MAKE_UP_EXAM) {
|
||||
return nl2br(esc($message), false);
|
||||
}
|
||||
|
||||
$lines = explode("\n", $message);
|
||||
$lastIndex = count($lines) - 1;
|
||||
foreach ($lines as $index => $line) {
|
||||
$escaped = esc($line);
|
||||
$lines[$index] = $index === $lastIndex ? '<strong>' . $escaped . '</strong>' : $escaped;
|
||||
}
|
||||
|
||||
return implode('<br>', $lines);
|
||||
}
|
||||
|
||||
private function decisionMessage(string $name, array $evaluation, string $opens, string $deadline): string
|
||||
{
|
||||
if ((string) ($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::PASSED) {
|
||||
@@ -231,12 +283,29 @@ final class EnrollmentRegistrationEmailService
|
||||
}
|
||||
|
||||
return match ((string) ($evaluation['deliberation_decision'] ?? '')) {
|
||||
DeliberationDecision::REPEAT_CLASS => 'The deliberation decision for ' . $name . ' is to repeat the current grade. After registration is completed, the student will remain in the same grade and class when available.',
|
||||
DeliberationDecision::MAKE_UP_EXAM => 'The deliberation decision for ' . $name . ' is pending the result of a make-up exam. Registration may be completed now. The student will initially remain in the same grade.',
|
||||
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.'
|
||||
. "\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
|
||||
{
|
||||
$raw = trim((string) (($this->configurationModel ?? new ConfigurationModel())->getConfig('make-up-exam') ?? ''));
|
||||
if ($raw === '') {
|
||||
return 'a date to be announced';
|
||||
}
|
||||
|
||||
$timestamp = strtotime($raw);
|
||||
if ($timestamp !== false) {
|
||||
return date('m-d-Y', $timestamp);
|
||||
}
|
||||
|
||||
return $raw;
|
||||
}
|
||||
|
||||
private function financialSection(int $parentId, array $schoolYear, ?string $previousYear): string
|
||||
{
|
||||
$carry = $previousYear !== null ? $this->invoiceBalance($parentId, $previousYear) : 0.0;
|
||||
@@ -250,14 +319,11 @@ final class EnrollmentRegistrationEmailService
|
||||
|
||||
$message = trim((string) ($schoolYear['financial_policy_message'] ?? ''));
|
||||
if ($message === '') {
|
||||
$message = 'The balance is shown for information and does not currently block registration.';
|
||||
$message = 'The balance needs to be settled with the school before the re-enrollment process can be started.';
|
||||
}
|
||||
|
||||
return '<h3>Family Account Information</h3>'
|
||||
. '<p><strong>Carry-over balance:</strong> $' . number_format($carry, 2) . '<br>'
|
||||
. '<strong>Registration fee:</strong> $' . number_format($registrationFee, 2) . '<br>'
|
||||
. '<strong>New-year tuition due now:</strong> $' . number_format($tuition, 2) . '<br>'
|
||||
. '<strong>Mandatory fees:</strong> $' . number_format($mandatory, 2) . '<br>'
|
||||
. '<strong>Total currently due:</strong> $' . number_format($total, 2) . '</p>'
|
||||
. '<p>' . esc($message) . '</p>';
|
||||
}
|
||||
@@ -428,13 +494,13 @@ final class EnrollmentRegistrationEmailService
|
||||
'automatic_distribution_pending' => $this->assignedGradeText($evaluation),
|
||||
'same_class_assigned' => 'Same grade and class',
|
||||
'temporary_same_grade' => 'Same grade initially',
|
||||
'manual_class_required' => 'Same grade - administrative class assignment required',
|
||||
'manual_class_required' => 'Same grade',
|
||||
'exit_required' => 'Completion or exit process required',
|
||||
default => 'Pending',
|
||||
};
|
||||
}
|
||||
|
||||
private function requiredAction(array $evaluation, string $deadline): string
|
||||
private function requiredAction(array $evaluation, string $deadline, string $name = 'The student'): string
|
||||
{
|
||||
if ((string) ($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::PASSED) {
|
||||
return 'Complete re-enrollment before ' . $deadline . '.';
|
||||
@@ -444,7 +510,7 @@ final class EnrollmentRegistrationEmailService
|
||||
return ($evaluation['adult_student'] ?? false) ? 'Student must complete the authorized adult-student process or contact administration.' : 'Contact the school administration.';
|
||||
}
|
||||
return ($evaluation['deliberation_decision'] ?? '') === DeliberationDecision::MAKE_UP_EXAM
|
||||
? 'Complete re-enrollment and follow the school instructions regarding the make-up exam.'
|
||||
? ''
|
||||
: 'Complete re-enrollment before ' . $deadline . '.';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user