From 861d11c49e2b07090925d06c367037fa588b91fe Mon Sep 17 00:00:00 2001 From: Dave Greenberg Date: Wed, 8 Oct 2014 16:46:47 -0700 Subject: [PATCH] CRM-15376 - Porting fixes from https://github.com/civicrm/civicrm-core/pull/4233 to 4.5 branch. ---------------------------------------- * CRM-15376: https://issues.civicrm.org/jira/browse/CRM-15376 --- CRM/Core/BAO/ActionSchedule.php | 7 +- .../CRM/Core/BAO/ActionScheduleTest.php | 98 ++++++++++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php index 03b5c15991..d48cc36f94 100755 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -1265,11 +1265,16 @@ GROUP BY c.id $havingClause = "HAVING TIMEDIFF({$now}, latest_log_time) >= TIME('{$hrs}:00:00')"; $groupByClause = 'GROUP BY reminder.contact_id, reminder.entity_id, reminder.entity_table'; $selectClause .= ', MAX(reminder.action_date_time) as latest_log_time'; + //CRM-15376 - do not send our reminders if original criteria no longer applies + // the first part of the startDateClause array is the earliest the reminder can be sent. If the + // event (e.g membership_end_date) has changed then the reminder may no longer apply + // @todo - this only handles events that get moved later. Potentially they might get moved earlier + $originalEventStartDateClause = empty($startDateClause) ? '' : 'AND' . $startDateClause[0]; $sqlInsertValues = "{$selectClause} {$fromClause} {$joinClause} INNER JOIN {$reminderJoinClause} -{$whereClause} {$limitWhereClause} AND {$repeatEventClause} {$notINClause} +{$whereClause} {$limitWhereClause} AND {$repeatEventClause} {$originalEventStartDateClause} {$notINClause} {$groupByClause} {$havingClause}"; diff --git a/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php b/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php index 7de69679f8..d9ea1cb18b 100644 --- a/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php +++ b/tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php @@ -364,9 +364,38 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase { 'start_action_unit' => 'week', 'subject' => 'subject sched_contact_grad_anniv', ); + $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'] = array( // create() + 'name' => 'sched_membership_end_2month', + 'title' => 'sched_membership_end_2month', + 'absolute_date' => '', + 'body_html' => '

body sched_membership_end_2month

', + 'body_text' => 'body sched_membership_end_2month', + 'end_action' => '', + 'end_date' => '', + 'end_frequency_interval' => '4', + 'end_frequency_unit' => 'month', + 'entity_status' => '', + 'entity_value' => '', + 'group_id' => '', + 'is_active' => 1, + 'is_repeat' => '1', + 'mapping_id' => 4, + 'msg_template_id' => '', + 'recipient' => '', + 'recipient_listing' => '', + 'recipient_manual' => '', + 'record_activity' => 1, + 'repetition_frequency_interval' => '4', + 'repetition_frequency_unit' => 'week', + 'start_action_condition' => 'after', + 'start_action_date' => 'membership_end_date', + 'start_action_offset' => '2', + 'start_action_unit' => 'month', + 'subject' => 'subject sched_membership_end_2month', + ); + $this->_setUp(); - $this->quickCleanup(array('civicrm_action_log', 'civicrm_action_schedule')); } /** @@ -381,7 +410,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase { $this->mut->clearMessages(); $this->mut->stop(); unset($this->mut); - + $this->quickCleanup(array('civicrm_action_schedule', 'civicrm_action_log', 'civicrm_membership', 'civicrm_email')); $this->_tearDown(); } @@ -523,6 +552,71 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase { )); } + /** + * Test that the first and SECOND notifications are sent out + * + */ + function testMembershipEndDate_Repeat() { + // creates membership with end_date = 20120615 + $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2))); + $result = $this->callAPISuccess('Email', 'create', array( + 'contact_id' => $membership->contact_id, + 'email' => 'test-member@example.com', + )); + $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id))); + + $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks']; + $actionSchedule['entity_value'] = $membership->membership_type_id; + $this->callAPISuccess('action_schedule', 'create', $actionSchedule); + + // end_date=2012-06-15 ; schedule is 2 weeks before end_date + $this->assertCronRuns(array( + array( // After the 2-week mark, send an email + 'time' => '2012-08-15 01:00:00', + 'recipients' => array(array('test-member@example.com')), + ), + array( // After the 2-week mark, send an email + 'time' => '2012-09-12 01:00:00', + 'recipients' => array(array('test-member@example.com')), + ), + )); + } + + /** + * Test that the first notification is sent but the second is NOT sent if the end date changes in + * between + * see CRM-15376 + */ + function testMembershipEndDate_Repeat_ChangedEndDate_CRM_15376() { + // creates membership with end_date = 20120615 + $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2))); + $this->callAPISuccess('Email', 'create', array( + 'contact_id' => $membership->contact_id, + 'email' => 'test-member@example.com', + )); + $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id))); + + $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks']; + $actionSchedule['entity_value'] = $membership->membership_type_id; + $this->callAPISuccess('action_schedule', 'create', $actionSchedule); + // end_date=2012-06-15 ; schedule is 2 weeks before end_date + $this->assertCronRuns(array( + array( // After the 2-week mark, send an email + 'time' => '2012-08-15 01:00:00', + 'recipients' => array(array('test-member@example.com')), + ), + )); + + //extend membership - reminder should NOT go out + $this->callAPISuccess('membership', 'create', array('id' => $membership->id, 'end_date' => '2014-01-01')); + $this->assertCronRuns(array( + array( // After the 2-week mark, send an email + 'time' => '2012-09-12 01:00:00', + 'recipients' => array(), + ), + )); + } + /** * For contacts/members which match schedule based on end date, * an email should be sent. -- 2.25.1