From: jitendrapurohit Date: Fri, 15 Apr 2016 11:23:25 +0000 (+0530) Subject: CRM-18316 - Pledge scheduled dates are created incorrectly at the end of a month X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=7e66081a3c86bada4d95bd5e7437200dde9778fe;p=civicrm-core.git CRM-18316 - Pledge scheduled dates are created incorrectly at the end of a month minor fix add comments --- diff --git a/CRM/Pledge/BAO/PledgePayment.php b/CRM/Pledge/BAO/PledgePayment.php index d670d57584..87da53ba1e 100644 --- a/CRM/Pledge/BAO/PledgePayment.php +++ b/CRM/Pledge/BAO/PledgePayment.php @@ -506,28 +506,23 @@ WHERE civicrm_pledge.id = %2 * CRM_Utils_Date::intervalAdd( $params['frequency_unit'], $i * ($params['frequency_interval']) , calculateBaseScheduledDate( &$params ))) * * @param array $params - * @param int $paymentNo * * @return array * Next scheduled date as an array */ - public static function calculateBaseScheduleDate(&$params, $paymentNo = NULL) { + public static function calculateBaseScheduleDate(&$params) { $date = array(); $scheduled_date = CRM_Utils_Date::processDate($params['scheduled_date']); $date['year'] = (int) substr($scheduled_date, 0, 4); $date['month'] = (int) substr($scheduled_date, 4, 2); $date['day'] = (int) substr($scheduled_date, 6, 2); - $date['hour'] = (int) substr($scheduled_date, 7, 2); - $date['minute'] = (int) substr($scheduled_date, 9, 2); - $date['seconds'] = (int) substr($scheduled_date, 11, 2); // calculation of schedule date according to frequency day of period // frequency day is not applicable for daily installments if ($params['frequency_unit'] != 'day' && $params['frequency_unit'] != 'year') { if ($params['frequency_unit'] != 'week') { // CRM-18316: To calculate pledge scheduled dates at the end of a month. $date['day'] = $params['frequency_day']; - $interval = $paymentNo * ($params['frequency_interval']); - $lastDayOfMonth = date('t', mktime($date['hour'], $date['minute'], $date['seconds'], $date['month'] + $interval, 1, $date['year'])); + $lastDayOfMonth = date('t', mktime(0, 0, 0, $date['month'], 1, $date['year'])); if ($lastDayOfMonth < $date['day']) { $date['day'] = $lastDayOfMonth; } @@ -566,13 +561,32 @@ WHERE civicrm_pledge.id = %2 * formatted date */ public static function calculateNextScheduledDate(&$params, $paymentNo, $basePaymentDate = NULL) { + $interval = $paymentNo * ($params['frequency_interval']); if (!$basePaymentDate) { - $basePaymentDate = self::calculateBaseScheduleDate($params, $paymentNo); + $basePaymentDate = self::calculateBaseScheduleDate($params); + } + + //CRM-18316 - change $basePaymentDate for the end dates of the month eg: 29, 30 or 31. + if ($params['frequency_unit'] == 'month' && in_array($params['frequency_day'], array(29, 30, 31))) { + $frequency = $params['frequency_day']; + extract(date_parse($basePaymentDate)); + $lastDayOfMonth = date('t', mktime($hour, $minute, $second, $month + $interval, 1, $year)); + // Take the last day in case the current month is Feb or frequency_day is set to 31. + if (in_array($lastDayOfMonth, array(28, 29)) || $frequency == 31) { + $frequency = 0; + $interval++; + } + $basePaymentDate = array( + 'M' => $month, + 'd' => $frequency, + 'Y' => $year, + ); } + return CRM_Utils_Date::format( CRM_Utils_Date::intervalAdd( $params['frequency_unit'], - $paymentNo * ($params['frequency_interval']), + $interval, $basePaymentDate ) ); diff --git a/tests/phpunit/CRM/Pledge/BAO/PledgePaymentTest.php b/tests/phpunit/CRM/Pledge/BAO/PledgePaymentTest.php index 544455674f..96eb69a672 100644 --- a/tests/phpunit/CRM/Pledge/BAO/PledgePaymentTest.php +++ b/tests/phpunit/CRM/Pledge/BAO/PledgePaymentTest.php @@ -262,47 +262,58 @@ class CRM_Pledge_BAO_PledgePaymentTest extends CiviUnitTestCase { 'frequency_day' => 31, 'frequency_interval' => 1, ); - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 2); - $this->assertEquals('20110731000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 2); + $this->assertEquals('20110731000000', $nextScheduleDate); // assert pledge scheduled date for month february. - $scheduleDateForFeb = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 9); - $this->assertEquals('20120229000000', $scheduleDateForFeb); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 9); + $this->assertEquals('20120229000000', $nextScheduleDate); //Case: Frequency day = 31 and scheduled date = 31st of any month $params['scheduled_date'] = '20110131'; $params['frequency_day'] = 31; - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 1); - $this->assertEquals('20110228000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 1); + $this->assertEquals('20110228000000', $nextScheduleDate); //Case: Frequency day = 30 and scheduled date = 30th of any month $params['scheduled_date'] = '20110130'; $params['frequency_day'] = 30; - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 3); - $this->assertEquals('20110430000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 3); + $this->assertEquals('20110430000000', $nextScheduleDate); //Case: Frequency day = 30 and scheduled date = any day of month $params['scheduled_date'] = '20110110'; $params['frequency_day'] = 30; - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 4); - $this->assertEquals('20110530000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 4); + $this->assertEquals('20110530000000', $nextScheduleDate); //Case: Frequency day = any and scheduled date = 31st of any month $params['scheduled_date'] = '20110131'; $params['frequency_day'] = 5; - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 5); - $this->assertEquals('20110605000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 5); + $this->assertEquals('20110605000000', $nextScheduleDate); - //Case: Frequency day = any AND Satrt date = 30th of any month + //Case: Frequency day = any AND scheduled date = 30th of any month $params['scheduled_date'] = '20110130'; $params['frequency_day'] = 10; - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 6); - $this->assertEquals('20110710000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 6); + $this->assertEquals('20110710000000', $nextScheduleDate); - //Case: Frequency day = any AND Satrt date = any day month + //Case: Frequency day = any AND scheduled date = any day month $params['scheduled_date'] = '20110124'; $params['frequency_day'] = 6; - $scheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 7); - $this->assertEquals('20110806000000', $scheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 7); + $this->assertEquals('20110806000000', $nextScheduleDate); + + //Case: Frequency day = 31 AND scheduled date = 29 Feb + $params['scheduled_date'] = '20160229'; + $params['frequency_day'] = 31; + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 5); + $this->assertEquals('20160731000000', $nextScheduleDate); + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 6); + $this->assertEquals('20160831000000', $nextScheduleDate); + //check date for february + $nextScheduleDate = CRM_Pledge_BAO_PledgePayment::calculateNextScheduledDate($params, 12); + $this->assertEquals('20170228000000', $nextScheduleDate); } /**