From 7e9abd5a2bdadc458ac8a980cd2e72baec7a9c7c Mon Sep 17 00:00:00 2001 From: eileen Date: Sun, 2 Aug 2020 09:58:39 +1200 Subject: [PATCH] Use saved contribution's line items rather than the primaryContributionID By the time we reach this point in the code we know that 1) the contributon exists and it has an id 2) it has line items - either those created in it's pending stage or those calculated in repeattransaction Therefore we can reasonably assume these line items are accurate now and use them, rather than the confusing primaryContributionID that we have doubts about the validity of --- CRM/Contribute/BAO/Contribution.php | 7 +++---- tests/phpunit/api/v3/ContributionTest.php | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index 791ebe27a5..872ac8b70a 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -4511,7 +4511,6 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac if ($contributionParams['contribution_status_id'] === $completedContributionStatusID) { self::updateMembershipBasedOnCompletionOfContribution( $contribution, - $primaryContributionID, $changeDate ); } @@ -5211,13 +5210,12 @@ LEFT JOIN civicrm_contribution on (civicrm_contribution.contact_id = civicrm_co * load them in this function. Code clean up would compensate for any minor performance implication. * * @param \CRM_Contribute_BAO_Contribution $contribution - * @param int $primaryContributionID * @param string $changeDate * * @throws \CRM_Core_Exception * @throws \CiviCRM_API3_Exception */ - public static function updateMembershipBasedOnCompletionOfContribution($contribution, $primaryContributionID, $changeDate) { + public static function updateMembershipBasedOnCompletionOfContribution($contribution, $changeDate) { $memberships = self::getRelatedMemberships($contribution->id); foreach ($memberships as $membership) { $membershipParams = [ @@ -5254,10 +5252,11 @@ LIMIT 1;"; // Passing num_terms to the api triggers date calculations, but for pending memberships these may be already calculated. // sigh - they should be consistent but removing the end date check causes test failures & maybe UI too? // The api assumes num_terms is a special sauce for 'is_renewal' so we need to not pass it when updating a pending to completed. + // ... except testCompleteTransactionMembershipPriceSetTwoTerms hits this line so the above is obviously not true.... // @todo once apiv4 ships with core switch to that & find sanity. $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType( $membershipParams['membership_type_id'], - $primaryContributionID + $contribution->id ); } // @todo remove all this stuff in favour of letting the api call further down handle in diff --git a/tests/phpunit/api/v3/ContributionTest.php b/tests/phpunit/api/v3/ContributionTest.php index 70e9db3248..71424285c1 100644 --- a/tests/phpunit/api/v3/ContributionTest.php +++ b/tests/phpunit/api/v3/ContributionTest.php @@ -3459,14 +3459,32 @@ class api_v3_ContributionTest extends CiviUnitTestCase { } /** - * Test membership is renewed when transaction completed. + * Test membership is renewed for 2 terms when transaction completed based on the line item having 2 terms as qty. + * + * Also check that altering the qty for the most recent contribution results in repeattransaction picking it up. */ public function testCompleteTransactionMembershipPriceSetTwoTerms() { $this->createPriceSetWithPage('membership'); $this->setUpPendingContribution($this->_ids['price_field_value'][1]); $this->callAPISuccess('contribution', 'completetransaction', ['id' => $this->_ids['contribution']]); - $membership = $this->callAPISuccess('membership', 'getsingle', ['id' => $this->_ids['membership']]); + $membership = $this->callAPISuccessGetSingle('membership', ['id' => $this->_ids['membership']]); $this->assertEquals(date('Y-m-d', strtotime('yesterday + 2 years')), $membership['end_date']); + + $paymentProcessorID = $this->paymentProcessorAuthorizeNetCreate(); + + $contributionRecurID = $this->callAPISuccess('ContributionRecur', 'create', ['contact_id' => $membership['contact_id'], 'payment_processor_id' => $paymentProcessorID, 'amount' => 20, 'frequency_interval' => 1])['id']; + $this->callAPISuccess('Contribution', 'create', ['id' => $this->_ids['contribution'], 'contribution_recur_id' => $contributionRecurID]); + $this->callAPISuccess('contribution', 'repeattransaction', ['contribution_recur_id' => $contributionRecurID, 'contribution_status_id' => 'Completed']); + $membership = $this->callAPISuccessGetSingle('membership', ['id' => $this->_ids['membership']]); + $this->assertEquals(date('Y-m-d', strtotime('yesterday + 4 years')), $membership['end_date']); + + // Update the most recent contribution to have a qty of 1 in it's line item and then repeat, expecting just 1 year to be added. + $contribution = Contribution::get()->setOrderBy(['id' => 'DESC'])->setSelect(['id'])->execute()->first(); + CRM_Core_DAO::executeQuery('UPDATE civicrm_line_item SET price_field_value_id = ' . $this->_ids['price_field_value'][0] . ' WHERE contribution_id = ' . $contribution['id']); + $this->callAPISuccess('contribution', 'repeattransaction', ['contribution_recur_id' => $contributionRecurID, 'contribution_status_id' => 'Completed']); + $membership = $this->callAPISuccessGetSingle('membership', ['id' => $this->_ids['membership']]); + $this->assertEquals(date('Y-m-d', strtotime('yesterday + 5 years')), $membership['end_date']); + $this->cleanUpAfterPriceSets(); } -- 2.25.1