Your IP : 216.73.217.117


Current Path : /var/www/cesa.co.za/php/includes/
Upload File :
Current File : /var/www/cesa.co.za/php/includes/SchoolAttendees.php

<?php
/*
 * Contact otto@igotafrica.com for details
 */

include_once($_SERVER['DOCUMENT_ROOT'] . '/php/includes/BaseTableClass.php');
include_once($_SERVER['DOCUMENT_ROOT'] . '/php/includes/AnonRespondees.php');
include_once($_SERVER['DOCUMENT_ROOT'] . '/php/includes/SchoolEvents.php');
include_once($_SERVER['DOCUMENT_ROOT'] . '/php/includes/SchoolPayments.php');
include_once($_SERVER['DOCUMENT_ROOT'] . '/php/includes/ErrorLog.php');

/**
 * Control the  SchoolAttendees table
 *
 * @author Otto Saayman
 */
class SchoolAttendees extends BaseTableClass
{

    /** School (SCE) certificate copy / dev test recipient — not CPD (cpdcertificates@). */
    const SCHOOL_CERTIFICATE_DEFAULT_EMAIL = 'blessings@cesa.co.za';

    public function createTableIfNotExists() {
        $createTable = "CREATE TABLE `SchoolAttendees` (
  `AttendeeID` int(11) NOT NULL,
  `ContactTitle` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `ContactFirstName` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `ContactLastName` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `CompanyName` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `AddressLine1` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `AddressLine2` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `AddressLine3` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `City` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `PostalCode` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `PhoneNumber` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `MobileNumber` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `FaxNumber` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `EmailAddress` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `DietaryReq` longtext CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `EventID` int(11) DEFAULT 0,
  `Attended` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT 'y',
  `OrderNum` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `OrgVATNum` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `IDNumber` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `SAACEMemNumber` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `ECSANumber` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `Designation` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `Cancelled` int(11) NOT NULL DEFAULT 0,
  `DateCancelled` datetime DEFAULT NULL,
  `BookingName` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `BookingTel` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `BookingEmail` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `BookingFax` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `DateBooked` datetime DEFAULT NULL,
  `KnownAs` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `Comments` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  `CertificateSent` datetime DEFAULT NULL,
  `CompanyType` varchar(50) DEFAULT NULL,
  `SAICEMember` tinyint(1) DEFAULT 0,
  `SAICEMemNumber` varchar(50) DEFAULT NULL,
  `CESAStaff` tinyint(1) NOT NULL DEFAULT 0,
  `BookingForm` longtext DEFAULT NULL,
  `ResponsiblePayment` varchar(255) DEFAULT NULL,
  `ResponsiblePaymentName` varchar(255) DEFAULT NULL,
  `ResponsiblePaymentCellNo` varchar(255) DEFAULT NULL,
  `ResponsiblePaymentDesignation` varchar(255) DEFAULT NULL,
  `HRManagerName` varchar(255) DEFAULT NULL,
  `HRManagerCellNo` varchar(20) DEFAULT NULL,
  `HRManagerEMail` varchar(255) DEFAULT NULL,
  `MarketingSource` varchar(255) DEFAULT NULL,
  `PackageChosen` varchar(255) DEFAULT NULL,
  `Parking` tinyint(1) NOT NULL DEFAULT 0,
  `DateUpdated` datetime DEFAULT NULL,
  `ProfAssoc` varchar(255) DEFAULT NULL,
  `Province` varchar(255) DEFAULT NULL,
  `Country` varchar(255) DEFAULT NULL,
  `ProfAssocMemNum` varchar(255) DEFAULT NULL,
  `TestCompleted` tinyint(1) NOT NULL DEFAULT 0,
  `TestPassed` tinyint(1) NOT NULL DEFAULT 0,
  `YearsExperience` decimal(10,2) DEFAULT NULL,
  `Subscribed` char(1) DEFAULT NULL,
  `QuizReminderSent` datetime DEFAULT NULL,
  `BlockReminderCertSend` tinyint(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `SchoolAttendees`
--
ALTER TABLE `SchoolAttendees`
  ADD PRIMARY KEY (`AttendeeID`),
  ADD UNIQUE KEY `ContactTitle` (`ContactFirstName`,`ContactLastName`,`PhoneNumber`,`EmailAddress`,`EventID`),
  ADD KEY `EventAttended` (`EventID`,`Attended`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `SchoolAttendees`
--
ALTER TABLE `SchoolAttendees`
  MODIFY `AttendeeID` int(11) NOT NULL AUTO_INCREMENT;";
    }
    
    public function findById($id)
    {

        $sql = "SELECT * FROM SchoolAttendees sa "
            . "INNER JOIN SchoolEvents se ON sa.EventId = se.EventID "
            . "WHERE sa.AttendeeID = " . $this->sqlf->qstr($id);

        //        echo $sql;

        return $this->sqlf->getRow($sql);
    }

    public function findAllIds()
    {
        return $this->sqlf->getAll("SELECT AttendeeID FROM SchoolAttendees "
            . "WHERE EmailAddress IS NOT NULL AND EmailAddress != '' AND EmailAddress NOT LIKE 'no e-mail address%' "
            . "AND Cancelled = 0");
    }

    public function upsert($SchoolAttendees)
    {

        $action = 'INSERT';
        $where = '';

        //        var_dump($SchoolAttendees);
        //        exit;

        if (isset($SchoolAttendees['AttendeeID']) && $SchoolAttendees['AttendeeID'] > 0) {
            $action = 'UPDATE';
            $where = 'AttendeeID = ' . $SchoolAttendees['AttendeeID'];
        }

        if (isset($SchoolAttendees['Cancelled']) && $SchoolAttendees['Cancelled'] > 0) {
            $SchoolAttendees['Attended'] = 'n';
        }

        // var_dump($SchoolAttendees);
        // exit;

        return $this->sqlf->autoExecute('SchoolAttendees', $SchoolAttendees, $action, $where, 'AttendeeID');
    }

    public function findToSendCertificates()
    {

        $findSendCertSQL = "SELECT *, SchoolEvents.Cancelled AS EventCancelled FROM SchoolAttendees "
            . "INNER JOIN SchoolEvents ON SchoolAttendees.EventID = SchoolEvents.EventID "
            . "WHERE SchoolEvents.Cancelled = 0 AND SchoolEvents.EndDate <= NOW() "
            . "AND (SchoolAttendees.CertificateSent IS NULL OR SchoolAttendees.CertificateSent = '' OR SchoolAttendees.CertificateSent = '0000-00-00 00:00:00') "
            . "AND SchoolAttendees.Attended = 'y' "
            . "AND SchoolAttendees.Cancelled = 0 "
            . "AND SchoolEvents.Cancelled = 0 "
            . "AND SchoolEvents.EndDate > '2023-07-01' "
            . "AND (SchoolEvents.TrainerID IS NULL OR SchoolEvents.TrainerID NOT IN (45, 52)) "
            . "AND SchoolAttendees.AttendeeID IN (SELECT AttendeeID FROM SchoolPayments)"
            // . "LIMIT 0, 10"
        ;

        // ErrorLog::logInfo('Selecting attendees for events: ' . $findSendCertSQL);

        // echo $findSendCertSQL . " <br />\r\n";

        return $this->sqlf->getAll($findSendCertSQL);
    }

    public function findByEventId($eventId)
    {
        //        echo "SELECT * FROM SchoolAttendees "
        //        . "INNER JOIN SchoolEvents ON SchoolAttendees.EventID = SchoolEvents.EventID "
        //        . "WHERE SchoolAttendees.EventID = $eventId <br />";
        return $this->sqlf->getAll("SELECT * FROM SchoolAttendees "
            . "INNER JOIN SchoolEvents ON SchoolAttendees.EventID = SchoolEvents.EventID "
            . "WHERE SchoolAttendees.EventID = $eventId");
    }

    public function chooseAttendedPaid($requestVars)
    {

        $attendeeIds = array();

        if (isset($requestVars['AttendeeIDs']) && strlen($requestVars['AttendeeIDs']) > 0) {
            $attendeeIds = json_decode($requestVars['AttendeeIDs'], true);
        }

        if ((isset($requestVars['markAllAsAttendedPaid']) && $requestVars['markAllAsAttendedPaid'] > 0) || (isset($requestVars['markSelectedAsAttendedPaid']) && $requestVars['markSelectedAsAttendedPaid'] > 0)) {
            $this->markAllAsAttendedPaid($requestVars['EventID'], true, true, $attendeeIds);
        } elseif ((isset($requestVars['markAllAsAttended']) && $requestVars['markAllAsAttended'] > 0) || (isset($requestVars['markSelectedAsAttended']) && $requestVars['markSelectedAsAttended'] > 0)) {
            $this->markAllAsAttendedPaid($requestVars['EventID'], true, false, $attendeeIds);
        } elseif ((isset($requestVars['markAllAsPaid']) && $requestVars['markAllAsPaid'] > 0) || (isset($requestVars['markSelectedAsPaid']) && $requestVars['markSelectedAsPaid'] > 0)) {
            $this->markAllAsAttendedPaid($requestVars['EventID'], false, true, $attendeeIds);
        } elseif ((isset($requestVars['markAllAsNotAttendedPaid']) && $requestVars['markAllAsNotAttendedPaid'] > 0) || (isset($requestVars['markSelectedAsNotAttendedPaid']) && $requestVars['markSelectedAsNotAttendedPaid'] > 0)) {
            $this->markAllAsNotAttendedPaid($requestVars['EventID'], true, true, $attendeeIds);
        } elseif ((isset($requestVars['markAllAsNotAttended']) && $requestVars['markAllAsNotAttended'] > 0) || (isset($requestVars['markSelectedAsNotAttended']) && $requestVars['markSelectedAsNotAttended'] > 0)) {
            $this->markAllAsNotAttendedPaid($requestVars['EventID'], true, false, $attendeeIds);
        } elseif ((isset($requestVars['markAllAsNotPaid']) && $requestVars['markAllAsNotPaid'] > 0) || (isset($requestVars['markSelectedAsNotPaid']) && $requestVars['markSelectedAsNotPaid'] > 0)) {
            $this->markAllAsNotAttendedPaid($requestVars['EventID'], false, true, $attendeeIds);
        }
    }

    public function markAllAsAttendedPaid($eventId, $attended = true, $paid = true, $attendeeIds = array(), $unpaid = false)
    {

        global $sqlf;

        $eventAttendees = $this->findByEventId($eventId);
        $marketingPaymentObject = new SchoolPayments($sqlf);

        foreach ($eventAttendees as $eventAttendee) {

            if (count($attendeeIds) > 0 && !in_array($eventAttendee['AttendeeID'], $attendeeIds)) {
                continue;
            }

            if ($attended) {

                $eventAttendee['Attended'] = 'y';

                unset($eventAttendee['EventName']);
                unset($eventAttendee['EventDescription']);
                unset($eventAttendee['Level']);
                unset($eventAttendee['Venue']);
                unset($eventAttendee['StartDate']);
                unset($eventAttendee['EndDate']);
                unset($eventAttendee['StartTime']);
                unset($eventAttendee['EndTime']);
                unset($eventAttendee['AvailableSpaces']);
                unset($eventAttendee['CostPerPerson']);
                unset($eventAttendee['FacilitatorID']);
                unset($eventAttendee['ProviderID']);
                unset($eventAttendee['PresenterID']);
                unset($eventAttendee['Hours']);
                unset($eventAttendee['CPD']);
                unset($eventAttendee['CODE']);
                unset($eventAttendee['NQFLevel']);
                unset($eventAttendee['AccredNum']);
                unset($eventAttendee['RegDeadline']);
                unset($eventAttendee['Category']);
                unset($eventAttendee['Onceoff']);
                unset($eventAttendee['OnceoffSeq']);
                unset($eventAttendee['MemberDiscount']);
                unset($eventAttendee['EarlyBirdDiscount']);
                unset($eventAttendee['EarlyBirdDate']);
                unset($eventAttendee['Cancelled']);
                unset($eventAttendee['BankAccName']);
                unset($eventAttendee['ExternalLink']);
                unset($eventAttendee['SchoolCourseID']);
                unset($eventAttendee['FileAttachment']);
                unset($eventAttendee['WebCategory']);
                unset($eventAttendee['CandidateAcademy']);
                unset($eventAttendee['BookingConfirmed']);
                unset($eventAttendee['AttendanceRegister']);
                unset($eventAttendee['SACPCMPNum']);
                unset($eventAttendee['AccredNum2']);
                unset($eventAttendee['CostPackage']);
                unset($eventAttendee['ContactPerson']);
                unset($eventAttendee['ContactTel']);
                unset($eventAttendee['ContactEmail']);
                unset($eventAttendee['CourseType']);
                unset($eventAttendee['OnlineCourseLink']);
                unset($eventAttendee['QuestionnaireID']);
                unset($eventAttendee['TestRequired']);
                unset($eventAttendee['TrainerID']);
                unset($eventAttendee['AttendanceRegister2']);
                unset($eventAttendee['AttendanceRegister3']);
                unset($eventAttendee['AttendanceRegister4']);
                unset($eventAttendee['AttendanceRegister5']);
                unset($eventAttendee['CopyRegFormTo']);
                unset($eventAttendee['TrainerInvRecv']);
                unset($eventAttendee['ECSACategory']);
                unset($eventAttendee['SACPCMPCategory']);
                unset($eventAttendee['SACPCMP_CPDPoints']);
                unset($eventAttendee['OtherCPDPoints']);
                unset($eventAttendee['SendRegistrationConfirmation']);
                unset($eventAttendee['PilotCourse']);
                unset($eventAttendee['Archived']);
                unset($eventAttendee['CertificateSent']);
                unset($eventAttendee['DateUpdated']);
                unset($eventAttendee['QuizReminderSent']);
                unset($eventAttendee['DateCancelled']);
                unset($eventAttendee['CESAVerificationNumberDates']);
                unset($eventAttendee['SACNASP_ValidationNumber']);
                unset($eventAttendee['SACNASP_CPD_Points']);
                unset($eventAttendee['YearsExperience']);

                $this->sqlf->autoExecute('SchoolAttendees', $eventAttendee, 'UPDATE', 'AttendeeID = ' . $eventAttendee['AttendeeID']);

                $this->sqlf->execute("UPDATE SchoolAttendees SET CertificateSent = NULL WHERE CertificateSent = '0000-00-00'");
                $this->sqlf->execute("UPDATE SchoolAttendees SET QuizReminderSent = NULL WHERE QuizReminderSent = '0000-00-00'");
            }

            if ($paid) {
                $marketingPaymentObject->markPaidByEventAttendeeId($eventAttendee['AttendeeID'], $eventAttendee['CostPerPerson'], $eventAttendee['EventID']);
            } elseif ($unpaid) {
                $marketingPaymentObject->markUnpaidByEventAttendeeId($eventAttendee['AttendeeID'], $eventAttendee['EventID']);
            }

            $this->SchoolAttendeeUpsert($eventAttendee['AttendeeID']);
        } //foreach
    }

    public function markAllAsNotAttendedPaid($eventId, $attended = true, $paid = true, $attendeeIds = array(), $unpaid = false)
    {

        global $sqlf;

        $eventAttendees = $this->findByEventId($eventId);
        $marketingPaymentObject = new SchoolPayments($sqlf);

        foreach ($eventAttendees as $eventAttendee) {

            if (count($attendeeIds) > 0 && !in_array($eventAttendee['AttendeeID'], $attendeeIds)) {
                continue;
            }

            if ($attended) {

                $eventAttendee['Attended'] = 'n';

                unset($eventAttendee['EventName']);
                unset($eventAttendee['EventDescription']);
                unset($eventAttendee['Level']);
                unset($eventAttendee['Venue']);
                unset($eventAttendee['StartDate']);
                unset($eventAttendee['EndDate']);
                unset($eventAttendee['StartTime']);
                unset($eventAttendee['EndTime']);
                unset($eventAttendee['AvailableSpaces']);
                unset($eventAttendee['CostPerPerson']);
                unset($eventAttendee['FacilitatorID']);
                unset($eventAttendee['ProviderID']);
                unset($eventAttendee['PresenterID']);
                unset($eventAttendee['Hours']);
                unset($eventAttendee['CPD']);
                unset($eventAttendee['CODE']);
                unset($eventAttendee['NQFLevel']);
                unset($eventAttendee['AccredNum']);
                unset($eventAttendee['RegDeadline']);
                unset($eventAttendee['Category']);
                unset($eventAttendee['Onceoff']);
                unset($eventAttendee['OnceoffSeq']);
                unset($eventAttendee['MemberDiscount']);
                unset($eventAttendee['EarlyBirdDiscount']);
                unset($eventAttendee['EarlyBirdDate']);
                unset($eventAttendee['Cancelled']);
                unset($eventAttendee['BankAccName']);
                unset($eventAttendee['ExternalLink']);
                unset($eventAttendee['SchoolCourseID']);
                unset($eventAttendee['FileAttachment']);
                unset($eventAttendee['WebCategory']);
                unset($eventAttendee['CandidateAcademy']);
                unset($eventAttendee['BookingConfirmed']);
                unset($eventAttendee['AttendanceRegister']);
                unset($eventAttendee['SACPCMPNum']);
                unset($eventAttendee['AccredNum2']);
                unset($eventAttendee['CostPackage']);
                unset($eventAttendee['ContactPerson']);
                unset($eventAttendee['ContactTel']);
                unset($eventAttendee['ContactEmail']);
                unset($eventAttendee['CourseType']);
                unset($eventAttendee['OnlineCourseLink']);
                unset($eventAttendee['QuestionnaireID']);
                unset($eventAttendee['TestRequired']);
                unset($eventAttendee['TrainerID']);
                unset($eventAttendee['AttendanceRegister2']);
                unset($eventAttendee['AttendanceRegister3']);
                unset($eventAttendee['AttendanceRegister4']);
                unset($eventAttendee['AttendanceRegister5']);
                unset($eventAttendee['CopyRegFormTo']);
                unset($eventAttendee['TrainerInvRecv']);

                unset($eventAttendee['SACPCMPCategory']);
                unset($eventAttendee['SACPCMP_CPDPoints']);
                unset($eventAttendee['OtherCPDPoints']);
                unset($eventAttendee['SendRegistrationConfirmation']);
                unset($eventAttendee['PilotCourse']);
                unset($eventAttendee['Archived']);
                unset($eventAttendee['CertificateSent']);
                unset($eventAttendee['DateUpdated']);
                unset($eventAttendee['QuizReminderSent']);
                unset($eventAttendee['DateCancelled']);

                $this->sqlf->autoExecute('SchoolAttendees', $eventAttendee, 'UPDATE', 'AttendeeID = ' . $eventAttendee['AttendeeID']);

                // $this->sqlf->execute("UPDATE SchoolAttendees SET CertificateSent = NULL WHERE CertificateSent = '0000-00-00'");
                // $this->sqlf->execute("UPDATE SchoolAttendees SET QuizReminderSent = NULL WHERE QuizReminderSent = '0000-00-00'");
            }

            if ($paid) {
                $marketingPaymentObject->markUnpaidByEventAttendeeId($eventAttendee['AttendeeID'], $eventAttendee['EventID']);
            }

            $this->SchoolAttendeeUpsert($eventAttendee['AttendeeID']);
        } //foreach
    }

    function SchoolAttendeeUpsert($attendeeId, $attendeeRow = array())
    {

        global $sqlf;

        // Initialize debug array to collect all debug information
        $debugInfo = [];
        $debugInfo[] = "=== SchoolAttendeeUpsert Debug Log ===";
        $debugInfo[] = "Timestamp: " . date('Y-m-d H:i:s');
        $debugInfo[] = "AttendeeID: " . $attendeeId;
        $hasFailures = false;

        // var_dump($attendeeRow);
        // exit;

        $schoolAttendee = $this->findById($attendeeId);

        // If attendee doesn't exist, return early to prevent creating records without EventID
        if (!$schoolAttendee || !isset($schoolAttendee['EventID']) || empty($schoolAttendee['EventID'])) {
            $debugInfo[] = 'ERROR: Attendee not found or missing EventID. AttendeeID: ' . $attendeeId;
            // ErrorLog::logInfo('SchoolAttendeeUpsert: Attendee not found or missing EventID. AttendeeID: ' . $attendeeId);
            return;
        }

        // Check if DateBooked needs to be set - use $schoolAttendee from database, not $attendeeRow
        if (is_null($schoolAttendee['DateBooked']) || $schoolAttendee['DateBooked'] == '' || $schoolAttendee['DateBooked'] == '0000-00-00 00:00:00') {
            $schoolAttendeeUpdate['AttendeeID'] = $attendeeId; // Use the function parameter, not $attendeeRow
            $schoolAttendeeUpdate['DateBooked'] = date('Y-m-d H:i:s');
            $this->upsert($schoolAttendeeUpdate);
        }

        // var_dump($attendeeRow['Cancelled']);
        // exit;

        if ((isset($attendeeRow['Cancelled']) && !is_null($attendeeRow['Cancelled']) && $attendeeRow['Cancelled'] > 0)
            || (isset($attendeeRow['EventCancelled']) && !is_null($attendeeRow['EventCancelled']) && $attendeeRow['EventCancelled'] > 0)
        ) {
            $schoolAttendeeUpdate['AttendeeID'] = $attendeeId; // Use the function parameter, not $attendeeRow
            $schoolAttendeeUpdate['Attended'] = 'n';
            $schoolAttendee['Attended'] = 'n';
            $this->upsert($schoolAttendeeUpdate);
        }

        $schoolEvents = new SchoolEvents($sqlf);
        $schoolEvent = $schoolEvents->findById($schoolAttendee['EventID']);
        $schoolCourses = new SchoolCourses($sqlf);
        $schoolCourse = $schoolCourses->findById($schoolEvent['SchoolCourseID']);
        $eventEndDate = new DateTime($schoolEvent['EndDate'] . ' ' . $schoolEvent['EndTime']);

        $debugInfo[] = 'Event: ' . $schoolEvent['EventName'] . ' (ID: ' . $schoolEvent['EventID'] . ')';
        $debugInfo[] = 'Course: ' . $schoolCourse['CourseName'] . ' (ID: ' . $schoolCourse['CourseID'] . ')';
        $debugInfo[] = 'Event End Date: ' . $eventEndDate->format('Y-m-d H:i:s');

        if ($eventEndDate->getTimestamp() > time()) {
            // Event not ended yet
            $debugInfo[] = $schoolEvent['EventName'] . ' - Event not ended yet';
            // Email debug information and return
            // self::emailDebugInfo($debugInfo);
            return;
        }

        $dateBooked = new DateTime($schoolAttendee['DateBooked']);

        if ($eventEndDate->getTimestamp() < $dateBooked->getTimestamp()) {
            //Use date booked, because attendee was added after the event
            $eventEndDate = clone $dateBooked;
        }

        $mustSend = 0;
        $sendReminder = false;
        $feedbackCompleted = 0;

        $anonRespondeeObj = new AnonRespondees($this->sqlf);

        // School Feedback Questionnaire is hard coded in /echasl23rptSchoolFeedbackQues.php
        $anonRespondee = $anonRespondeeObj->findBySchoolAttendeeId(225, $schoolAttendee['AttendeeID']);

        if (is_array($anonRespondee) && count($anonRespondee) > 0) {
            $feedbackCompleted = 1;
            $debugInfo[] = 'Feedback found by SchoolAttendeeID';
        } else {
            // Attempt to find feedback by ID number
            $anonRespondee = $anonRespondeeObj->findByIDNumber(225, $schoolAttendee['IDNumber'], $schoolAttendee['EventID']);

            if (is_array($anonRespondee) && count($anonRespondee) > 0) {
                $feedbackCompleted = 1;
                $debugInfo[] = 'Feedback found by ID Number: ' . $schoolAttendee['IDNumber'];

                $anonRespondeeRow = $anonRespondeeObj->find($anonRespondee['Anon_RespondeeID']);

                $anonRespondeeRow['SchoolAttendeeID'] = $schoolAttendee['AttendeeID'];

                $anonRespondeeObj->upsert($anonRespondeeRow);
            } else {
                // Attempt to find feedback by e-mail address
                $anonRespondee = $anonRespondeeObj->findByEMail(225, $schoolAttendee['EmailAddress'], $schoolAttendee['EventID']);

                if (is_array($anonRespondee) && count($anonRespondee) > 0) {
                    $feedbackCompleted = 1;
                    $debugInfo[] = 'Feedback found by Email: ' . $schoolAttendee['EmailAddress'];

                    $anonRespondeeRow = $anonRespondeeObj->find($anonRespondee['Anon_RespondeeID']);

                    $anonRespondeeRow['SchoolAttendeeID'] = $schoolAttendee['AttendeeID'];
    
                    $anonRespondeeObj->upsert($anonRespondeeRow);
                } else
                    // Attempt to find feedback by name and surname
                    $anonRespondee = $anonRespondeeObj->findByNameLastname(225, $schoolAttendee['ContactFirstName'], $schoolAttendee['ContactLastName'], $schoolAttendee['EventID']);

                if (is_array($anonRespondee) && count($anonRespondee) > 0) {
                    $feedbackCompleted = 1;
                    $debugInfo[] = 'Feedback found by Name: ' . $schoolAttendee['ContactFirstName'] . ' ' . $schoolAttendee['ContactLastName'];

                    $anonRespondeeRow = $anonRespondeeObj->find($anonRespondee['Anon_RespondeeID']);

                    $anonRespondeeRow['SchoolAttendeeID'] = $schoolAttendee['AttendeeID'];

                    $anonRespondeeObj->upsert($anonRespondeeRow);
                } else {
                    $debugInfo[] = 'No feedback found for attendee';
                }
            }
        }

        if ($feedbackCompleted > 0) {
            $mustSend = 1;
        }

        if ($mustSend > 0 && $schoolEvent['QuestionnaireID'] > 0 && $schoolAttendee['TestCompleted'] <= 0) {
            //Look for a test completed before the event attendee was added

            $anonRespondeeObj = new AnonRespondees($this->sqlf);

            $anonRespondee = $anonRespondeeObj->findByEMail($schoolEvent['QuestionnaireID'], $schoolAttendee['EmailAddress']);

            if ((!is_array($anonRespondee) || count($anonRespondee) <= 0) && strlen($schoolAttendee['IDNumber']) > 0) {
                $anonRespondee = $anonRespondeeObj->findByIDNumber($schoolEvent['QuestionnaireID'], $schoolAttendee['IDNumber']);
            }

            if ((!is_array($anonRespondee) || count($anonRespondee) <= 0) && strlen($schoolAttendee['ContactFirstName']) > 0 && strlen($schoolAttendee['ContactLastName']) > 0) {
                $anonRespondee = $anonRespondeeObj->findByNameLastname($schoolEvent['QuestionnaireID'], $schoolAttendee['ContactFirstName'], $schoolAttendee['ContactLastName']);
            }

            if (is_array($anonRespondee) && count($anonRespondee) > 0) {

                $debugInfo[] = 'Quiz found for attendee';

                $schoolAttendee['TestPassed'] = 0;
                $schoolAttendee['TestCompleted'] = 1;

                $scorePerc = $anonRespondee['Score'] / $anonRespondee['TotalScore'] * 100;

                if ($scorePerc >= $anonRespondee['PassPerc']) {
                    $schoolAttendee['TestPassed'] = 1;
                    $debugInfo[] = 'Test PASSED - Score: ' . $scorePerc . '% (Required: ' . $anonRespondee['PassPerc'] . '%)';
                } else {
                    $debugInfo[] = 'Test FAILED - Score: ' . $scorePerc . '% (Required: ' . $anonRespondee['PassPerc'] . '%)';
                }

                //                $this->upsert($schoolAttendee);
            } else {
                $debugInfo[] = 'Quiz not found for attendee';
            }

            //            var_dump($anonRespondee);
            //            echo '<br /><br />';
            //            var_dump($schoolAttendee['DateBooked']);
            //            echo '<br /><br />';
        }
        //        exit;

        if (
            $mustSend > 0
            && $schoolEvent['TestRequired'] > 0
            && $schoolEvent['QuestionnaireID'] > 0
            && $schoolCourse['NonCPDCourse'] <= 0
            && $schoolEvent['CPD'] > 0
        ) {
            // Only check for test passed if it's a CPD event

            $mustSend = $schoolAttendee['TestPassed'];
            $oneWeeksOn = clone $eventEndDate;
            $oneWeeksOn->modify('+1 weeks');

            // echo $oneWeeksOn->format('Y-m-d H:i:s') . ': One week on<br />';

            if ($mustSend <= 0 && $oneWeeksOn->getTimestamp() <= time()) {
                // Test not passed, but one week has passed
                $mustSend = 1;
            }
        } elseif ($feedbackCompleted > 0 && $schoolEvent['TestRequired'] <= 0) {
            $mustSend = 1;
        }

        if ($schoolAttendee['BlockReminderCertSend'] > 0) {
            $debugInfo[] = $schoolEvent['EventName'] . ' - ' . $schoolAttendee['ContactFirstName'] . ' '
                . $schoolAttendee['ContactLastName'] . ' - '
                . 'Sending of Certificates BLOCKED';
            // Email debug information and return
            // self::emailDebugInfo($debugInfo);
            return;
        }

        if (
            $mustSend > 0 && ($schoolAttendee['CertificateSent'] == '' || $schoolAttendee['CertificateSent'] == '0000-00-00 00:00:00') &&
            $schoolAttendee['Attended'] == 'y'
        ) {

            $debugInfo[] = $schoolEvent['EventName'] . ' - ' . $schoolAttendee['ContactFirstName'] . ' ' . $schoolAttendee['ContactLastName'] . ' - '
                . 'Checking for payment';

            $schoolPayments = new SchoolPayments($sqlf);

            if ($schoolPayments->isPaid($schoolAttendee['AttendeeID'])) {

                $AttendeeID = $schoolAttendee["AttendeeID"];
                $EmailAddress = $schoolAttendee["EmailAddress"];
                $ContactFirstName = $schoolAttendee["ContactFirstName"];
                $ContactLastName = $schoolAttendee["ContactLastName"];
                $BookingEmail = $schoolAttendee["BookingEmail"];

                include($_SERVER['DOCUMENT_ROOT'] . "/echasl23/inc_gencertificate.php");

                $schoolEvent['AttendeeName'] = $schoolAttendee['ContactFirstName'];

                $mailData = array(
                    'NumMessages' => 1,
                    'AttendeeID1' => $schoolAttendee['AttendeeID'],
                    'Email1' => $schoolAttendee['EmailAddress'],
                    'Name1' => $schoolAttendee['ContactFirstName'],
                    'EmailMessage' => SchoolAttendees::getSendCertificateBody($schoolAttendee['TestPassed'], $schoolEvent, $schoolCourse),
                    'EventName' => $schoolEvent['EventName'],
                    'File1' => $sFilename,
                    'EventDate1' => $eventEndDate->format('Y-m-d'),
                );

                $debugInfo[] = $eventEndDate->format('Y-m-d') . ',"' . $schoolEvent['EventName'] . '",' . $schoolAttendee["EmailAddress"] . ',Sending certificate';
                $this->sendAttendeeCertificates($mailData);
                $sendReminder = false;
            } else {
                $debugInfo[] = $schoolEvent['EventName'] . ' - ' . $schoolAttendee['ContactFirstName'] . ' ' . $schoolAttendee['ContactLastName'] . ' - '
                    . 'Not paid';
                $debugInfo[] = $eventEndDate->format('Y-m-d') . ',"' . $schoolEvent['EventName'] . '",' . $schoolAttendee["EmailAddress"] . ',Not paid';
                $sendReminder = true;
            }
            //            exit;
        } else {
            $debugInfo[] = $eventEndDate->format('Y-m-d') . ' - ' . $schoolAttendee['ContactFirstName'] . ' ' . $schoolAttendee['ContactLastName']
                . ',"' . $schoolEvent['EventName'] . '",' . $schoolAttendee["EmailAddress"]
                . ',Event not attended, not test complete, not feedback completed, or certificate sent';
        }

        $threeDaysOn = clone $eventEndDate;
        $threeDaysOn->modify('+2 days');

        $debugInfo[] = 'Check send reminder: ' . $threeDaysOn->format('Y-m-d H:i:s');

        if (
            ($schoolAttendee['QuizReminderSent'] == '' || $schoolAttendee['QuizReminderSent'] == '0000-00-00 00:00:00')
            && $sendReminder
            && $threeDaysOn->getTimestamp() < time()
            && $schoolAttendee['Attended'] == 'y'
        ) {

            $hasCPD = false;

            $schoolPayments = new SchoolPayments($sqlf);
            $reminderBody = "Thank you for your attendance of " . $schoolEvent['EventName'] . " which took place on " . SchoolEvents::getEventDatesString($schoolEvent) . ".\r\n\r\n";

            if ($schoolEvent['CPD'] > 0) {
                $hasCPD = true;
                // $reminderBody .= "This is a gentle reminder that the following is still outstanding.  There is no time limit for completing the outstanding task(s); however, "
                //     . "we will be unable to provide you with a CPD certificate until these are completed.\r\n\r\n";
            } else {
                // $reminderBody .= "This is a gentle reminder that the following is still outstanding.  There is no time limit for completing the outstanding task(s); however, "
                //     . "we will be unable to provide you with a certificate until these are completed.\r\n\r\n";
            }

            $hasOutstandingItems = false;
            $feedbackLink = '';
            $courseQuizRequired = false;
            $paymentRequired = false;

            if ($feedbackCompleted <= 0) {
                // $reminderBody .= "- Feedback questionnaire: https://www.cesa.co.za/questionnaire.php?qid=225&attendeeId="
                //     . $schoolAttendee['AttendeeID'] . '&chk=' . md5($schoolAttendee['AttendeeID'])
                //     . '&id=' . $schoolEvent['EventID'] . "\r\n";
                $feedbackLink = 'https://www.cesa.co.za/questionnaire.php?qid=225&attendeeId='
                    . $schoolAttendee['AttendeeID'] . '&chk=' . md5($schoolAttendee['AttendeeID'])
                    . '&id=' . $schoolEvent['EventID'];
                $hasOutstandingItems = true;
            }

            if ($schoolEvent['TestRequired'] > 0 && $schoolEvent['QuestionnaireID'] > 0 && $schoolAttendee['TestPassed'] <= 0) {
                // $reminderBody .= "- Course quiz\r\n";
                $courseQuizRequired = true;
                $hasOutstandingItems = true;
            }

            if (!$schoolPayments->isPaid($schoolAttendee['AttendeeID'])) {
                // $reminderBody .= "- Payment\r\n";
                $hasOutstandingItems = true;
                $paymentRequired = true;
            }

            // Only send the reminder if there are actually outstanding items
            if ($hasOutstandingItems) {

                $hasFeedback = strlen($feedbackLink) > 0;
                $tasks = [];
                if ($courseQuizRequired) {
                    $tasks[] = 'complete the Course Quiz';
                }
                if ($paymentRequired) {
                    $tasks[] = 'make payment';
                }
                if ($hasFeedback) {
                    $tasks[] = 'complete the Feedback Questionnaire';
                }
                $taskList = count($tasks) === 1
                    ? $tasks[0]
                    : (count($tasks) === 2
                        ? $tasks[0] . ' and ' . $tasks[1]
                        : implode(', ', array_slice($tasks, 0, -1)) . ', and ' . $tasks[count($tasks) - 1]);
                $certType = $hasCPD ? 'a CPD certificate' : 'a certificate';
                $reminderBody .= "This is a gentle reminder that you need to {$taskList} for this course.  "
                    . "There is no time limit for doing this, however, "
                    . "we will be unable to provide you with {$certType} until these are completed.\r\n\r\n";

                $reminderBody .= "If the above information is incorrect or you require further information, please contact Blessings Banda on Blessings@cesa.co.za / "
                    . "+27 (0) 73 422 0680 or both on +27 (0)11 463-2022.";

                $mailData = array(
                    'NumMessages' => 1,
                    'AttendeeID1' => $schoolAttendee['AttendeeID'],
                    'Email1' => $schoolAttendee['EmailAddress'],
                    'Name1' => $schoolAttendee['ContactFirstName'],
                    'EmailMessage' => $reminderBody,
                    'EventName' => $schoolEvent['EventName'],
                    'EventDate1' => $eventEndDate->format('Y-m-d'),
                    'subject' => 'SCE Event Reminder ',
                );

                $this->sendAttendeeCertificates($mailData);
                $debugInfo[] = $eventEndDate->format('Y-m-d') . ',"' . $schoolEvent['EventName'] . '",' . $schoolAttendee["EmailAddress"] . ',reminder sent';
            } else {
                // Debug: Log when reminder is not sent due to no outstanding items
                $debugInfo[] = $eventEndDate->format('Y-m-d') . ',"' . $schoolEvent['EventName'] . '",' . $schoolAttendee["EmailAddress"] . ',reminder NOT sent - no outstanding items';

                // Email debug information
                // self::emailDebugInfo($debugInfo);
            }
        }
        
        $debugInfo[] = 'SchoolAttendeeUpsert processing completed';

        // ErrorLog::logInfo('SchoolAttendeeUpsert processing completed: ' . print_r($debugInfo, true));
        
        // echo 'save done<br />' . "\r\n"
        //     . '--------------------------------<br /><br />' . "\r\n\r\n";
        flush();
        // exit;
    }

    public static function getSendCertificateBody($testPassed = true, $event = array(), $schoolCourse = array())
    {

        $return = "Attached is your certificate for the course you attended through the School of Consulting Engineering.\r\n\r\n"
            . "Regards,\r\n\r\n\r\n"
            . "School of Consulting Engineering Consulting Engineers of South Africa\r\n"
            . "011 463 2022\r\n"
            . "cpdcertificates@cesa.co.za";

        if (is_array($event) && count($event) > 0) {

            if (!isset($event['AttendeeName'])) {
                $event['AttendeeName'] = 'Student';
            }

            if (!$testPassed && $event['TestRequired'] > 0 && $event['CPD'] > 0 && $schoolCourse['NonCPDCourse'] <= 0) {
                $return = "Attached please find your interim Attendance Certificate for the " . $event['EventName'] . " course you attended on " . SchoolEvents::getEventDatesString($event) . ".\r\n\r\n"
                    . "You have most likely not had time in your busy schedule to complete the outstanding tasks (Course Quiz / Feedback Questionnaire), and therefore we would like to emphasise that this is not a CPD certificate.  There is no time limit for completing the outstanding tasks; however, we will be unable to provide you with a CPD certificate until these are completed.\r\n\r\n"
                    . "Should you require any further information, please don't hesitate to contact Blessings Banda on Blessings@cesa.co.za / +27 (0) 73 422 0680 or both on +27 (0)11 463-2022.";
            } elseif (!$testPassed && $event['TestRequired'] <= 0 && $event['CPD'] <= 0 && $schoolCourse['NonCPDCourse'] <= 0) {
                $return = "Attached please find your Attendance certificate for the " . $event['EventName'] . " course you attended on " . SchoolEvents::getEventDatesString($event) . ".\r\n\r\n"
                    . "Please note that this is not a CPD certificate.\r\n\r\n"
                    . "Should you require any further information, please don't hesitate to contact Blessings Banda on Blessings@cesa.co.za / +27 (0) 73 422 0680 or both on +27 (0)11 463-2022.";
            } elseif (($testPassed && $event['CPD'] > 0 && $schoolCourse['NonCPDCourse'] <= 0) ||
                ($event['TestRequired'] <= 0 && $event['CPD'] > 0 && $schoolCourse['NonCPDCourse'] <=  0)
            ) {
                $return = "Attached please find your CPD certificate for the " . $event['EventName'] . " course you attended on " . SchoolEvents::getEventDatesString($event) . ".\r\n\r\n"
                    . "Should you require any further information, please don't hesitate to contact Blessings Banda on Blessings@cesa.co.za / +27 (0) 73 422 0680 or both on +27 (0)11 463-2022.";
            } elseif ($schoolCourse['NonCPDCourse'] > 0) {
                $return = "Attached please find your Attendance certificate for the " . $event['EventName'] . " course you attended on " . SchoolEvents::getEventDatesString($event) . ".\r\n\r\n"
                    . "Should you require any further information, please don't hesitate to contact Blessings Banda on Blessings@cesa.co.za / +27 (0) 73 422 0680 or both on +27 (0)11 463-2022.";
            }
        }

        return $return;
    }

    public static function sendAttendeeCertificates($formData)
    {

        global $conni, $env;

        // Initialize debug array to collect all debug information
        $debugInfo = [];
        $debugInfo[] = "=== Certificate Sending Debug Log ===";
        $debugInfo[] = "Timestamp: " . date('Y-m-d H:i:s');
        $debugInfo[] = "Environment: " . $env;
        $hasFailures = false;
        $showDebug = false;

        if ($showDebug) {
            echo "<pre style='background:#111;color:#0f0;padding:10px;white-space:pre-wrap;'>";
            echo "Certificate debug started at " . date('Y-m-d H:i:s') . "\n";
            echo "Environment: " . $env . "\n";
            flush();
        }

        $isNewSendRequest = !isset($formData['start']) && isset($formData['go']) && intval($formData['go']) === 1;
        if ($isNewSendRequest || !isset($_SESSION['send_cert_data'])) {
            // Always refresh payload on a new submit to avoid using stale attendees from a previous screen.
            $_SESSION['send_cert_data'] = $formData;
            $_SESSION['send_cert_data']['start'] = 1;
            unset($_SESSION['sent']);
        } elseif (isset($formData['start'])) {
            $_SESSION['send_cert_data']['start'] = intval($formData['start']);
        }

        if (!isset($_SESSION['send_cert_data']['start']) || $_SESSION['send_cert_data']['start'] <= 0) {
            $_SESSION['send_cert_data']['start'] = 1;
        }

        if ((!isset($_SESSION['send_cert_data']) || !isset($_SESSION['send_cert_data']['NumMessages'])) && isset($formData['NumMessages'])
            && $formData['NumMessages'] > 0
        ) {
            $_SESSION['send_cert_data']['NumMessages'] = $formData['NumMessages'];
        }

        $numMessages = isset($_SESSION['send_cert_data']['NumMessages'])
            ? intval($_SESSION['send_cert_data']['NumMessages'])
            : 0;

        if ($numMessages <= 0) {
            return 0;
        }

        $debugInfo[] = 'Session data: ' . print_r($_SESSION['send_cert_data'], true);

        if (!isset($_SESSION['sent'])) {
            $_SESSION['sent'] = 0;
        }

        $certificateBatchSize = 5;
        if ($numMessages > $certificateBatchSize) {
            @set_time_limit(max(300, $numMessages * 15));
        }

        $isTestOnly = isset($_SESSION['send_cert_data']["sendtestonly"]) && $_SESSION['send_cert_data']["sendtestonly"] === "yes";
        $testEmailAddress = isset($_SESSION['send_cert_data']["TestEmailAddress"]) ? trim($_SESSION['send_cert_data']["TestEmailAddress"]) : '';

        while ($_SESSION['send_cert_data']['start'] <= $numMessages) {

            $batchStart = $_SESSION['send_cert_data']['start'];
            $batchEnd = $batchStart + $certificateBatchSize;
            if ($batchEnd > $numMessages + 1) {
                $batchEnd = $numMessages + 1;
            }

            $_SESSION['send_cert_data']['end'] = $batchEnd;
            $debugInfo[] = 'Batch start=' . $batchStart . ', end=' . $batchEnd;

            $iEmailsSent = 0;

        for ($i = $batchStart; $i < $batchEnd; $i++) {

            if (!isset($_SESSION['send_cert_data']["Email" . $i])) {
                ErrorLog::logInfo(
                    'Certificate send skipped: Missing Email field for index=' . $i
                    . ', EventID=' . (isset($_SESSION['send_cert_data']['EventID']) ? $_SESSION['send_cert_data']['EventID'] : '')
                );
                error_log(
                    'Certificate send skipped: Missing Email field for index=' . $i
                    . ', EventID=' . (isset($_SESSION['send_cert_data']['EventID']) ? $_SESSION['send_cert_data']['EventID'] : '')
                );
                if ($showDebug) {
                    echo "SKIP index {$i}: missing Email{$i}\n";
                    flush();
                }
                continue;
            }

            $SendTo = $_SESSION['send_cert_data']["Email" . $i];
            $actualSendTo = $SendTo;
            $attendeeId = isset($_SESSION['send_cert_data']["AttendeeID" . $i]) ? $_SESSION['send_cert_data']["AttendeeID" . $i] : '';
            $attendeeName = isset($_SESSION['send_cert_data']["Name" . $i]) ? $_SESSION['send_cert_data']["Name" . $i] : '';
            $CCTo = "";
            if (isset($_SESSION['send_cert_data']["sendcopysce"]) && $_SESSION['send_cert_data']["sendcopysce"] == "yes")
                $CCTo = "cpdcertificates@cesa.co.za";
            if ((isset($_SESSION['send_cert_data']["sendcopybb"]) && $_SESSION['send_cert_data']["sendcopybb"] == "yes") && !empty($_SESSION['send_cert_data']["BookedBy" . $i]))
                $CCTo .= "," . $_SESSION['send_cert_data']["BookedBy" . $i];
            if (!empty($_SESSION['send_cert_data']["CopyExtra"]))
                $CCTo .= "," . $_SESSION['send_cert_data']["CopyExtra"];

            if (is_array($CCTo)) {
                $CCTo = array_values(array_filter(array_map('trim', $CCTo), 'strlen'));
            } else {
                $CCTo = trim((string) $CCTo, ",");
                $CCTo = ($CCTo === '') ? [] : array_values(array_filter(array_map('trim', explode(',', $CCTo)), 'strlen'));
            }

            $MessageBody = "";

            $MessageBody .= "Dear " . $_SESSION['send_cert_data']["Name" . $i] . "," . "\r\n\r\n" . $_SESSION['send_cert_data']["EmailMessage"];

            if ($isTestOnly) {
                if ($testEmailAddress === '') {
                    ErrorLog::logError(
                        'Certificate send failed: test-only mode enabled but TestEmailAddress is empty. '
                        . 'AttendeeID=' . $attendeeId
                    );
                    $hasFailures = true;
                    continue;
                }
                $SendTo = $testEmailAddress;
                $CCTo = [];
            }

            if (isset($_SESSION['send_cert_data']["File" . $i])) {

                $sql = "UPDATE SchoolAttendees SET CertificateSent='" . date("Y-m-d H:i:s") . "' WHERE AttendeeID=" . $_SESSION['send_cert_data']["AttendeeID" . $i];

                $debugInfo[] = 'Sent certificate ' . $SendTo . ': ' . $sql;

                if (!$isTestOnly) {
                    mysqli_query($conni, $sql);
                }

                $Attachment = $_SERVER['DOCUMENT_ROOT'] . "/echasl23/certificates/files/" . $_SESSION['send_cert_data']["File" . $i];
            } else {

                $sql = "UPDATE SchoolAttendees 
                    SET QuizReminderSent='" . date("Y-m-d H:i:s") . "' 
                    WHERE AttendeeID=" . $_SESSION['send_cert_data']["AttendeeID" . $i];

                $debugInfo[] = 'Sent reminder ' . $SendTo . ': ' . $sql;

                if (!$isTestOnly) {
                    mysqli_query($conni, $sql);
                }

                $Attachment = null;
            }
            // exit;

            if (!isset($_SESSION['send_cert_data']['subject'])) {
                $_SESSION['send_cert_data']['subject'] = "CESA Certificate - ";
            }
            $emailSubject = $_SESSION['send_cert_data']['subject'] . $_SESSION['send_cert_data']["EventName"];

            if (trim((string) $SendTo) === '' && count($CCTo) <= 0 && !$isTestOnly) {
                ErrorLog::logError(
                    'Certificate send failed: no attendee email and no alternate recipients selected. '
                    . 'AttendeeID=' . $attendeeId
                    . ', Name=' . $attendeeName
                    . ', Subject=' . $emailSubject
                );
                $hasFailures = true;
                continue;
            }

            ErrorLog::logInfo(
                'Certificate send attempt: Index=' . $i
                . ', AttendeeID=' . $attendeeId
                . ', Name=' . $attendeeName
                . ', ActualRecipient=' . $actualSendTo
                . ', SentTo=' . $SendTo
                . ', Subject=' . $emailSubject
                . ', TestOnly=' . ($isTestOnly ? 'Y' : 'N')
            );
            if ($showDebug) {
                echo "ATTEMPT index {$i}: attendee={$attendeeId}, to={$SendTo}, subject={$emailSubject}\n";
                flush();
            }

            $bcc = ['cpdcertificates@cesa.co.za', 'cesasce-reminders@igotafrica.com'];

            if ($env == 'dev') {
                $CCTo = [];
                $bcc = [];
                $SendTo = 'cesa-sce@igotafrica.com';
            }

            if (!is_array($CCTo)) {
                $CCTo = trim((string) $CCTo, ",");
                $CCTo = ($CCTo === '') ? [] : array_values(array_filter(array_map('trim', explode(',', $CCTo)), 'strlen'));
            }

            if (in_array('otto@igotafrica.com', $CCTo, true)) {
                $CCTo = [];
                $bcc = [];
                $SendTo = 'otto@igotafrica.com';
            }

            $debugInfo[] = 'Sending cert to ' . $_SESSION['send_cert_data']["Name" . $i] . ' on ' . $SendTo . ' and CC ' . print_r($CCTo, true) . ' and BCC ' . print_r($bcc, true);
            
            // Try to send the email and track failures
            try {

                // var_dump($SendTo);
                // var_dump($emailSubject);
                // var_dump($MessageBody);
                // var_dump($Attachment);
                // var_dump($CCTo);
                // var_dump($bcc);
                // exit;

                maill(
                    $SendTo,
                    $emailSubject,
                    $MessageBody,
                    $Attachment,
                    array(
                        'from-address' => 'cpdcertificates@cesa.co.za', 
                        'from-name' => 'CESA CPD Certificates', 
                        'cc' => $CCTo,
                         'bcc' => $bcc
                         )
                );
                $debugInfo[] = 'SUCCESS: Certificate sent to ' . $_SESSION['send_cert_data']["Name" . $i] . ' (' . $SendTo . ')';
                ErrorLog::logInfo(
                    'Certificate send success: AttendeeID=' . $attendeeId
                    . ', Name=' . $attendeeName
                    . ', ActualRecipient=' . $actualSendTo
                    . ', SentTo=' . $SendTo
                    . ', Subject=' . $emailSubject
                    . ', TestOnly=' . ($isTestOnly ? 'Y' : 'N')
                );
                error_log(
                    'Certificate send success: AttendeeID=' . $attendeeId
                    . ', Name=' . $attendeeName
                    . ', ActualRecipient=' . $actualSendTo
                    . ', SentTo=' . $SendTo
                    . ', Subject=' . $emailSubject
                    . ', TestOnly=' . ($isTestOnly ? 'Y' : 'N')
                );
                if ($showDebug) {
                    echo "SUCCESS index {$i}: attendee={$attendeeId}, sentTo={$SendTo}\n";
                    flush();
                }
                $iEmailsSent++;
            } catch (Exception $e) {
                // Email failed - add to debug info
                $hasFailures = true;
                $debugInfo[] = "FAILED to send certificate to: " . $_SESSION['send_cert_data']["Name" . $i] . " (" . $SendTo . ")";
                $debugInfo[] = "Error: " . $e->getMessage();
                $debugInfo[] = "AttendeeID: " . $_SESSION['send_cert_data']["AttendeeID" . $i];
                $debugInfo[] = "---";
                ErrorLog::logError(
                    'Certificate send failed: AttendeeID=' . $attendeeId
                    . ', Name=' . $attendeeName
                    . ', ActualRecipient=' . $actualSendTo
                    . ', SentTo=' . $SendTo
                    . ', Subject=' . $emailSubject
                    . ', TestOnly=' . ($isTestOnly ? 'Y' : 'N')
                    . ', Error=' . $e->getMessage()
                );
                error_log(
                    'Certificate send failed: AttendeeID=' . $attendeeId
                    . ', Name=' . $attendeeName
                    . ', ActualRecipient=' . $actualSendTo
                    . ', SentTo=' . $SendTo
                    . ', Subject=' . $emailSubject
                    . ', TestOnly=' . ($isTestOnly ? 'Y' : 'N')
                    . ', Error=' . $e->getMessage()
                );
                if ($showDebug) {
                    echo "FAILED index {$i}: attendee={$attendeeId}, error={$e->getMessage()}\n";
                    flush();
                }
            }
        } // endfor batch loop

            $_SESSION['sent'] += $iEmailsSent;
            $debugInfo[] = $iEmailsSent . ' mails sent in this batch';
            $debugInfo[] = 'Total sent so far: ' . $_SESSION['sent'];

            $_SESSION['send_cert_data']['start'] = $batchEnd;

            if ($showDebug) {
                echo "Batch complete: next start=" . $_SESSION['send_cert_data']['start'] . ", totalSent=" . $_SESSION['sent'] . "\n";
                flush();
            }
        } // endwhile all batches

        $totalSent = $_SESSION['sent'];
        unset($_SESSION['send_cert_data']);
        unset($_SESSION['sent']);

        if ($hasFailures) {
            $debugInfo[] = 'Certificate sending completed with failures. Total sent: ' . $totalSent;
        }

        $debugInfo[] = 'Certificate sending finished. Total sent: ' . $totalSent;

        if ($showDebug) {
            echo "All batches complete. totalSent={$totalSent}\n";
            echo "</pre>";
            flush();
        }

        return $totalSent;
    }

    /**
     * Email debug information to cesa@igotafrica.com
     * @param array $debugInfo Array of debug messages
     */
    private static function emailDebugInfo($debugInfo)
    {
        if (empty($debugInfo)) {
            return;
        }

        $subject = 'Certificate Sending Debug Log - ' . date('Y-m-d H:i:s');
        $messageBody = implode("\n", $debugInfo);
        
        // Add some formatting for better readability
        $formattedMessage = "Certificate Sending Debug Information\n";
        $formattedMessage .= "=====================================\n\n";
        $formattedMessage .= $messageBody;
        $formattedMessage .= "\n\n";
        $formattedMessage .= "--- End of Debug Log ---\n";
        $formattedMessage .= "Generated at: " . date('Y-m-d H:i:s');

        try {
            maill(
                'cesa@igotafrica.com',
                $subject,
                $formattedMessage,
                null,
                array(
                    'from-address' => 'cpdcertificates@cesa.co.za',
                    'from-name' => 'CESA Certificate System',
                    'isHTML' => false
                )
            );
        } catch (Exception $e) {
            // If email fails, we can't do much about it, but we could log it
            error_log('Failed to send debug email: ' . $e->getMessage());
        }
    }

    public static function sendAttendeeRegistrationForm($attendee)
    {

        global $conni, $env;

        $SendTo = $attendee['EmailAddress'];

        $MessageBody = "Dear " . $attendee['ContactFirstName'] . "," . "\r\n\r\n" . 'Please find your registration form attached for ' . $attendee['EventName'] . ' on ' . $attendee['StartDate'];

        $filePath = $attendee['AttendeeID'] . '-registration-form.html';
        GeneratePDF($filePath, $attendee['BookingForm']);

        //        echo 'Sending to ' . $SendTo . '<br />';
        //        echo $_SERVER['DOCUMENT_ROOT'] . "/echasl23/downloads/" . $attendee['AttendeeID'] . '-registration-form_html.pdf';
        //        exit;

        maill(
            $SendTo,
            'Event Registration form for ' . $attendee['EventName'],
            $MessageBody,
            $_SERVER['DOCUMENT_ROOT'] . "/echasl23/downloads/" . $attendee['AttendeeID'] . '-registration-form_html.pdf',
            array('from-address' => 'sce.co.za', 'from-name' => 'CESA SCE', 'bcc' => array('sce@cesa.co.za'))
        );
    }

    /**
     * Parse comma-, semicolon-, or whitespace-separated email addresses.
     *
     * @param string $input
     * @return array
     */
    public static function parseEmailAddressList($input)
    {
        if (!is_string($input) || trim($input) === '') {
            return array();
        }

        $parts = preg_split('/[\s,;]+/', trim($input), -1, PREG_SPLIT_NO_EMPTY);
        $valid = array();

        foreach ($parts as $email) {
            $email = trim($email);
            if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
                $valid[] = $email;
            }
        }

        return array_values(array_unique($valid));
    }

    /**
     * Attendees eligible for certificate email on the certificates list (attended + paid).
     *
     * @param int $eventId
     * @param array $attendeeIds Optional filter
     * @return array
     */
    public function getCertificateEmailAttendees($eventId, array $attendeeIds = array())
    {
        $eventId = intval($eventId);
        if ($eventId <= 0) {
            return array();
        }

        $sql = "SELECT AttendeeID, ContactFirstName, ContactLastName, EmailAddress, BookingEmail
            FROM SchoolAttendees
            WHERE SchoolAttendees.EventID = " . $eventId . "
            AND Attended = 'y'
            AND AttendeeID IN (SELECT AttendeeID FROM SchoolPayments WHERE EventID = " . $eventId . ")";

        if (count($attendeeIds) > 0) {
            $ids = array();
            foreach ($attendeeIds as $id) {
                $id = intval($id);
                if ($id > 0) {
                    $ids[] = $id;
                }
            }
            if (count($ids) > 0) {
                $sql .= " AND AttendeeID IN (" . implode(', ', $ids) . ")";
            }
        }

        $sql .= " ORDER BY ContactLastName, ContactFirstName, AttendeeID";

        $rows = $this->sqlf->getAll($sql);

        return is_array($rows) ? $rows : array();
    }

    /**
     * Generate certificate PDF for an attendee; returns absolute file path or null.
     *
     * @param int $attendeeId
     * @return string|null
     */
    public function generateCertificateFilePath($attendeeId)
    {
        global $sqlf;

        $AttendeeID = intval($attendeeId);
        if ($AttendeeID <= 0) {
            return null;
        }

        if (!is_object($sqlf)) {
            throw new Exception('Database connection is not available for certificate generation.');
        }

        $sFilename = '';
        include $_SERVER['DOCUMENT_ROOT'] . '/echasl23/inc_gencertificate.php';

        if ($sFilename === '') {
            return null;
        }

        $path = rtrim($_SERVER['DOCUMENT_ROOT'], '/') . '/echasl23/certificates/files/' . $sFilename;

        return is_file($path) ? $path : null;
    }

    /**
     * Send all eligible event certificates in one email to a single address.
     *
     * @param array $params event_id, to_address, bcc_addresses, email_message, send_copy_sce, attendee_ids
     * @return array sent_count, attachment_count, event_name
     * @throws Exception
     */
    public function sendAllCertificatesToOneAddress(array $params)
    {
        global $conni, $env;

        $eventId = isset($params['event_id']) ? intval($params['event_id']) : 0;
        if ($eventId <= 0) {
            throw new Exception('No event specified.');
        }

        $toAddress = isset($params['to_address']) ? trim((string) $params['to_address']) : '';
        if ($toAddress === '' || !filter_var($toAddress, FILTER_VALIDATE_EMAIL)) {
            throw new Exception('A valid To e-mail address is required.');
        }

        $attendeeIds = isset($params['attendee_ids']) && is_array($params['attendee_ids'])
            ? $params['attendee_ids']
            : array();

        $attendees = $this->getCertificateEmailAttendees($eventId, $attendeeIds);
        if (count($attendees) <= 0) {
            throw new Exception('No eligible attendees found for this event.');
        }

        $event = $this->sqlf->getRow("SELECT EventName FROM SchoolEvents WHERE EventID = " . $eventId . " LIMIT 1");
        $eventName = (is_array($event) && isset($event['EventName'])) ? $event['EventName'] : 'School event';

        $attachments = array();
        $attendeeIdsSent = array();

        foreach ($attendees as $attendee) {
            $filePath = $this->generateCertificateFilePath($attendee['AttendeeID']);
            if ($filePath === null) {
                throw new Exception(
                    'Could not generate certificate for '
                    . $attendee['ContactFirstName'] . ' ' . $attendee['ContactLastName'] . '.'
                );
            }

            $attachments[] = array(
                'path' => $filePath,
                'name' => basename($filePath),
            );
            $attendeeIdsSent[] = intval($attendee['AttendeeID']);
        }

        $messageBody = isset($params['email_message']) ? trim((string) $params['email_message']) : '';
        if ($messageBody === '') {
            $messageBody = "Attached are the certificates for attendees of " . $eventName . ".\r\n\r\n"
                . SchoolAttendees::getSendCertificateBody();
        }

        $bcc = self::parseEmailAddressList(isset($params['bcc_addresses']) ? $params['bcc_addresses'] : '');
        $sendCopySce = !empty($params['send_copy_sce']) || !empty($params['send_copy_cpdcertificates']);
        if ($sendCopySce) {
            $bcc[] = self::SCHOOL_CERTIFICATE_DEFAULT_EMAIL;
        }
        $bcc[] = 'cesasce-reminders@igotafrica.com';
        $bcc = array_values(array_unique($bcc));

        $sendTo = $toAddress;
        if ($env == 'dev') {
            $bcc = array();
            $sendTo = self::SCHOOL_CERTIFICATE_DEFAULT_EMAIL;
        }

        if (in_array('otto@igotafrica.com', $bcc, true) || $sendTo === 'otto@igotafrica.com') {
            $bcc = array();
            $sendTo = 'otto@igotafrica.com';
        }

        $subject = 'CESA Certificate - ' . $eventName;

        maill(
            $sendTo,
            $subject,
            $messageBody,
            null,
            array(
                'from-address' => 'website@cesa.co.za',
                'from-name' => 'School of Consulting Engineering',
                'bcc' => $bcc,
                'attachments' => $attachments,
            )
        );

        $now = date('Y-m-d H:i:s');
        if ($env != 'dev' && is_object($conni)) {
            foreach ($attendeeIdsSent as $attendeeId) {
                mysqli_query(
                    $conni,
                    "UPDATE SchoolAttendees SET CertificateSent='" . mysqli_real_escape_string($conni, $now)
                    . "' WHERE AttendeeID=" . intval($attendeeId)
                );
            }
        }

        return array(
            'sent_count' => count($attendeeIdsSent),
            'attachment_count' => count($attachments),
            'event_name' => $eventName,
            'sent_to' => $sendTo,
        );
    }

    public function sendAllAttendeeCertificates()
    {
        // Initialize debug array for bulk certificate sending
        $debugInfo = [];
        $debugInfo[] = "=== Bulk Certificate Sending Debug Log ===";
        $debugInfo[] = "Timestamp: " . date('Y-m-d H:i:s');

        $attendees = $this->findToSendCertificates();

        $debugInfo[] = 'Found ' . count($attendees) . ' attendees to send certificates';
        // exit;

        $alreadySent = [];

        foreach ($attendees as $attendee) {

            unset($_SESSION['send_cert_data']);

            if (in_array($attendee['AttendeeID'], $alreadySent)) {
                $debugInfo[] = 'Already sent certificate for ' . $attendee['ContactFirstName'] . ' ' . $attendee['ContactLastName'] . ' '
                    . $attendee['EmailAddress'];
                continue;
            }

            $alreadySent[] = $attendee['AttendeeID'];

            // if (count($alreadySent) > 160) {
            //     $debugInfo[] = 'Already sent certificates for ' . count($alreadySent) . ' attendees';
            //     continue;
            // }

            $this->SchoolAttendeeUpsert($attendee['AttendeeID']);
        }

        $debugInfo[] = 'Bulk certificate sending completed. Total processed: ' . count($alreadySent);
        
        // Email debug information
        // self::emailDebugInfo($debugInfo);
    }

    public function fixCase($attendee)
    {

        $SchoolAttendee['AttendeeID'] = $attendee['AttendeeID'];
        $SchoolAttendee['ContactFirstName'] = ucwords(strtolower($attendee['ContactFirstName']));
        $SchoolAttendee['KnownAs'] = ucwords(strtolower($attendee['KnownAs']));
        $SchoolAttendee['ContactLastName'] = ucwords(strtolower($attendee['ContactLastName']));
        $SchoolAttendee['Organisation'] = str_replace('(pty)', '(Pty)', ucwords(strtolower($attendee['Organisation'])));
        $SchoolAttendee['CompanyName'] = str_replace('(pty)', '(Pty)', ucwords(strtolower($attendee['CompanyName'])));
        $SchoolAttendee['EmailAddress'] = strtolower($attendee['EmailAddress']);

        $this->upsert($SchoolAttendee);
    }
}

function SchoolAttendeeUpsert($rsOld, $rsNew = array())
{

    global $sqlf;

    $schoolAttendees = new SchoolAttendees($sqlf);

    $rsUpdate = $rsOld;

    if (count($rsNew) > 0) {
        $rsUpdate = $rsNew;
    }

    $schoolAttendees->SchoolAttendeeUpsert($rsOld['AttendeeID'], $rsUpdate);
}

function getSchoolAttendeeRegistrationFormLink($attendeeID)
{
    return '<p><a href="/php/templates/school/SchoolAttendeeBookingForm.php?SchoolAttendeeID=' . $attendeeID . '" target="_blank">Registration Form</a></p>'
        . '<p><a href="/php/templates/school/SchoolAttendeeBookingFormSend.php?SchoolAttendeeID=' . $attendeeID . '">Resend Registration Form</a></p>'
        . '<p><a href="/php/templates/school/SchoolAttendeeFixCase.php?SchoolAttendeeID=' . $attendeeID . '">Fix Case</a></p>';
}

function schoolAttendeeRowRender(&$objThis)
{
    if ($objThis->Cancelled->CurrentValue == 0) {
        $objThis->Cancelled->CellAttrs["style"] = "background-color: #ccff66";
    } elseif ($objThis->Cancelled->CurrentValue == 1) {
        $objThis->Cancelled->CellAttrs["style"] = "background-color: #ff9999";
    }

    $sChangeAtt = "<select name='Attended" . $objThis->AttendeeID->CurrentValue . "' onChange='javascript:if (confirm(\"Save Changes?\")) UpdateAttended(" . $objThis->AttendeeID->CurrentValue . ",this.options[this.selectedIndex].value)'>";
    $sChangeAtt .= "<option value='y'";
    if ($objThis->Attended->CurrentValue == 'y')
        $sChangeAtt .= " selected";
    $sChangeAtt .= ">Yes</option>";
    $sChangeAtt .= "<option value='n'";
    if ($objThis->Attended->CurrentValue == 'n')
        $sChangeAtt .= " selected";
    $sChangeAtt .= ">No</option>";
    $sChangeAtt .= "<option value='u'";
    if ($objThis->Attended->CurrentValue == 'u')
        $sChangeAtt .= " selected";
    $sChangeAtt .= ">Unknown</option></select>";
    $objThis->Attended->ViewValue = $sChangeAtt;
}

function schoolAttendeeListOptionsLoad(&$objThis) {

    $objThis->ListOptions->Add("paid");     
    $objThis->ListOptions->Items["paid"]->CssStyle = "white-space: nowrap;";
    $objThis->ListOptions->Items["paid"]->OnLeft = FALSE;  
    $objThis->ListOptions->Items["paid"]->Header="Paid";
    $objThis->ListOptions->MoveItem("paid",count($objThis->ListOptions->Items)-1);
    
    $objThis->ListOptions->Add("registration");     
    $objThis->ListOptions->Items["registration"]->CssStyle = "white-space: nowrap;";
    $objThis->ListOptions->Items["registration"]->OnLeft = FALSE;  
    $objThis->ListOptions->Items["registration"]->Header="Registration Form";
    $objThis->ListOptions->MoveItem("registration",count($objThis->ListOptions->Items)-1);
}

function schoolAttendeeListOptionsRendered(&$objThis, &$schoolAttendees) {

    global $conn;
    
    $sql = "SELECT AmountPaid, AmountDue FROM SchoolPayments WHERE AttendeeID='".$schoolAttendees->AttendeeID->CurrentValue."'";
    $rs = $conn->Execute($sql);
    if ($rs && !$rs->EOF) {
        $rs->MoveFirst();
        if ($rs->fields('AmountPaid') >= $rs->fields('AmountDue')) {      
            $objThis->ListOptions->Items["paid"]->Body = '<SPAN class=phpmaker>Paid</SPAN>';      
        } else { 
            $objThis->ListOptions->Items["paid"]->Body = '<SPAN class=phpmaker>Not Paid</SPAN>'; 
        }
     } else { 
        $objThis->ListOptions->Items["paid"]->Body = '<SPAN class=phpmaker>Not Paid</SPAN>'; 
     }
     $rs->Close();
                 
     $objThis->ListOptions->Items["registration"]->Body = getSchoolAttendeeRegistrationFormLink($schoolAttendees->AttendeeID->CurrentValue);

}

function schoolAttendeeListPageLoad() {

    if (isset($_REQUEST['EventID']) && strlen($_REQUEST['EventID']) > 0) {

        if (!isset($_SESSION[EW_SESSION_MESSAGE])) {
            $_SESSION[EW_SESSION_MESSAGE] = '';
        }

        $_SESSION[EW_SESSION_MESSAGE] .= '<span class="phpmaker" style="margin-bottom: 10px;">'
                . '<a href="SchoolAttendeesimport.php?EventID=' . $_REQUEST['EventID'] . '">'
                . '<img src="images/expand.gif" alt="Import Attendees" title="Import Attendees" width="16" height="16" border="0">'
                . '&nbsp;Import Attendees</a>'
                . '</span>';

        $_SESSION[EW_SESSION_MESSAGE] .= '&nbsp;&nbsp;<span class="phpmaker" style="margin-bottom: 10px;">'
                . '<a href="/echasl23/SchoolAttendeeBulkEmail.php?EventID=' . $_REQUEST['EventID'] . '">'
                . '<img src="images/expand.gif" alt="Email Attendees" title="Email Attendees" width="16" height="16" border="0">'
                . '&nbsp;Email Attendees</a>'
                . '</span>';

        $_SESSION[EW_SESSION_MESSAGE] .= '&nbsp;&nbsp;<span class="phpmaker" style="margin-bottom: 10px;">'
                . '<a href="/echasl23/SchoolEventInsufficientDelegatesEmail.php?EventID=' . $_REQUEST['EventID'] . '">'
                . '<img src="images/expand.gif" alt="Insufficient Delegates Email" title="Insufficient Delegates Email" width="16" height="16" border="0">'
                . '&nbsp;Insufficient Delegates Email</a>'
                . '</span>';

        $eventId = intval($_REQUEST['EventID']);
        $eventCancelled = false;
        if (isset($GLOBALS['sqlf']) && is_object($GLOBALS['sqlf'])) {
            $eventRow = $GLOBALS['sqlf']->getRow('SELECT Cancelled FROM SchoolEvents WHERE EventID = ' . $eventId . ' LIMIT 1');
            if (is_array($eventRow)) {
                $eventCancelled = intval(isset($eventRow['Cancelled']) ? $eventRow['Cancelled'] : 0) > 0;
            }
        } elseif (isset($GLOBALS['conni']) && $GLOBALS['conni']) {
            $cancelRec = mysqli_query($GLOBALS['conni'], 'SELECT Cancelled FROM SchoolEvents WHERE EventID=' . $eventId . ' LIMIT 1');
            if ($cancelRec && ($cancelRow = mysqli_fetch_assoc($cancelRec))) {
                $eventCancelled = intval($cancelRow['Cancelled']) > 0;
            }
            if ($cancelRec) {
                mysqli_free_result($cancelRec);
            }
        }

        if (!$eventCancelled) {
            $_SESSION[EW_SESSION_MESSAGE] .= '&nbsp;&nbsp;<span class="phpmaker" style="margin-bottom: 10px;">'
                    . '<a href="/echasl23/SchoolEventCoursePostponedEmail.php?EventID=' . $eventId . '">'
                    . '<img src="images/expand.gif" alt="Postpone" title="Postpone" width="16" height="16" border="0">'
                    . '&nbsp;Postpone</a>'
                    . '</span>';
            $_SESSION[EW_SESSION_MESSAGE] .= '&nbsp;&nbsp;<span class="phpmaker" style="margin-bottom: 10px;">'
                    . '<a href="/echasl23/SchoolEventCoursePostponedNewDatesEmail.php?EventID=' . $eventId . '">'
                    . '<img src="images/expand.gif" alt="New Dates - Postpone" title="New Dates - Postpone" width="16" height="16" border="0">'
                    . '&nbsp;New Dates – Postpone</a>'
                    . '</span>';
        }

        if ($eventCancelled) {
            $_SESSION[EW_SESSION_MESSAGE] .= '&nbsp;&nbsp;<span class="phpmaker" style="margin-bottom: 10px;">'
                    . '<a href="/echasl23/SchoolEventCourseCancelledEmail.php?EventID=' . $eventId . '">'
                    . '<img src="images/expand.gif" alt="Course Cancelled Email" title="Course Cancelled Email" width="16" height="16" border="0">'
                    . '&nbsp;Course Cancelled Email</a>'
                    . '</span>';
        }
    }

}

// Custom code to handle sorting for custom view
function SchoolAttendees_Recordset_Selecting(&$objThis, &$filter) {
    // Get the current order by from session
    $sOrderBy = $objThis->getSessionOrderBy();
    if ($sOrderBy <> "") {
        // Replace table references with view column names
        $sOrderBy = str_replace("SchoolAttendees.DateBooked", "DateBooked", $sOrderBy);
        $sOrderBy = str_replace("SchoolAttendees.AttendeeID", "AttendeeID", $sOrderBy);
        $sOrderBy = str_replace("SchoolEvents.EventID", "EventID", $sOrderBy);
        $sOrderBy = str_replace("SchoolEvents.StartDate", "StartDate", $sOrderBy);
        $sOrderBy = str_replace("SchoolEvents.EndDate", "EndDate", $sOrderBy);
        $sOrderBy = str_replace("SchoolCourses.CourseName", "EventName", $sOrderBy);
        $sOrderBy = str_replace("SchoolAttendees.CompanyName", "Organisation", $sOrderBy);
        $sOrderBy = str_replace("Concat_Ws(' ', SchoolAttendees.ContactFirstName, SchoolAttendees.ContactLastName)", "Delegate", $sOrderBy);
    } else {
        $sOrderBy = "DateBooked DESC";
    }

    // Set the corrected order by
    $objThis->setSessionOrderBy($sOrderBy);
}