Merge pull request #19014 from eileenmcnaughton/cancel
authorSeamus Lee <seamuslee001@gmail.com>
Wed, 2 Dec 2020 23:12:45 +0000 (10:12 +1100)
committerGitHub <noreply@github.com>
Wed, 2 Dec 2020 23:12:45 +0000 (10:12 +1100)
dev/core#927 Add test demonstrating that an extraneous activity is being created & fix

CRM/Contribute/BAO/Contribution.php
ext/contributioncancelactions/contributioncancelactions.php
ext/contributioncancelactions/tests/phpunit/CancelTest.php
tests/phpunit/CRM/Member/Form/MembershipTest.php
tests/phpunit/CRMTraits/Financial/OrderTrait.php
tests/phpunit/api/v3/MembershipTest.php

index 236c1c203e2527d17dcea9de69e6d13a3fc09289..b7bbf5f323715235ec3f5d1d65d12254eb2e71e6 100644 (file)
@@ -935,45 +935,6 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
   protected static function cancel($memberships, $contributionId, $membershipStatuses, $participant, $oldStatus, $pledgePayment, $pledgeID, $pledgePaymentIDs, $contributionStatusId) {
     // @fixme https://lab.civicrm.org/dev/core/issues/927 Cancelling membership etc is not desirable for all use-cases and we should be able to disable it
     $participantStatuses = CRM_Event_PseudoConstant::participantStatus();
-    if (is_array($memberships)) {
-      foreach ($memberships as $membership) {
-        $update = TRUE;
-        //Update Membership status if there is no other completed contribution associated with the membership.
-        $relatedContributions = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id, TRUE);
-        foreach ($relatedContributions as $contriId) {
-          if ($contriId == $contributionId) {
-            continue;
-          }
-          $statusId = CRM_Core_DAO::getFieldValue('CRM_Contribute_BAO_Contribution', $contriId, 'contribution_status_id');
-          if (CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $statusId) === 'Completed') {
-            $update = FALSE;
-          }
-        }
-        if ($membership && $update) {
-          $newStatus = array_search('Cancelled', $membershipStatuses);
-
-          // Create activity
-          $allStatus = CRM_Member_BAO_Membership::buildOptions('status_id', 'get');
-          $activityParam = [
-            'subject' => "Status changed from {$allStatus[$membership->status_id]} to {$allStatus[$newStatus]}",
-            'source_contact_id' => CRM_Core_Session::singleton()->get('userID'),
-            'target_contact_id' => $membership->contact_id,
-            'source_record_id' => $membership->id,
-            'activity_type_id' => 'Change Membership Status',
-            'status_id' => 'Completed',
-            'priority_id' => 'Normal',
-            'activity_date_time' => 'now',
-          ];
-
-          $membership->status_id = $newStatus;
-          $membership->is_override = TRUE;
-          $membership->status_override_end_date = 'null';
-          $membership->save();
-          civicrm_api3('activity', 'create', $activityParam);
-        }
-      }
-    }
-
     if ($participant) {
       $updatedStatusId = array_search('Cancelled', $participantStatuses);
       CRM_Event_BAO_Participant::updateParticipantStatus($participant->id, $oldStatus, $updatedStatusId, TRUE);
index 8665b19d2412e662c2dace501a2718c0f489b7b5..d72a390ef75cbd9c0294c793e5c00bd0a57cfc7f 100644 (file)
@@ -104,6 +104,6 @@ function contributioncancelactions_cancel_related_pending_memberships($contribut
     return;
   }
   foreach ($connectedMemberships as $membershipID) {
-    civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1]);
+    civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1, 'status_override_end_date' => 'null']);
   }
 }
index 946b3484d4511b90477c8d5d0da3b01aada95ae7..567da3f45c96abd47dfc8526951e50422fa99388 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Civi\Api4\Activity;
+use Civi\Api4\Contribution;
 use Civi\Test\Api3TestTrait;
 use Civi\Test\CiviEnvBuilder;
 use Civi\Test\HeadlessInterface;
@@ -13,6 +15,7 @@ use Civi\Api4\Event;
 use Civi\Api4\PriceField;
 use Civi\Api4\Participant;
 use PHPUnit\Framework\TestCase;
+use Civi\Test\ContactTestTrait;
 
 /**
  * FIXME - Add test description.
@@ -31,6 +34,7 @@ use PHPUnit\Framework\TestCase;
 class CancelTest extends TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
 
   use Api3TestTrait;
+  use ContactTestTrait;
 
   /**
    * Created ids.
@@ -276,6 +280,45 @@ class CancelTest extends TestCase implements HeadlessInterface, HookInterface, T
     $this->assertEquals('', $afterPledge['pledge_total_paid']);
   }
 
+  /**
+   * Test cancelling a contribution with a membership on the contribution edit
+   * form.
+   *
+   * @throws \API_Exception
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
+  public function testCancelFromContributionForm(): void {
+    $this->createContact();
+    $this->createMembershipType();
+    $this->createMembershipOrder();
+    $this->createLoggedInUser();
+    $formValues = [
+      'id' => $this->ids['Contribution'][0],
+      'contact_id' => $this->ids['contact'][0],
+      'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Cancelled'),
+    ];
+    $form = new CRM_Contribute_Form_Contribution();
+    $_SERVER['REQUEST_METHOD'] = 'GET';
+    $form->controller = new CRM_Core_Controller();
+    $form->controller->setStateMachine(new CRM_Core_StateMachine($form->controller));
+    $form->testSubmit($formValues, CRM_Core_Action::UPDATE);
+
+    $contribution = Contribution::get()
+      ->addWhere('id', '=', $this->ids['Contribution'][0])
+      ->addSelect('contribution_status_id:name')
+      ->execute()->first();
+    $this->assertEquals('Cancelled', $contribution['contribution_status_id:name']);
+    $membership = $this->callAPISuccessGetSingle('Membership', []);
+    $this->assertEquals('Cancelled', CRM_Core_PseudoConstant::getName('CRM_Member_BAO_Membership', 'status_id', $membership['status_id']));
+    $activity = Activity::get()
+      ->addSelect('subject', 'source_record_id', 'status_id')
+      ->addWhere('activity_type_id:name', '=', 'Change Membership Status')
+      ->execute();
+    $this->assertCount(1, $activity);
+    $this->assertEquals('Status changed from Pending to Cancelled', $activity->first()['subject']);
+  }
+
   /**
    * Create an event and an order for a participant in that event.
    *
index 61a88b684e5e90a50c8f8453783a7534c3a126e6..3682925eb6c3a1b9246b313b7e0bf21eeb9bc5c5 100644 (file)
@@ -25,6 +25,8 @@
  */
 class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
 
+  use CRMTraits_Financial_OrderTrait;
+
   protected $_individualId;
   protected $_contribution;
   protected $_financialTypeId = 1;
@@ -1320,41 +1322,29 @@ Expires: ',
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    */
-  public function testContributionFormStatusUpdate() {
+  public function testContributionFormStatusUpdate(): void {
 
-    $this->_individualId = $this->createLoggedInUser();
-    $membershipId = $this->contactMembershipCreate([
-      'contact_id' => $this->_individualId,
-      'membership_type_id' => $this->membershipTypeAnnualFixedID,
-      'status_id' => 'New',
-    ]);
+    $this->_contactID = $this->createLoggedInUser();
+    $this->createContributionAndMembershipOrder();
 
     $params = [
       'total_amount' => 50,
       'financial_type_id' => 2,
-      'contact_id' => $this->_individualId,
+      'contact_id' => $this->_contactID,
       'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
       'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Cancelled'),
     ];
 
-    $contriParams = [
-      'membership_id' => $membershipId,
-      'total_amount' => 50,
-      'financial_type_id' => 2,
-      'contact_id' => $this->_individualId,
-    ];
-    $contribution = CRM_Member_BAO_Membership::recordMembershipContribution($contriParams);
-
     //Update Contribution to Cancelled.
     $form = new CRM_Contribute_Form_Contribution();
-    $form->_id = $params['id'] = $contribution->id;
+    $form->_id = $params['id'] = $this->ids['Contribution'][0];
     $form->_mode = NULL;
     $form->_contactID = $this->_individualId;
     $form->testSubmit($params, CRM_Core_Action::UPDATE);
-    $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]);
+    $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_contactID]);
 
     //Assert membership status overrides when the contribution cancelled.
-    $this->assertEquals($membership['is_override'], TRUE);
+    $this->assertEquals(TRUE, $membership['is_override']);
     $this->assertEquals($membership['status_id'], $this->callAPISuccessGetValue('MembershipStatus', [
       'return' => 'id',
       'name' => 'Cancelled',
index fbbd2347eb9447e30ae1a72948693d4bece0b62c..8652d40ac20e9d41c14d82b7eb421a6b47cef09a 100644 (file)
@@ -74,7 +74,7 @@ trait CRMTraits_Financial_OrderTrait {
    *
    * @throws \CRM_Core_Exception
    */
-  protected function createContributionAndMembershipOrder() {
+  protected function createContributionAndMembershipOrder(): void {
     $this->ids['membership_type'][0] = $this->membershipTypeCreate();
     $orderID = $this->callAPISuccess('Order', 'create', [
       'financial_type_id' => 'Donation',
@@ -110,6 +110,10 @@ trait CRMTraits_Financial_OrderTrait {
             'contact_id' => $this->_contactID,
             'membership_type_id' => 'General',
             'source' => 'Payment',
+            // This is necessary because Membership_BAO otherwise ignores the
+            // pending status. I do have a fix but it's held up behind other pending-review PRs
+            // so this should be temporary until we get the membership PRs flowing.
+            'skipStatusCal' => TRUE,
           ],
           'line_item' => $this->getMembershipLineItem(),
         ],
index bec416700c6f26cfc8d4c2e51b460deefa1b085d..4550d1eff110acde3b783d294b3e3382a55eb61f 100644 (file)
@@ -139,24 +139,17 @@ class api_v3_MembershipTest extends CiviUnitTestCase {
 
   /**
    * Test Activity creation on cancellation of membership contribution.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testActivityForCancelledContribution() {
+  public function testActivityForCancelledContribution(): void {
     $contactId = $this->createLoggedInUser();
-    $membershipID = $this->contactMembershipCreate($this->_params);
-
-    $ContributionCreate = $this->callAPISuccess('Contribution', 'create', [
-      'financial_type_id' => 'Member Dues',
-      'total_amount' => 100,
-      'contact_id' => $this->_params['contact_id'],
-    ]);
-    $this->callAPISuccess('MembershipPayment', 'create', [
-      'sequential' => 1,
-      'contribution_id' => $ContributionCreate['id'],
-      'membership_id' => $membershipID,
-    ]);
 
+    $this->createContributionAndMembershipOrder();
+    $membershipID = $this->callAPISuccessGetValue('MembershipPayment', ['return' => 'id']);
     $form = new CRM_Contribute_Form_Contribution();
-    $form->_id = $ContributionCreate['id'];
+    $form->_id = $this->ids['Contribution'][0];
     $form->testSubmit([
       'total_amount' => 100,
       'financial_type_id' => 1,
@@ -169,7 +162,7 @@ class api_v3_MembershipTest extends CiviUnitTestCase {
     $this->callAPISuccessGetSingle('Activity', [
       'activity_type_id' => 'Membership Signup',
       'source_record_id' => $membershipID,
-      'subject' => 'General - Payment - Status: test status',
+      'subject' => 'General - Payment - Status: Pending',
     ]);
     $this->callAPISuccessGetSingle('Activity', [
       'activity_type_id' => 'Change Membership Status',