CRM-15376 - Porting fixes from https://github.com/civicrm/civicrm-core/pull/4233...
authorDave Greenberg <dave@civicrm.org>
Wed, 8 Oct 2014 23:46:47 +0000 (16:46 -0700)
committerDave Greenberg <dave@civicrm.org>
Wed, 8 Oct 2014 23:46:47 +0000 (16:46 -0700)
----------------------------------------
* CRM-15376:
  https://issues.civicrm.org/jira/browse/CRM-15376

CRM/Core/BAO/ActionSchedule.php
tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php

index 03b5c15991cd81881b5c935b418b0b397e409c62..d48cc36f942f2fd5e26ef6aa0836c1e5d61a603d 100755 (executable)
@@ -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}";
 
index 7de69679f874daba8087e833811fcf9eee68f66c..d9ea1cb18bc93de3ab0a65881480ce2faccf1af7 100644 (file)
@@ -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' => '<p>body sched_membership_end_2month</p>',
+      '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.