From 4a3451de13b748fa84188e36b5c7a96b6fd059de Mon Sep 17 00:00:00 2001 From: Jon Goldberg Date: Fri, 21 Feb 2020 18:17:23 -0500 Subject: [PATCH] [REF] Extract self-service eligibility code into its own function --- CRM/Event/BAO/Participant.php | 63 +++++++++++++++++ CRM/Event/Form/SelfSvcTransfer.php | 19 +---- CRM/Event/Form/SelfSvcUpdate.php | 46 +----------- .../phpunit/CRM/Event/BAO/ParticipantTest.php | 70 +++++++++++++++++++ 4 files changed, 137 insertions(+), 61 deletions(-) diff --git a/CRM/Event/BAO/Participant.php b/CRM/Event/BAO/Participant.php index b24c279aa8..cdc3c4e903 100644 --- a/CRM/Event/BAO/Participant.php +++ b/CRM/Event/BAO/Participant.php @@ -1874,4 +1874,67 @@ WHERE civicrm_participant.contact_id = {$contactID} AND } } + /** + * Evaluate whether a participant record is eligible for self-service transfer/cancellation. If so, + * return additional participant/event details. + * + * TODO: BAO-level functions shouldn't set a redirect, and it should be possible to return "false" to the + * calling function. The next refactor will add a fourth param $errors, which can be passed by reference + * from the calling function. Instead of redirecting, we will return the error. + * TODO: This function should always return FALSE when self-service has been disabled on an event. + * TODO: This function fails when the "hours until self-service" is greater than 24 or less than zero. + * @param int $participantId + * @param string $url + * @param bool $isBackOffice + */ + public static function getSelfServiceEligibility($participantId, $url, $isBackOffice) { + $optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'participant_role', 'id', 'name'); + $query = " + SELECT cpst.name as status, cov.name as role, cp.fee_level, cp.fee_amount, cp.register_date, cp.status_id, ce.start_date, ce.title, cp.event_id + FROM civicrm_participant cp + LEFT JOIN civicrm_participant_status_type cpst ON cpst.id = cp.status_id + LEFT JOIN civicrm_option_value cov ON cov.value = cp.role_id and cov.option_group_id = {$optionGroupId} + LEFT JOIN civicrm_event ce ON ce.id = cp.event_id + WHERE cp.id = {$participantId}"; + $dao = CRM_Core_DAO::executeQuery($query); + while ($dao->fetch()) { + $details['status'] = $dao->status; + $details['role'] = $dao->role; + $details['fee_level'] = trim($dao->fee_level, CRM_Core_DAO::VALUE_SEPARATOR); + $details['fee_amount'] = $dao->fee_amount; + $details['register_date'] = $dao->register_date; + $details['event_start_date'] = $dao->start_date; + $eventTitle = $dao->title; + $eventId = $dao->event_id; + } + //verify participant status is still Registered + if ($details['status'] != 'Registered') { + $status = "You cannot transfer or cancel your registration for " . $eventTitle . ' as you are not currently registered for this event.'; + CRM_Core_Session::setStatus($status, ts('Sorry'), 'alert'); + CRM_Utils_System::redirect($url); + } + $query = "select start_date as start, selfcancelxfer_time as time from civicrm_event where id = " . $eventId; + $dao = CRM_Core_DAO::executeQuery($query); + while ($dao->fetch()) { + $time_limit = $dao->time; + $start_date = $dao->start; + } + $start_time = new Datetime($start_date); + $timenow = new Datetime(); + if (!$isBackOffice && !empty($start_time) && $start_time < $timenow) { + $status = ts('Registration for this event cannot be cancelled or transferred once the event has begun. Contact the event organizer if you have questions.'); + CRM_Core_Error::statusBounce($status, $url, ts('Sorry')); + } + if (!$isBackOffice && !empty($time_limit) && $time_limit > 0) { + $interval = $timenow->diff($start_time); + $days = $interval->format('%d'); + $hours = $interval->format('%h'); + if ($hours <= $time_limit && $days < 1) { + $status = ts("Registration for this event cannot be cancelled or transferred less than %1 hours prior to the event's start time. Contact the event organizer if you have questions.", [1 => $time_limit]); + CRM_Core_Error::statusBounce($status, $url, ts('Sorry')); + } + } + return $details; + } + } diff --git a/CRM/Event/Form/SelfSvcTransfer.php b/CRM/Event/Form/SelfSvcTransfer.php index 8fac0d8119..4569886426 100644 --- a/CRM/Event/Form/SelfSvcTransfer.php +++ b/CRM/Event/Form/SelfSvcTransfer.php @@ -164,23 +164,8 @@ class CRM_Event_Form_SelfSvcTransfer extends CRM_Core_Form { $this->_contact_email = $email; $details = CRM_Event_BAO_Participant::participantDetails($this->_from_participant_id); - $optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'participant_role', 'id', 'name'); - $query = " - SELECT cpst.name as status, cov.name as role, cp.fee_level, cp.fee_amount, cp.register_date, civicrm_event.start_date - FROM civicrm_participant cp - LEFT JOIN civicrm_participant_status_type cpst ON cpst.id = cp.status_id - LEFT JOIN civicrm_option_value cov ON cov.value = cp.role_id and cov.option_group_id = {$optionGroupId} - LEFT JOIN civicrm_event ON civicrm_event.id = cp.event_id - WHERE cp.id = {$this->_from_participant_id}"; - $dao = CRM_Core_DAO::executeQuery($query); - while ($dao->fetch()) { - $details['status'] = $dao->status; - $details['role'] = $dao->role; - $details['fee_level'] = $dao->fee_level; - $details['fee_amount'] = $dao->fee_amount; - $details['register_date'] = $dao->register_date; - $details['event_start_date'] = $dao->start_date; - } + $selfServiceDetails = CRM_Event_BAO_Participant::getSelfServiceEligibility($this->_from_participant_id, $url, $this->isBackoffice); + $details = array_merge($details, $selfServiceDetails); $this->assign('details', $details); //This participant row will be cancelled. Get line item(s) to cancel $this->selfsvctransferUrl = CRM_Utils_System::url('civicrm/event/selfsvcupdate', diff --git a/CRM/Event/Form/SelfSvcUpdate.php b/CRM/Event/Form/SelfSvcUpdate.php index baf595938f..760478a058 100644 --- a/CRM/Event/Form/SelfSvcUpdate.php +++ b/CRM/Event/Form/SelfSvcUpdate.php @@ -137,52 +137,10 @@ class CRM_Event_Form_SelfSvcUpdate extends CRM_Core_Form { $this->_contact_email = $email; $details = CRM_Event_BAO_Participant::participantDetails($this->_participant_id); - $optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'participant_role', 'id', 'name'); $contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_participant_id, 'contribution_id', 'participant_id'); $this->assign('contributionId', $contributionId); - $query = " - SELECT cpst.name as status, cov.name as role, cp.fee_level, cp.fee_amount, cp.register_date, cp.status_id, civicrm_event.start_date - FROM civicrm_participant cp - LEFT JOIN civicrm_participant_status_type cpst ON cpst.id = cp.status_id - LEFT JOIN civicrm_option_value cov ON cov.value = cp.role_id and cov.option_group_id = {$optionGroupId} - LEFT JOIN civicrm_event ON civicrm_event.id = cp.event_id - WHERE cp.id = {$this->_participant_id}"; - $dao = CRM_Core_DAO::executeQuery($query); - while ($dao->fetch()) { - $details['status'] = $dao->status; - $details['role'] = $dao->role; - $details['fee_level'] = trim($dao->fee_level, CRM_Core_DAO::VALUE_SEPARATOR); - $details['fee_amount'] = $dao->fee_amount; - $details['register_date'] = $dao->register_date; - $details['event_start_date'] = $dao->start_date; - } - //verify participant status is still Registered - if ($details['status'] !== 'Registered') { - $status = "You cannot transfer or cancel your registration for " . $this->_event_title . ' as you are not currently registered for this event.'; - CRM_Core_Session::setStatus($status, ts('Sorry'), 'alert'); - CRM_Utils_System::redirect($url); - } - $query = "select start_date as start, selfcancelxfer_time as time from civicrm_event where id = " . $this->_event_id; - $dao = CRM_Core_DAO::executeQuery($query); - while ($dao->fetch()) { - $time_limit = $dao->time; - $start_date = $dao->start; - } - $start_time = new Datetime($start_date); - $timenow = new Datetime(); - if (!$this->isBackoffice && !empty($start_time) && $start_time < $timenow) { - $status = ts('Registration for this event cannot be cancelled or transferred once the event has begun. Contact the event organizer if you have questions.'); - CRM_Core_Error::statusBounce($status, $url, ts('Sorry')); - } - if (!$this->isBackoffice && !empty($time_limit) && $time_limit > 0) { - $interval = $timenow->diff($start_time); - $days = $interval->format('%d'); - $hours = $interval->format('%h'); - if ($hours <= $time_limit && $days < 1) { - $status = ts("Registration for this event cannot be cancelled or transferred less than %1 hours prior to the event's start time. Contact the event organizer if you have questions.", [1 => $time_limit]); - CRM_Core_Error::statusBounce($status, $url, ts('Sorry')); - } - } + $selfServiceDetails = CRM_Event_BAO_Participant::getSelfServiceEligibility($this->_participant_id, $url, $this->isBackoffice); + $details = array_merge($details, $selfServiceDetails); $this->assign('details', $details); $this->selfsvcupdateUrl = CRM_Utils_System::url('civicrm/event/selfsvcupdate', "reset=1&id={$this->_participant_id}&id=0"); $this->selfsvcupdateText = ts('Update'); diff --git a/tests/phpunit/CRM/Event/BAO/ParticipantTest.php b/tests/phpunit/CRM/Event/BAO/ParticipantTest.php index d4f4e2db77..0a3cba0fd9 100644 --- a/tests/phpunit/CRM/Event/BAO/ParticipantTest.php +++ b/tests/phpunit/CRM/Event/BAO/ParticipantTest.php @@ -412,4 +412,74 @@ class CRM_Event_BAO_ParticipantTest extends CiviUnitTestCase { $this->eventDelete($eventId); } + /** + * Test various self-service eligibility scenarios. + * + * @dataProvider selfServiceScenarios + * @param $selfSvcEnabled + * @param $selfSvcHours + * @param $hoursToEvent + * @param $participantStatusId + * @param $isBackOffice + * @param $successExpected A boolean that indicates whether this test should pass or fail. + */ + public function testGetSelfServiceEligibility($selfSvcEnabled, $selfSvcHours, $hoursToEvent, $participantStatusId, $isBackOffice, $successExpected) { + $participantId = $this->participantCreate(['contact_id' => $this->_contactId, 'event_id' => $this->_eventId, 'status_id' => $participantStatusId]); + $now = new Datetime(); + $startDate = $now->add(new DateInterval("PT{$hoursToEvent}H"))->format('Y-m-d H:i:s'); + $this->callAPISuccess('Event', 'create', [ + 'id' => $this->_eventId, + 'allow_selfcancelxfer' => $selfSvcEnabled, + 'selfcancelxfer_time' => $selfSvcHours, + 'start_date' => $startDate, + ]); + $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_eventId}"); + // If we return without an error, then success. But we don't always expect success. + try { + CRM_Event_BAO_Participant::getSelfServiceEligibility($participantId, $url, $isBackOffice); + } + catch (\Exception $e) { + if ($successExpected === FALSE) { + return; + } + else { + $this->fail(); + } + } + if ($successExpected === FALSE) { + $this->fail(); + } + } + + public function selfServiceScenarios() { + // Standard pass scenario + $scenarios[] = [ + 'selfSvcEnabled' => TRUE, + 'selfSvcHours' => 12, + 'hoursToEvent' => 16, + 'participantStatusId' => 1, + 'isBackOffice' => FALSE, + 'successExpected' => TRUE, + ]; + // Too late to self-service + $scenarios[] = [ + 'selfSvcEnabled' => TRUE, + 'selfSvcHours' => 12, + 'hoursToEvent' => 8, + 'participantStatusId' => 1, + 'isBackOffice' => FALSE, + 'successExpected' => FALSE, + ]; + // Participant status is other than "Registered". + $scenarios[] = [ + 'selfSvcEnabled' => TRUE, + 'selfSvcHours' => 12, + 'hoursToEvent' => 16, + 'participantStatusId' => 2, + 'isBackOffice' => FALSE, + 'successExpected' => FALSE, + ]; + return $scenarios; + } + } -- 2.25.1