From 3ac22820f7f10bbf30e23bb9306289d94d9903ff Mon Sep 17 00:00:00 2001 From: Muhammad Shahrukh <> Date: Tue, 30 Jul 2024 12:48:28 +0500 Subject: [PATCH] FOSFAB-320: Add functionality to link cases while creating a case --- CRM/Civicase/Hook/Post/LinkCase.php | 145 ++++++++++++++++++ .../new-link-cases-case-action.service.js | 40 +++++ ...se-details-linked-cases-tab.directive.html | 24 ++- ...case-details-linked-cases-tab.directive.js | 19 ++- civicase.php | 1 + 5 files changed, 223 insertions(+), 6 deletions(-) create mode 100644 CRM/Civicase/Hook/Post/LinkCase.php create mode 100644 ang/civicase/case/actions/services/new-link-cases-case-action.service.js diff --git a/CRM/Civicase/Hook/Post/LinkCase.php b/CRM/Civicase/Hook/Post/LinkCase.php new file mode 100644 index 000000000..f604e9a6a --- /dev/null +++ b/CRM/Civicase/Hook/Post/LinkCase.php @@ -0,0 +1,145 @@ +shouldRun($op, $objectName)) { + return; + } + + $linkToCaseId = (int) CRM_Utils_Request::retrieve('linkToCaseId', 'Positive'); + $linkedToCaseDetails = $this->getLinkedToCaseDetails($linkToCaseId); + $caseDetails = $this->getCaseDetails($objectId); + + $params = [ + 'case_id' => $linkToCaseId, + 'link_to_case_id' => $objectId, + 'activity_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Link Cases'), + 'medium_id' => CRM_Core_OptionGroup::values('encounter_medium', FALSE, FALSE, FALSE, 'AND is_default = 1'), + 'activity_date_time' => date('YmdHis'), + 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_status_id', 'Completed'), + 'subject' => $this->getActivitySubject($caseDetails, $linkedToCaseDetails), + 'source_contact_id' => \CRM_Core_Session::getLoggedInContactID(), + 'target_contact_id' => $linkedToCaseContacts[0]['contact_id'] ?? NULL, + ]; + + $activity = CRM_Activity_BAO_Activity::create($params); + + $caseParams = [ + 'case_id' => $objectId, + 'activity_id' => $activity->id, + ]; + CRM_Case_BAO_Case::processCaseActivity($caseParams); + + $caseParams = [ + 'case_id' => $linkToCaseId, + 'activity_id' => $activity->id, + ]; + CRM_Case_BAO_Case::processCaseActivity($caseParams); + } + + /** + * Determines if the hook should run or not. + * + * @param string $op + * The operation being performed. + * @param string $objectName + * Object name. + * + * @return bool + * returns a boolean to determine if hook will run or not. + */ + private function shouldRun(string $op, string $objectName): bool { + return $objectName == 'Case' && $op === 'create' + && (int) CRM_Utils_Request::retrieve('linkToCaseId', 'Positive') > 0; + } + + /** + * Get case details required to create the activity subject. + * + * @param int $id + * The case id. + * + * @return array + * case details. + */ + private function getLinkedToCaseDetails(int $id): array { + $case = CiviCase::get(FALSE) + ->addSelect('contact.display_name', 'case_type_id.title') + ->addJoin('CaseContact AS case_contact', 'INNER', ['id', '=', 'case_contact.case_id']) + ->addJoin('Contact AS contact', 'INNER', ['contact.id', '=', 'case_contact.contact_id']) + ->addWhere('id', '=', $id) + ->execute() + ->first(); + + return [ + 'id' => $id, + 'caseType' => $case['case_type_id.title'] ?? '', + 'contact' => $case['contact.display_name'] ?? '', + ]; + } + + /** + * Get case details required to create the activity subject. + * + * @param int $id + * The case id. + * + * @return array + * case details. + */ + private function getCaseDetails(int $id): array { + $caseClient = Contact::get(FALSE) + ->addSelect('display_name') + ->addWhere('id', '=', $_POST['client_id'] ?? 0) + ->execute() + ->first(); + + return [ + 'id' => $id, + 'caseType' => CRM_Case_BAO_Case::getCaseType($id), + 'contact' => $caseClient['display_name'] ?? '', + ]; + } + + /** + * Create activity subject. + * + * @param array $caseDetails + * The case details. + * @param array $linkedToCaseDetails + * The linked to case details. + * + * @return string + * Activity subject. + */ + private function getActivitySubject(array $caseDetails, array $linkedToCaseDetails): string { + return ts('Create link between %1 - %2 (CaseID: %3) and %4 - %5 (CaseID: %6)', [ + 1 => $caseDetails['contact'], + 2 => $caseDetails['caseType'], + 3 => $caseDetails['id'], + 4 => $linkedToCaseDetails['contact'], + 5 => $linkedToCaseDetails['caseType'], + 6 => $linkedToCaseDetails['id'], + ]); + } + +} diff --git a/ang/civicase/case/actions/services/new-link-cases-case-action.service.js b/ang/civicase/case/actions/services/new-link-cases-case-action.service.js new file mode 100644 index 000000000..72c5cc656 --- /dev/null +++ b/ang/civicase/case/actions/services/new-link-cases-case-action.service.js @@ -0,0 +1,40 @@ +(function (angular, $, _) { + var module = angular.module('civicase'); + + module.service('NewLinkCasesCaseAction', NewLinkCasesCaseAction); + + /** + * Create and Link Case Action service + * + * @param {object} $q $q service + * @param {object} ActivityType ActivityType + * @param {string} currentCaseCategory current case category + */ + function NewLinkCasesCaseAction ($q, ActivityType, currentCaseCategory) { + /** + * Click event handler for the Action + * + * @param {object} cases cases + * + * @returns {Promise} promise which resolves to the path for the popup + */ + this.doAction = function (cases) { + var currentCase = cases[0]; + var activityTypes = ActivityType.getAll(true); + + var link = { + path: 'civicrm/case/add', + query: { + action: 'add', + reset: 1, + atype: _.findKey(activityTypes, { name: 'Open Case' }), + linkToCaseId: currentCase.id, + context: 'standalone', + case_type_category: currentCaseCategory + } + }; + + return $q.resolve(link); + }; + } +})(angular, CRM.$, CRM._); diff --git a/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.html b/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.html index f885a39ea..e130d32a2 100644 --- a/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.html +++ b/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.html @@ -7,6 +7,13 @@ {{ ts('Link Cases') }} + {{ ts('Click the button below to create a new link for this case') }} - - {{ ts('Link Cases') }} - +
+ + {{ ts('Link Cases') }} + + + {{ ts('Create new linked Case') }} + +
diff --git a/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.js b/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.js index d63962be6..dcd95ce07 100644 --- a/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.js +++ b/ang/civicase/case/details/linked-cases-tab/directives/case-details-linked-cases-tab.directive.js @@ -17,12 +17,14 @@ * * @param {object} $scope the scope object. * @param {object} LinkCasesCaseAction the link case action service. + * @param {object} NewLinkCasesCaseAction the new link case action service. * @param {Function} civicaseCrmUrl crm url service. * @param {Function} civicaseCrmLoadForm service to load civicrm forms */ function civicaseCaseDetailsLinkedCasesTabController ($scope, - LinkCasesCaseAction, civicaseCrmUrl, civicaseCrmLoadForm) { + LinkCasesCaseAction, NewLinkCasesCaseAction, civicaseCrmUrl, civicaseCrmLoadForm) { $scope.linkCase = linkCase; + $scope.newLinkCase = newLinkCase; /** * Opens a modal that allows the user to link the case stored in the scope with @@ -39,5 +41,20 @@ }); }); } + + /** + * Opens a modal that allows the user to open a new case and link it at the same time. + * + * The case details are refreshed after linking the cases. + */ + function newLinkCase () { + NewLinkCasesCaseAction.doAction([$scope.item]) + .then(function (openCaseForm) { + civicaseCrmLoadForm(civicaseCrmUrl(openCaseForm.path, openCaseForm.query)) + .on('crmFormSuccess crmPopupFormSuccess', function () { + $scope.refresh(); + }); + }); + } } })(angular); diff --git a/civicase.php b/civicase.php index f0b5f904d..5e6d9467a 100644 --- a/civicase.php +++ b/civicase.php @@ -279,6 +279,7 @@ function civicase_civicrm_post($op, $objectName, $objectId, &$objectRef) { new CRM_Civicase_Hook_Post_PopulateCaseCategoryForCaseType(), new CRM_Civicase_Hook_Post_CaseCategoryCustomGroupSaver(), new CRM_Civicase_Hook_Post_UpdateCaseTypeListForCaseCategoryCustomGroup(), + new CRM_Civicase_Hook_Post_LinkCase(), ]; foreach ($hooks as $hook) {