From 57d376bbbdbe9828dcd14fd3242d7437911b3433 Mon Sep 17 00:00:00 2001 From: eileenmcnaugton Date: Mon, 5 Sep 2016 18:21:34 +1200 Subject: [PATCH 1/2] CRM-18236 fix for double-sending reminders Conflicts: tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php --- CRM/Core/BAO/ActionSchedule.php | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php index c0d642ff4598..b47ec9ecf63e 100755 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -1254,7 +1254,7 @@ public static function buildRecipientContacts($mappingID, $now, $params = array( } // ( now >= date_built_from_start_time ) OR ( now = absolute_date ) - $dateClause = "reminder.id IS NULL AND {$startDate}"; + $dateClause = $startDate ? " AND {$startDate} " : ''; // start composing query $selectClause = 'SELECT ' . implode(', ', $select); @@ -1272,26 +1272,37 @@ public static function buildRecipientContacts($mappingID, $now, $params = array( {$fromClause} {$joinClause} LEFT JOIN {$reminderJoinClause} -{$whereClause} {$limitWhereClause} AND {$dateClause} {$notINClause} +{$whereClause} AND reminder.id IS NULL {$limitWhereClause} {$dateClause} {$notINClause} "; // In some cases reference_date got outdated due to many reason e.g. In Membership renewal end_date got extended // which means reference date mismatches with the end_date where end_date may be used as the start_action_date // criteria for some schedule reminder so in order to send new reminder we INSERT new reminder with new reference_date // value via UNION operation + // We need to add in reminders that + // have not already had a reminder for the current end date and HAVE had a reminder for a prior end date for the same reminder. + // These will have been excluded earlier. if (strpos($selectColumns, 'reference_date') !== FALSE) { - $dateClause = str_replace('reminder.id IS NULL', 'reminder.id IS NOT NULL', $dateClause); $referenceQuery = " INSERT INTO civicrm_action_log ({$selectColumns}) {$selectClause} {$fromClause} {$joinClause} LEFT JOIN {$reminderJoinClause} -{$whereClause} {$limitWhereClause} {$notINClause} AND {$dateClause} AND - reminder.action_date_time IS NOT NULL AND - reminder.reference_date IS NOT NULL -GROUP BY reminder.id, reminder.reference_date -HAVING reminder.id = MAX(reminder.id) AND reminder.reference_date <> {$dateField} + LEFT JOIN ( + SELECT entity_id, entity_table + {$fromClause} + {$joinClause} + LEFT JOIN {$reminderJoinClause} + {$whereClause} {$limitWhereClause} {$dateClause} {$notINClause} + AND reminder.reference_date = $dateField + ) as already_sent ON e.id = already_sent.entity_id AND already_sent.entity_table = '{$mapping->entity}' +{$whereClause} {$limitWhereClause} {$notINClause} {$dateClause} + AND reminder.id IS NOT NULL + AND reminder.reference_date IS NOT NULL + AND reminder.reference_date <> $dateField + AND already_sent.entity_id IS NULL + GROUP BY e.id "; } From bdeecafba4eb582be1c93b5b6d02613819e63772 Mon Sep 17 00:00:00 2001 From: Andrew Cormick-Dockery Date: Mon, 5 Sep 2016 22:39:26 +0000 Subject: [PATCH 2/2] CRM-18236 For some reason this query is not working well on entity_id - but does on entity_table --- CRM/Core/BAO/ActionSchedule.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php index b47ec9ecf63e..55496cbc1a4f 100755 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -29,8 +29,6 @@ * * @package CRM * @copyright CiviCRM LLC (c) 2004-2015 - * $Id$ - * */ /** @@ -1220,10 +1218,10 @@ public static function buildRecipientContacts($mappingID, $now, $params = array( $select[] = 'e.id as entity_id'; $select[] = "'{$mapping->entity}' as entity_table"; $select[] = "{$actionSchedule->id} as action_schedule_id"; - $reminderJoinClause = "civicrm_action_log reminder ON reminder.contact_id = {$contactField} AND -reminder.entity_id = e.id AND -reminder.entity_table = '{$mapping->entity}' AND -reminder.action_schedule_id = %1"; + $reminderJoinClause = "civicrm_action_log reminder ON reminder.contact_id = {$contactField} + AND reminder.entity_id = e.id + AND reminder.entity_table = '{$mapping->entity}' + AND reminder.action_schedule_id = %1"; if ($anniversary) { // only consider reminders less than 11 months ago @@ -1280,8 +1278,9 @@ public static function buildRecipientContacts($mappingID, $now, $params = array( // criteria for some schedule reminder so in order to send new reminder we INSERT new reminder with new reference_date // value via UNION operation // We need to add in reminders that - // have not already had a reminder for the current end date and HAVE had a reminder for a prior end date for the same reminder. - // These will have been excluded earlier. + // have not already had a reminder for the current end date and HAVE had a reminder for a different + // end date for the same reminder. These will have been excluded earlier, on the basis of a reminder having gone out + // so we want to selectively re-add them. if (strpos($selectColumns, 'reference_date') !== FALSE) { $referenceQuery = " INSERT INTO civicrm_action_log ({$selectColumns}) @@ -1301,7 +1300,7 @@ public static function buildRecipientContacts($mappingID, $now, $params = array( AND reminder.id IS NOT NULL AND reminder.reference_date IS NOT NULL AND reminder.reference_date <> $dateField - AND already_sent.entity_id IS NULL + AND already_sent.entity_table IS NULL GROUP BY e.id "; }