diff --git a/CRM/Contribute/BAO/ContributionRecur.php b/CRM/Contribute/BAO/ContributionRecur.php index dc0b467ff884fef56e53829cf2ade1dca542a88d..7f80887281a1fc7c6f98c613da1af6941a068cc7 100644 --- a/CRM/Contribute/BAO/ContributionRecur.php +++ b/CRM/Contribute/BAO/ContributionRecur.php @@ -428,14 +428,31 @@ INNER JOIN civicrm_contribution con ON ( con.id = mp.contribution_id ) * @throws \CiviCRM_API3_Exception */ public static function getTemplateContribution($id, $overrides = []) { - $templateContribution = civicrm_api3('Contribution', 'get', [ - 'contribution_recur_id' => $id, - 'options' => ['limit' => 1, 'sort' => ['id DESC']], - 'sequential' => 1, - 'contribution_test' => '', + // use api3 because api4 doesn't handle ContributionRecur yet... + $is_test = civicrm_api3('ContributionRecur', 'getvalue', [ + 'return' => "is_test", + 'id' => $id, ]); - if ($templateContribution['count']) { - $result = array_merge($templateContribution['values'][0], $overrides); + // First look for new-style template contribution with is_template=1 + $templateContributions = \Civi\Api4\Contribution::get() + ->addWhere('contribution_recur_id', '=', $id) + ->addWhere('is_template', '=', 1) + ->addWhere('is_test', '=', $is_test) + ->addOrderBy('id', 'DESC') + ->setLimit(1) + ->execute(); + if (!$templateContributions->count()) { + // Fall back to old style template contributions + $templateContributions = \Civi\Api4\Contribution::get() + ->addWhere('contribution_recur_id', '=', $id) + ->addWhere('is_test', '=', $is_test) + ->addOrderBy('id', 'DESC') + ->setLimit(1) + ->execute(); + } + if ($templateContributions->count()) { + $templateContribution = $templateContributions->first(); + $result = array_merge($templateContribution, $overrides); $result['line_item'] = CRM_Contribute_BAO_ContributionRecur::calculateRecurLineItems($id, $result['total_amount'], $result['financial_type_id']); return $result; } diff --git a/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php b/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php index 0b120f16f43bb59a76a414886b7a1ea357bf473f..bd8370cbceb1bee2e15e56189c0be0fe7e7bdb84 100644 --- a/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php +++ b/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php @@ -94,7 +94,7 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase { } /** - * Test checking if contribution recurr object can allow for changes to financial types. + * Test checking if contribution recur object can allow for changes to financial types. * */ public function testSupportFinancialTypeChange() { @@ -130,4 +130,108 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase { $this->assertEquals('XAU', $dao->currency, 'Edit clobbered recur currency'); } + /** + * Check test contributions aren't picked up as template for non-test recurs + * + */ + public function testGetTemplateContributionMatchTest1() { + $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params); + // Create a first contrib + $firstContrib = $this->callAPISuccess('Contribution', 'create', [ + 'contribution_recur_id' => $contributionRecur['id'], + 'total_amount' => '3.00', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'currency' => 'USD', + 'contact_id' => $this->individualCreate(), + 'contribution_status_id' => 1, + 'receive_date' => 'yesterday', + ]); + // Create a test contrib - should not be picked up as template for non-test recur + $this->callAPISuccess('Contribution', 'create', [ + 'contribution_recur_id' => $contributionRecur['id'], + 'total_amount' => '3.00', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'currency' => 'USD', + 'contact_id' => $this->individualCreate(), + 'contribution_status_id' => 1, + 'receive_date' => 'yesterday', + 'is_test' => 1, + ]); + $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']); + $this->assertEquals($firstContrib['id'], $fetchedTemplate['id']); + } + + /** + * Check non-test contributions aren't picked up as template for test recurs + * + */ + public function testGetTemplateContributionMatchTest() { + $params = $this->_params; + $params['is_test'] = 1; + $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $params); + // Create a first test contrib + $firstContrib = $this->callAPISuccess('Contribution', 'create', [ + 'contribution_recur_id' => $contributionRecur['id'], + 'total_amount' => '3.00', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'currency' => 'USD', + 'contact_id' => $this->individualCreate(), + 'contribution_status_id' => 1, + 'receive_date' => 'yesterday', + 'is_test' => 1, + ]); + // Create a non-test contrib - should not be picked up as template for non-test recur + // This shouldn't occur - a live contrib against a test recur, but that's not the point... + $this->callAPISuccess('Contribution', 'create', [ + 'contribution_recur_id' => $contributionRecur['id'], + 'total_amount' => '3.00', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'currency' => 'USD', + 'contact_id' => $this->individualCreate(), + 'contribution_status_id' => 1, + 'receive_date' => 'yesterday', + 'is_test' => 0, + ]); + $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']); + $this->assertEquals($firstContrib['id'], $fetchedTemplate['id']); + } + + /** + * Test that is_template contribution is used where available + * + */ + public function testGetTemplateContributionNewTemplate() { + $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params); + // Create the template + $templateContrib = $this->callAPISuccess('Contribution', 'create', [ + 'contribution_recur_id' => $contributionRecur['id'], + 'total_amount' => '3.00', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'currency' => 'USD', + 'contact_id' => $this->individualCreate(), + 'contribution_status_id' => 1, + 'receive_date' => 'yesterday', + 'is_template' => 1, + ]); + // Create another normal contrib + $this->callAPISuccess('Contribution', 'create', [ + 'contribution_recur_id' => $contributionRecur['id'], + 'total_amount' => '3.00', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'currency' => 'USD', + 'contact_id' => $this->individualCreate(), + 'contribution_status_id' => 1, + 'receive_date' => 'yesterday', + ]); + $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']); + // Fetched template should be the is_template, not the latest contrib + $this->assertEquals($fetchedTemplate['id'], $templateContrib['id']); + } + }