membership#14: calculate lifetime memberships more accurately
authorJon Goldberg <jon@megaphonetech.com>
Wed, 15 Dec 2021 00:05:04 +0000 (19:05 -0500)
committerJon Goldberg <jon@megaphonetech.com>
Wed, 15 Dec 2021 03:36:24 +0000 (22:36 -0500)
CRM/Member/BAO/Membership.php
tests/phpunit/CRM/Member/BAO/MembershipTest.php

index 3a04e646c9d8ae238f7c964863a9f8aa379e4e72..082efddbde4c47e7715c3b9f7ade3af902ba7503 100644 (file)
@@ -2377,8 +2377,7 @@ WHERE {$whereClause}";
   }
 
   /**
-   * Returns the membership types for a particular contact
-   * who has lifetime membership without end date.
+   * Returns the membership types for a contact, optionally filtering to lifetime memberships only.
    *
    * @param int $contactID
    * @param bool $isTest
@@ -2386,33 +2385,26 @@ WHERE {$whereClause}";
    *
    * @return array
    */
-  public static function getAllContactMembership($contactID, $isTest = FALSE, $onlyLifeTime = FALSE) {
+  public static function getAllContactMembership($contactID, $isTest = FALSE, $onlyLifeTime = FALSE) : array {
     $contactMembershipType = [];
     if (!$contactID) {
       return $contactMembershipType;
     }
 
-    $dao = new CRM_Member_DAO_Membership();
-    $dao->contact_id = $contactID;
-    $pendingStatusId = array_search('Pending', CRM_Member_PseudoConstant::membershipStatus());
-    $dao->whereAdd("status_id != $pendingStatusId");
-
-    if ($isTest) {
-      $dao->is_test = $isTest;
-    }
-    else {
-      $dao->whereAdd('is_test IS NULL OR is_test = 0');
-    }
+    $membershipQuery = \Civi\Api4\Membership::get(FALSE)
+      ->addWhere('contact_id', '=', $contactID)
+      ->addWhere('status_id:name', '<>', 'Pending')
+      ->addWhere('is_test', '=', $isTest)
+      //CRM-4297
+      ->addOrderBy('end_date', 'DESC');
 
     if ($onlyLifeTime) {
-      $dao->whereAdd('end_date IS NULL');
+      // membership#14 - use duration_unit for calculating lifetime, not join/end date.
+      $membershipQuery->addWhere('membership_type_id.duration_unit', '=', 'lifetime');
     }
-
-    $dao->find();
-    while ($dao->fetch()) {
-      $membership = [];
-      CRM_Core_DAO::storeValues($dao, $membership);
-      $contactMembershipType[$dao->membership_type_id] = $membership;
+    $memberships = $membershipQuery->execute();
+    foreach ($memberships as $membership) {
+      $contactMembershipType[$membership['membership_type_id']] = $membership;
     }
     return $contactMembershipType;
   }
index 57dc51f4160fe828fec41be2516aa0a7f14763dd..8df9749e31f36b9bcacb12cba6445c29871053d5 100644 (file)
@@ -340,6 +340,51 @@ class CRM_Member_BAO_MembershipTest extends CiviUnitTestCase {
     $this->contactDelete($contactId);
   }
 
+  public function testGetAllContactMembership() {
+    $lifetimeTypeId = $this->membershipTypeCreate([
+      'name' => 'Lifetime',
+      'duration_unit' => 'lifetime',
+    ]);
+
+    // Contact 1 tests the "lifetimeOnly" code path.
+    $contactId = $this->individualCreate();
+
+    $pendingStatusId = array_search('Pending', CRM_Member_PseudoConstant::membershipStatus());
+    $cancelledStatusId = array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus());
+    $currentStatusId = array_search('Current', CRM_Member_PseudoConstant::membershipStatus());
+    $params = [
+      'contact_id' => $contactId,
+      'membership_type_id' => $this->_membershipTypeID,
+      'source' => 'Payment',
+      'is_override' => 1,
+      'status_id' => $pendingStatusId,
+    ];
+
+    CRM_Member_BAO_Membership::create($params);
+    $membershipId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id', 'contact_id', 'Database check for created membership.');
+    $memberships = CRM_Member_BAO_Membership::getAllContactMembership($contactId, FALSE, TRUE);
+    $this->assertEmpty($memberships, 'Verify pending membership is NOT retrieved.');
+    $this->membershipDelete($membershipId);
+
+    $params['status_id'] = $cancelledStatusId;
+    CRM_Member_BAO_Membership::create($params);
+    $membershipId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id', 'contact_id', 'Database check for created membership.');
+    $memberships = CRM_Member_BAO_Membership::getAllContactMembership($contactId, FALSE, TRUE);
+    $this->assertEmpty($memberships, 'Verify cancelled membership is NOT retrieved.');
+    $this->membershipDelete($membershipId);
+
+    // Lifetime membership.
+    $params['status_id'] = $currentStatusId;
+    $params['membership_type_id'] = $lifetimeTypeId;
+    CRM_Member_BAO_Membership::create($params);
+    $membershipId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id', 'contact_id', 'Database check for created membership.');
+    $memberships = CRM_Member_BAO_Membership::getAllContactMembership($contactId, FALSE, TRUE);
+    $this->assertEquals($membershipId, $memberships[$lifetimeTypeId]['id'], 'Verify current (lifetime) membership IS retrieved.');
+    $this->membershipDelete($membershipId);
+
+    $this->contactDelete($contactId);
+  }
+
   /**
    * Get the contribution.
    * page id from the membership record