From f42bcfb14e822ba42422beaeb6f83c8dece8e33c Mon Sep 17 00:00:00 2001 From: Monish Deb Date: Fri, 2 Aug 2019 13:59:12 +1200 Subject: [PATCH] Move the code to add or clear employer from relationship backoffice form to BAO This is a reduced version of https://github.com/civicrm/civicrm-core/pull/13331 which stalled on the QA over handling of removed employers - that code is simply excluded. I tested adding & removing & editing relationships with the current_employer checkbox ticked or unticked & this seems to work fine --- CRM/Contact/BAO/Contact/Utils.php | 5 +- CRM/Contact/BAO/Relationship.php | 39 ++++++++++++++-- CRM/Contact/Form/Relationship.php | 25 ---------- api/v3/Relationship.php | 5 ++ tests/phpunit/api/v3/RelationshipTest.php | 57 ++++++++++++++++++++--- 5 files changed, 91 insertions(+), 40 deletions(-) diff --git a/CRM/Contact/BAO/Contact/Utils.php b/CRM/Contact/BAO/Contact/Utils.php index 8850d9acc5..1d9f166a71 100644 --- a/CRM/Contact/BAO/Contact/Utils.php +++ b/CRM/Contact/BAO/Contact/Utils.php @@ -392,10 +392,7 @@ UNION $query = "UPDATE civicrm_contact contact_a,civicrm_contact contact_b SET contact_a.employer_id=contact_b.id, contact_a.organization_name=contact_b.organization_name WHERE contact_a.id ={$contactId} AND contact_b.id={$orgId}; "; - - //FIXME : currently civicrm mysql_query support only single statement - //execution, though mysql 5.0 support multiple statement execution. - $dao = CRM_Core_DAO::executeQuery($query); + CRM_Core_DAO::executeQuery($query); } } diff --git a/CRM/Contact/BAO/Relationship.php b/CRM/Contact/BAO/Relationship.php index d61854ecae..385ed19e86 100644 --- a/CRM/Contact/BAO/Relationship.php +++ b/CRM/Contact/BAO/Relationship.php @@ -278,13 +278,15 @@ class CRM_Contact_BAO_Relationship extends CRM_Contact_DAO_Relationship { * This is the function that check/add if the relationship created is valid. * * @param array $params - * (reference ) an assoc array of name/value pairs. + * Array of name/value pairs. * @param array $ids * The array that holds all the db ids. * @param int $contactId * This is contact id for adding relationship. * * @return CRM_Contact_BAO_Relationship + * + * @throws \CiviCRM_API3_Exception */ public static function add($params, $ids = [], $contactId = NULL) { $params['id'] = CRM_Utils_Array::value('relationship', $ids, CRM_Utils_Array::value('id', $params)); @@ -311,6 +313,7 @@ class CRM_Contact_BAO_Relationship extends CRM_Contact_DAO_Relationship { if (!empty($params['id']) && self::isCurrentEmployerNeedingToBeCleared($params, $params['id'], $type)) { CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($params['contact_id_a']); } + $relationship = new CRM_Contact_BAO_Relationship(); //@todo this code needs to be updated for the possibility that not all fields are set // by using $relationship->copyValues($params); @@ -340,7 +343,18 @@ class CRM_Contact_BAO_Relationship extends CRM_Contact_DAO_Relationship { } $relationship->save(); - + // is_current_employer is an optional parameter that triggers updating the employer_id field to reflect + // the relationship being updated. As of writing only truthy versions of the parameter are respected. + // https://github.com/civicrm/civicrm-core/pull/13331 attempted to cover both but stalled in QA + // so currently we have a cut down version. + if (!empty($params['is_current_employer'])) { + if (!$relationship->relationship_type_id || !$relationship->contact_id_a || !$relationship->contact_id_b) { + $relationship->fetch(); + } + if (self::isRelationshipTypeCurrentEmployer($relationship->relationship_type_id)) { + CRM_Contact_BAO_Contact_Utils::setCurrentEmployer([$relationship->contact_id_a => $relationship->contact_id_b]); + } + } // add custom field values if (!empty($params['custom'])) { CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_relationship', $relationship->id); @@ -1968,6 +1982,7 @@ AND cc.sort_name LIKE '%$name%'"; * * @return bool * True on success, false if error is encountered. + * @throws \CiviCRM_API3_Exception */ public static function disableExpiredRelationships() { $query = "SELECT id FROM civicrm_relationship WHERE is_active = 1 AND end_date < CURDATE()"; @@ -2261,13 +2276,13 @@ AND cc.sort_name LIKE '%$name%'"; * * @return bool * TRUE if current employer needs to be cleared. + * @throws \CiviCRM_API3_Exception */ public static function isCurrentEmployerNeedingToBeCleared($params, $relationshipId, $updatedRelTypeID = NULL) { - $existingTypeID = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Relationship', $relationshipId, 'relationship_type_id'); - $existingTypeName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $existingTypeID, 'name_b_a'); + $existingTypeID = (int) CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Relationship', $relationshipId, 'relationship_type_id'); $updatedRelTypeID = $updatedRelTypeID ? $updatedRelTypeID : $existingTypeID; - if ($existingTypeName !== 'Employer of') { + if (!self::isRelationshipTypeCurrentEmployer($existingTypeID)) { return FALSE; } //Clear employer if relationship is expired. @@ -2285,4 +2300,18 @@ AND cc.sort_name LIKE '%$name%'"; return FALSE; } + /** + * Is this a current employer relationship type. + * + * @todo - this could use cached pseudoconstant lookups. + * + * @param int $existingTypeID + * + * @return bool + */ + private static function isRelationshipTypeCurrentEmployer(int $existingTypeID): bool { + $isCurrentEmployerRelationshipType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $existingTypeID, 'name_b_a') === 'Employer of'; + return $isCurrentEmployerRelationshipType; + } + } diff --git a/CRM/Contact/Form/Relationship.php b/CRM/Contact/Form/Relationship.php index 1516238bbf..eca04a56c6 100644 --- a/CRM/Contact/Form/Relationship.php +++ b/CRM/Contact/Form/Relationship.php @@ -416,8 +416,6 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form { $note = !empty($params['note']) ? $params['note'] : ''; $this->saveRelationshipNotes($relationshipIds, $note); - $this->setEmploymentRelationship($params, $relationshipIds); - // Refresh contact tabs which might have been affected $this->ajaxResponse = [ 'reloadBlocks' => ['#crm-contactinfo-content'], @@ -638,27 +636,4 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form { } } - /** - * Sets current employee/employer relationship - * - * @param $params - * @param array $relationshipIds - */ - private function setEmploymentRelationship($params, $relationshipIds) { - $employerParams = []; - foreach ($relationshipIds as $id) { - if (!CRM_Contact_BAO_Relationship::isCurrentEmployerNeedingToBeCleared($params, $id) - //don't think this is required to check again. - && $this->_allRelationshipNames[$params['relationship_type_id']]["name_a_b"] == 'Employee of') { - // Fixme this is dumb why do we have to look this up again? - $rel = CRM_Contact_BAO_Relationship::getRelationshipByID($id); - $employerParams[$rel->contact_id_a] = $rel->contact_id_b; - } - } - if (!empty($employerParams)) { - // @todo this belongs in the BAO. - CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($employerParams); - } - } - } diff --git a/api/v3/Relationship.php b/api/v3/Relationship.php index d08889cd89..f7023dea4a 100644 --- a/api/v3/Relationship.php +++ b/api/v3/Relationship.php @@ -58,6 +58,11 @@ function _civicrm_api3_relationship_create_spec(&$params) { $params['contact_id_b']['api.required'] = 1; $params['relationship_type_id']['api.required'] = 1; $params['is_active']['api.default'] = 1; + $params['is_current_employer'] = [ + 'title' => 'Is Current Employer?', + 'description' => 'This is a optional parameter used to add employer contact when \'Employee Of\' relationship is created', + 'type' => CRM_Utils_Type::T_BOOLEAN, + ]; } /** diff --git a/tests/phpunit/api/v3/RelationshipTest.php b/tests/phpunit/api/v3/RelationshipTest.php index d29fe056de..a85f738d97 100644 --- a/tests/phpunit/api/v3/RelationshipTest.php +++ b/tests/phpunit/api/v3/RelationshipTest.php @@ -117,23 +117,24 @@ class api_v3_RelationshipTest extends CiviUnitTestCase { /** * Test Current Employer is correctly set. + * + * @throws \CRM_Core_Exception */ public function testCurrentEmployerRelationship() { $employerRelationshipID = $this->callAPISuccessGetValue('RelationshipType', [ - 'return' => "id", - 'name_b_a' => "Employer Of", + 'return' => 'id', + 'name_b_a' => 'Employer Of', ]); $employerRelationship = $this->callAPISuccess('Relationship', 'create', [ 'contact_id_a' => $this->_cId_a, 'contact_id_b' => $this->_cId_b, 'relationship_type_id' => $employerRelationshipID, + 'is_current_employer' => 1, ]); - $params = [$this->_cId_a => $this->_cId_b]; - CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($params); //Check if current employer is correctly set. $employer = $this->callAPISuccessGetValue('Contact', [ - 'return' => "current_employer", + 'return' => 'current_employer', 'id' => $this->_cId_a, ]); $organisation = $this->callAPISuccessGetValue('Contact', [ @@ -148,7 +149,7 @@ class api_v3_RelationshipTest extends CiviUnitTestCase { 'relationship_type_id' => $this->_relTypeID, ]); $employeeContact = $this->callAPISuccessGetSingle('Contact', [ - 'return' => ["current_employer"], + 'return' => ['current_employer'], 'id' => $this->_cId_a, ]); //current employer should be removed. @@ -1358,4 +1359,48 @@ class api_v3_RelationshipTest extends CiviUnitTestCase { $this->callAPISuccessGetCount('membership', ['contact_id' => $this->_cId_a], 0); } + /** + * Test api respects is_current_employer. + * + * @throws \CRM_Core_Exception + */ + public function testRelationshipCreateWithEmployerData() { + // CASE A: Create a current employee relationship without setting end date, ensure that employer field is set + $params = [ + 'relationship_type_id' => '5_a_b', + 'related_contact_id' => $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, + ]; + $reln = new CRM_Contact_Form_Relationship(); + $reln->_action = CRM_Core_Action::ADD; + $reln->_contactId = $this->_cId_a; + list ($params, $relationshipIds) = $reln->submit($params); + $this->assertEquals( + $this->_cId_b, + $this->callAPISuccess('Contact', 'getvalue', [ + 'id' => $this->_cId_a, + 'return' => 'current_employer_id', + ])); + // CASE B: Create a past employee relationship by setting end date of past, ensure that employer field is cleared + $params = [ + 'relationship_type_id' => '5_a_b', + 'related_contact_id' => $this->_cId_b, + // set date to past date + 'end_date' => '2010-12-20', + ]; + $reln->_action = CRM_Core_Action::UPDATE; + $reln->_relationshipId = $relationshipIds[0]; + list ($params, $relationshipIds) = $reln->submit($params); + $this->assertEmpty($this->callAPISuccess('Contact', 'getvalue', [ + 'id' => $this->_cId_a, + 'return' => 'current_employer_id', + ])); + $this->callAPISuccess('relationship', 'delete', ['id' => $relationshipIds[0]]); + } + } -- 2.25.1