dev/core#470: Current employer disapears when disabling expired relationships
authorMonish Deb <deb.monish@gmail.com>
Fri, 2 Aug 2019 02:43:53 +0000 (14:43 +1200)
committereileen <emcnaughton@wikimedia.org>
Sat, 3 Aug 2019 01:53:01 +0000 (13:53 +1200)
Overview
----------------------------------------
Steps to replicate:

1. Create a current relationship (set empty end-date) on individual A as  organization A and mark as current employer
2. Create a past relationship on individual A as  organization B without marking as current employer
3. Run Disable expired relationships cron job

Before
----------------------------------------
Result: Clear the employer field of Contact A

After
----------------------------------------
Result: Does not clear the employer field of Contact A

Technical Details
----------------------------------------
This PR replaces https://github.com/civicrm/civicrm-core/pull/13334

CRM/Contact/BAO/Relationship.php
tests/phpunit/api/v3/RelationshipTest.php

index 385ed19e866da2e54acd0a175c48227b76a424ad..5d55ef141a8269032ea3fca6c3dded375a8a18e8 100644 (file)
@@ -2281,8 +2281,9 @@ AND cc.sort_name LIKE '%$name%'";
   public static function isCurrentEmployerNeedingToBeCleared($params, $relationshipId, $updatedRelTypeID = NULL) {
     $existingTypeID = (int) CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Relationship', $relationshipId, 'relationship_type_id');
     $updatedRelTypeID = $updatedRelTypeID ? $updatedRelTypeID : $existingTypeID;
+    $currentEmployerID = (int) civicrm_api3('Contact', 'getvalue', ['return' => 'current_employer_id', 'id' => $params['contact_id_a']]);
 
-    if (!self::isRelationshipTypeCurrentEmployer($existingTypeID)) {
+    if ($currentEmployerID !== (int) $params['contact_id_b'] || !self::isRelationshipTypeCurrentEmployer($existingTypeID)) {
       return FALSE;
     }
     //Clear employer if relationship is expired.
@@ -2294,7 +2295,16 @@ AND cc.sort_name LIKE '%$name%'";
     if ((isset($params['is_current_employer']) && empty($params['is_current_employer']))
       || ((isset($params['is_active']) && empty($params['is_active'])))
       || $existingTypeID != $updatedRelTypeID) {
-      return TRUE;
+      // If there are no other active employer relationships between the same 2 contacts...
+      if (!civicrm_api3('Relationship', 'getcount', [
+        'is_active' => 1,
+        'relationship_type_id' => $existingTypeID,
+        'id' => ['<>' => $params['id']],
+        'contact_id_a' => $params['contact_id_a'],
+        'contact_id_b' => $params['contact_id_b'],
+      ])) {
+        return TRUE;
+      }
     }
 
     return FALSE;
index a85f738d97d94b89e498c967055167081b7aecb7..b8c23988a5a036b218e51e2985d49462d0b5563b 100644 (file)
@@ -1403,4 +1403,76 @@ class api_v3_RelationshipTest extends CiviUnitTestCase {
     $this->callAPISuccess('relationship', 'delete', ['id' => $relationshipIds[0]]);
   }
 
+  /**
+   * Test disabling an expired relationship does not incorrectly clear employer_id.
+   *
+   * See https://lab.civicrm.org/dev/core/issues/470
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
+  public function testDisableExpiredRelationships() {
+    // Step 1: Create a current employer relationship with Org A
+    $params = [
+      'relationship_type_id' => '5',
+      'contact_id_a' => $this->_cId_a,
+      'contact_id_b' => $this->_cId_b,
+      'start_date' => '2008-12-20',
+      'end_date' => NULL,
+      'is_active' => 1,
+      'is_current_employer' => 1,
+      'is_permission_a_b' => 0,
+      'is_permission_b_a' => 0,
+    ];
+    $this->callAPISuccess('Relationship', 'create', $params);
+
+    // ensure that the employer_id field is sucessfully set
+    $this->assertEquals(
+      $this->_cId_b,
+      $this->callAPISuccess('Contact', 'getvalue', [
+        'id' => $this->_cId_a,
+        'return' => 'current_employer_id',
+      ]));
+    // Step 2: Create a PAST employer relationship with Org B, and setting is_current_employer = FALSE
+    $orgID2 = $this->organizationCreate();
+    $params = [
+      'relationship_type_id' => '5',
+      'contact_id_a' => $this->_cId_a,
+      'contact_id_b' => $orgID2,
+      'start_date' => '2008-12-20',
+      'end_date' => '2008-12-22',
+      'is_active' => 1,
+      'is_current_employer' => 0,
+      'is_permission_a_b' => 0,
+      'is_permission_b_a' => 0,
+    ];
+
+    $relationshipB = $this->callAPISuccess('Relationship', 'create', $params);
+    // ensure that the employer_id field is still set to contact b
+    $this->assertEquals(
+      $this->_cId_b,
+      $this->callAPISuccess('Contact', 'getvalue', [
+        'id' => $this->_cId_a,
+        'return' => 'current_employer_id',
+      ]));
+
+    // Step 3: Call schedule job disable_expired_relationships
+    CRM_Contact_BAO_Relationship::disableExpiredRelationships();
+
+    // Result A: Ensure that employer field is not cleared
+    $this->assertEquals(
+      $this->_cId_b,
+      $this->callAPISuccess('Contact', 'getvalue', [
+        'id' => $this->_cId_a,
+        'return' => 'current_employer_id',
+      ]));
+    // Result B: Ensure that the previous employer relationship with Org B is successfully disabled
+    $this->assertEquals(
+      FALSE,
+      (bool) $this->callAPISuccess('Relationship', 'getvalue', [
+        'id' => $relationshipB['id'],
+        'return' => 'is_active',
+      ]));
+  }
+
 }