From 4099a9c51f7137cfb46ae3378278042689fdfec8 Mon Sep 17 00:00:00 2001 From: Alok Patel Date: Wed, 18 Oct 2017 16:12:58 +0530 Subject: [PATCH] CRM-20421: Inherited memberships memberships should be removed if parent's membership is not transferred to another contact after merging. --- CRM/Dedupe/Merger.php | 40 +++++++++++++++- tests/phpunit/api/v3/ContactTest.php | 70 ++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/CRM/Dedupe/Merger.php b/CRM/Dedupe/Merger.php index 47cc8b7435..0d46dfa65b 100644 --- a/CRM/Dedupe/Merger.php +++ b/CRM/Dedupe/Merger.php @@ -429,6 +429,34 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m return $sqls; } + /** + * Based on the provided two contact_ids and a set of tables, remove the + * belongings of the other contact and of their relations. + * + * @param int $otherID + * @param bool $tables + */ + public static function removeContactBelongings($otherID, $tables) { + // CRM-20421: Removing Inherited memberships when memberships of parent are not migrated to new contact. + if (in_array("civicrm_membership", $tables)) { + $membershipIDs = CRM_Utils_Array::collect('id', + CRM_Utils_Array::value('values', + civicrm_api3("Membership", "get", array( + "contact_id" => $otherID, + "return" => "id", + ) + ) + )); + + if (!empty($membershipIDs)) { + civicrm_api3("Membership", "get", array( + 'owner_membership_id' => array('IN' => $membershipIDs), + 'api.Membership.delete' => array('id' => '$value.id'), + )); + } + } + } + /** * Based on the provided two contact_ids and a set of tables, move the * belongings of the other contact to the main one. @@ -1482,7 +1510,7 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m $qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9'; $relTables = CRM_Dedupe_Merger::relTables(); - $submittedCustomFields = $moveTables = $locationMigrationInfo = $tableOperations = array(); + $submittedCustomFields = $moveTables = $locationMigrationInfo = $tableOperations = $removeTables = array(); foreach ($migrationInfo as $key => $value) { if ($value == $qfZeroBug) { @@ -1510,6 +1538,9 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m } } } + elseif (substr($key, 0, 15) == 'move_rel_table_' and $value == '0') { + $removeTables = array_merge($moveTables, $relTables[substr($key, 5)]['tables']); + } } self::mergeLocations($mainId, $otherId, $locationMigrationInfo, $migrationInfo); @@ -1518,6 +1549,13 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m CRM_Dedupe_Merger::moveContactBelongings($mainId, $otherId, $moveTables, $tableOperations, $customTablesToCopyValues); unset($moveTables, $tableOperations); + // **** Do table related removals + if (!empty($removeTables)) { + // **** CRM-20421 + CRM_Dedupe_Merger::removeContactBelongings($otherId, $removeTables); + $removeTables = array(); + } + // FIXME: fix gender, prefix and postfix, so they're edible by createProfileContact() $names['gender'] = array('newName' => 'gender_id', 'groupName' => 'gender'); $names['individual_prefix'] = array('newName' => 'prefix_id', 'groupName' => 'individual_prefix'); diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index c2f4f94e21..1fcb553a6e 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -1492,6 +1492,76 @@ class api_v3_ContactTest extends CiviUnitTestCase { $expected->matches($actual); } + /** + * Test merging 2 organizations. + * + * CRM-20421: This test make sure that inherited memberships are deleted upon merging organization. + */ + public function testMergeOrganizations() { + $organizationID1 = $this->organizationCreate(array(), 0); + $organizationID2 = $this->organizationCreate(array(), 1); + $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array( + 'employer_id' => $organizationID1, + ) + )); + $contact = $contact["values"][$contact["id"]]; + + $membershipType = $this->createEmployerOfMembership(); + $membershipParams = array( + 'membership_type_id' => $membershipType["id"], + 'contact_id' => $organizationID1, + 'start_date' => "01/01/2015", + 'join_date' => "01/01/2010", + 'end_date' => "12/31/2015", + ); + $ownermembershipid = $this->contactMembershipCreate($membershipParams); + + $contactmembership = $this->callAPISuccess("membership", "getsingle", array( + "contact_id" => $contact["id"], + )); + + $this->assertEquals($ownermembershipid, $contactmembership["owner_membership_id"], "Contact membership must be inherited from Organization"); + + CRM_Dedupe_Merger::moveAllBelongings($organizationID2, $organizationID1, array( + "move_rel_table_memberships" => "0", + "move_rel_table_relationships" => "1", + "main_details" => array( + "contact_id" => $organizationID2, + "contact_type" => "Organization", + ), + "other_details" => array( + "contact_id" => $organizationID1, + "contact_type" => "Organization", + ), + )); + + $contactmembership = $this->callAPISuccess("membership", "get", array( + "contact_id" => $contact["id"], + )); + + $this->assertEquals(0, $contactmembership["count"], "Contact membership must be deleted after merging organization without memberships."); + } + + private function createEmployerOfMembership() { + $params = array( + 'domain_id' => CRM_Core_Config::domainID(), + 'name' => 'Organization Membership', + 'description' => NULL, + 'member_of_contact_id' => 1, + 'financial_type_id' => 1, + 'minimum_fee' => 10, + 'duration_unit' => 'year', + 'duration_interval' => 1, + 'period_type' => 'rolling', + 'relationship_type_id' => 5, + 'relationship_direction' => 'b_a', + 'visibility' => 'Public', + 'is_active' => 1, + ); + $membershipType = $this->callAPISuccess('membership_type', 'create', $params); + return $membershipType["values"][$membershipType["id"]]; + } + /** * Verify successful update of household contact. */ -- 2.25.1