From 76fc5d355880a98b1919c5fa4ac734bd0a35e877 Mon Sep 17 00:00:00 2001 From: Jon Goldberg Date: Tue, 14 Dec 2021 19:05:04 -0500 Subject: [PATCH] membership#14: calculate lifetime memberships more accurately --- CRM/Member/BAO/Membership.php | 34 ++++++-------- .../phpunit/CRM/Member/BAO/MembershipTest.php | 45 +++++++++++++++++++ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/CRM/Member/BAO/Membership.php b/CRM/Member/BAO/Membership.php index 3a04e646c9..082efddbde 100644 --- a/CRM/Member/BAO/Membership.php +++ b/CRM/Member/BAO/Membership.php @@ -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; } diff --git a/tests/phpunit/CRM/Member/BAO/MembershipTest.php b/tests/phpunit/CRM/Member/BAO/MembershipTest.php index 57dc51f416..8df9749e31 100644 --- a/tests/phpunit/CRM/Member/BAO/MembershipTest.php +++ b/tests/phpunit/CRM/Member/BAO/MembershipTest.php @@ -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 -- 2.25.1