From 85f55d40988ba972826a4bca651241d9e49e6cf3 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Thu, 16 Jun 2022 12:25:15 +1200 Subject: [PATCH] Fix bug whereby editing contribution_recur.amount was not updating single-row line items Update CRM/Contribute/BAO/ContributionRecur.php yep - I got away with this in the test / my step through cos they were both one - Thanks Co-authored-by: Rich Lott Update tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php Co-authored-by: Rich Lott Update tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php Co-authored-by: Rich Lott Update tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php Co-authored-by: Rich Lott Update CRM/Contribute/BAO/ContributionRecur.php Co-authored-by: Matthew Wire --- CRM/Contribute/BAO/ContributionRecur.php | 38 ++++++++++++++++++- .../Contribute/BAO/ContributionRecurTest.php | 25 ++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/CRM/Contribute/BAO/ContributionRecur.php b/CRM/Contribute/BAO/ContributionRecur.php index 5928599940..5b24f61964 100644 --- a/CRM/Contribute/BAO/ContributionRecur.php +++ b/CRM/Contribute/BAO/ContributionRecur.php @@ -9,15 +9,17 @@ +--------------------------------------------------------------------+ */ +use Brick\Money\Money; use Civi\Api4\Contribution; use Civi\Api4\ContributionRecur; +use Civi\Api4\LineItem; /** * * @package CRM * @copyright CiviCRM LLC https://civicrm.org/licensing */ -class CRM_Contribute_BAO_ContributionRecur extends CRM_Contribute_DAO_ContributionRecur { +class CRM_Contribute_BAO_ContributionRecur extends CRM_Contribute_DAO_ContributionRecur implements Civi\Test\HookInterface { /** * Create recurring contribution. @@ -94,6 +96,40 @@ class CRM_Contribute_BAO_ContributionRecur extends CRM_Contribute_DAO_Contributi return $recurring; } + /** + * Event fired after modifying a recurring contribution. + * @param \Civi\Core\Event\PostEvent $event + */ + public static function self_hook_civicrm_post(\Civi\Core\Event\PostEvent $event) { + if ($event->action === 'edit') { + if (is_numeric($event->object->amount)) { + $templateContribution = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($event->object->id); + if (empty($templateContribution['id'])) { + return; + } + $lines = LineItem::get(FALSE) + ->addWhere('contribution_id', '=', $templateContribution['id']) + ->addWhere('contribution_id.is_template', '=', TRUE) + ->addSelect('contribution_id.total_amount') + ->execute(); + if (count($lines) === 1) { + $contributionAmount = $lines->first()['contribution_id.total_amount']; + // USD here is just ensuring both are in the same format. + if (Money::of($contributionAmount, 'USD')->compareTo(Money::of($event->object->amount, 'USD'))) { + // If different then we need to update + // the contribution. Note that if this is being called + // as a result of the contribution having been updated then there will + // be no difference. + Contribution::update(FALSE) + ->addWhere('id', '=', $templateContribution['id']) + ->setValues(['total_amount' => $event->object->amount]) + ->execute(); + } + } + } + } + } + /** * Check if there is a recurring contribution with the same trxn_id or invoice_id. * diff --git a/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php b/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php index fe83485bcf..6ad62e3ad6 100644 --- a/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php +++ b/tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php @@ -9,7 +9,9 @@ +--------------------------------------------------------------------+ */ +use Civi\Api4\Contribution; use Civi\Api4\ContributionRecur; +use Civi\Api4\LineItem; /** * Class CRM_Contribute_BAO_ContributionRecurTest @@ -284,7 +286,7 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase { // Make sure a template contribution exists. $templateContributionId = CRM_Contribute_BAO_ContributionRecur::ensureTemplateContributionExists($contributionRecur['id']); $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']); - $templateContribution = \Civi\Api4\Contribution::get(FALSE) + $templateContribution = Contribution::get(FALSE) ->addSelect('*', 'custom.*') ->addWhere('contribution_recur_id', '=', $contributionRecur['id']) ->addWhere('is_template', '=', 1) @@ -378,7 +380,7 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase { $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params); $contributionRecur = reset($contributionRecur['values']); // Create the template - $templateContrib = $this->callAPISuccess('Contribution', 'create', [ + $templateContribution = $this->callAPISuccess('Contribution', 'create', [ 'contribution_recur_id' => $contributionRecur['id'], 'total_amount' => '3.00', 'financial_type_id' => 1, @@ -390,13 +392,14 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase { 'receive_date' => 'yesterday', 'is_template' => 1, ]); + // Now update the template amount so we can test that this route updates the recur. $this->callAPISuccess('Contribution', 'create', [ - 'id' => $templateContrib['id'], + 'id' => $templateContribution['id'], 'contribution_recur_id' => $contributionRecur['id'], 'total_amount' => '2.00', 'currency' => 'USD', ]); - $updatedContributionRecur = \Civi\Api4\ContributionRecur::get(FALSE) + $updatedContributionRecur = ContributionRecur::get() ->addWhere('id', '=', $contributionRecur['id']) ->execute() ->first(); @@ -406,6 +409,20 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase { strtotime($contributionRecur['modified_date']), strtotime($updatedContributionRecur['modified_date']) ); + // Now check the reverse - update the recur & the template should update as there + // is a single line item. + ContributionRecur::update() + ->addWhere('id', '=', $contributionRecur['id']) + ->setValues(['amount' => 6]) + ->execute(); + + $this->assertEquals(6, Contribution::get() + ->addWhere('id', '=', $templateContribution['id']) + ->addSelect('total_amount')->execute()->first()['total_amount']); + $this->assertEquals(6, LineItem::get() + ->addWhere('contribution_id', '=', $templateContribution['id']) + ->addGroupBy('contribution_id') + ->addSelect('SUM(line_total) AS total_amount')->execute()->first()['total_amount']); } /** -- 2.25.1