From 04d0351fb96a750106e0487b58a328c8c5087a8e Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 14 Dec 2017 23:24:16 +0900 Subject: [PATCH] Add batch update via profile for cases --- CRM/Case/Form/Task/Batch.php | 265 +++++++++++++++++++ CRM/Case/Form/Task/PickProfile.php | 148 +++++++++++ CRM/Case/Task.php | 8 + CRM/Contact/BAO/Contact/Utils.php | 11 +- CRM/Core/BAO/UFField.php | 3 - CRM/Core/BAO/UFGroup.php | 24 +- templates/CRM/Case/Form/Task/Batch.tpl | 66 +++++ templates/CRM/Case/Form/Task/PickProfile.tpl | 37 +++ 8 files changed, 557 insertions(+), 5 deletions(-) create mode 100644 CRM/Case/Form/Task/Batch.php create mode 100644 CRM/Case/Form/Task/PickProfile.php create mode 100644 templates/CRM/Case/Form/Task/Batch.tpl create mode 100644 templates/CRM/Case/Form/Task/PickProfile.tpl diff --git a/CRM/Case/Form/Task/Batch.php b/CRM/Case/Form/Task/Batch.php new file mode 100644 index 000000000000..800ec5e88282 --- /dev/null +++ b/CRM/Case/Form/Task/Batch.php @@ -0,0 +1,265 @@ + ts('Name')), + CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, + 'contact_autocomplete_options', + TRUE, NULL, FALSE, 'name', TRUE + ) + ); + //get the read only field data. + $returnProperties = array_fill_keys(array_keys($readOnlyFields), 1); + $contactDetails = CRM_Contact_BAO_Contact_Utils::contactDetails($this->_caseIds, + 'CiviCase', $returnProperties + ); + + $this->assign('contactDetails', $contactDetails); + $this->assign('readOnlyFields', $readOnlyFields); + } + + /** + * Build the form object. + * + * + * @return void + */ + public function buildQuickForm() { + $ufGroupId = $this->get('ufGroupId'); + + if (!$ufGroupId) { + CRM_Core_Error::fatal('ufGroupId is missing'); + } + $this->_title = ts('Update multiple cases') . ' - ' . CRM_Core_BAO_UFGroup::getTitle($ufGroupId); + CRM_Utils_System::setTitle($this->_title); + + $this->addDefaultButtons(ts('Save')); + $this->_fields = array(); + $this->_fields = CRM_Core_BAO_UFGroup::getFields($ufGroupId, FALSE, CRM_Core_Action::VIEW); + + // remove file type field and then limit fields + $suppressFields = FALSE; + $removehtmlTypes = array('File'); + foreach ($this->_fields as $name => $field) { + if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name) && + in_array($this->_fields[$name]['html_type'], $removehtmlTypes) + ) { + $suppressFields = TRUE; + unset($this->_fields[$name]); + } + + //fix to reduce size as we are using this field in grid + if (is_array($field['attributes']) && !empty($this->_fields[$name]['attributes']['size']) && $this->_fields[$name]['attributes']['size'] > 19) { + //shrink class to "form-text-medium" + $this->_fields[$name]['attributes']['size'] = 19; + } + } + + $this->_fields = array_slice($this->_fields, 0, $this->_maxFields); + + $this->addButtons(array( + array( + 'type' => 'submit', + 'name' => ts('Update Case(s)'), + 'isDefault' => TRUE, + ), + array( + 'type' => 'cancel', + 'name' => ts('Cancel'), + ), + )); + + $this->assign('profileTitle', $this->_title); + $this->assign('componentIds', $this->_caseIds); + + $customFields = CRM_Core_BAO_CustomField::getFields('Case'); + foreach ($this->_caseIds as $caseId) { + $typeId = CRM_Core_DAO::getFieldValue("CRM_Case_DAO_Case", $caseId, 'case_type_id'); + foreach ($this->_fields as $name => $field) { + if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) { + $customValue = CRM_Utils_Array::value($customFieldID, $customFields); + $entityColumnValue = array(); + if (!empty($customValue['extends_entity_column_value'])) { + $entityColumnValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, + $customValue['extends_entity_column_value'] + ); + } + if ((CRM_Utils_Array::value($typeId, $entityColumnValue)) || + CRM_Utils_System::isNull($entityColumnValue[$typeId]) + ) { + CRM_Core_BAO_UFGroup::buildProfile($this, $field, NULL, $caseId); + } + } + else { + // handle non custom fields + CRM_Core_BAO_UFGroup::buildProfile($this, $field, NULL, $caseId); + } + } + } + + $this->assign('fields', $this->_fields); + + // don't set the status message when form is submitted. + $buttonName = $this->controller->getButtonName('submit'); + + if ($suppressFields && $buttonName != '_qf_Batch_next') { + CRM_Core_Session::setStatus(ts("File type field(s) in the selected profile are not supported for Update multiple cases."), ts('Unsupported Field Type'), 'error'); + } + + $this->addDefaultButtons(ts('Update Cases')); + } + + /** + * Set default values for the form. + * + * + * @return void + */ + public function setDefaultValues() { + if (empty($this->_fields)) { + return; + } + + $defaults = array(); + foreach ($this->_caseIds as $caseId) { + CRM_Core_BAO_UFGroup::setProfileDefaults(NULL, $this->_fields, $defaults, FALSE, $caseId, 'Case'); + } + + return $defaults; + } + + /** + * Process the form after the input has been submitted and validated. + * + * + * @return void + */ + public function postProcess() { + $params = $this->exportValues(); + $dates = array( + 'case_created_date', + 'case_start_date', + 'case_end_date', + 'case_modified_date', + ); + if (isset($params['field'])) { + $customFields = array(); + foreach ($params['field'] as $key => $value) { + $value['id'] = $key; + + if (!empty($value['case_type'])) { + $caseTypeId = $value['case_type_id'] = $value['case_type'][1]; + } + + unset($value['case_type']); + + //Get the case status + $value['status_id'] = (CRM_Utils_Array::value('case_status', $value)) ? $value['case_status'] : CRM_Core_DAO::getFieldValue('CRM_Case_DAO_Case', $key, 'status_id'); + unset($value['case_status']); + foreach ($dates as $val) { + if (isset($value[$val])) { + $value[$val] = CRM_Utils_Date::processDate($value[$val]); + } + } + if (empty($customFields)) { + if (empty($value['case_type_id'])) { + $caseTypeId = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_Case', $key, 'case_type_id'); + } + + // case type custom data + $customFields = CRM_Core_BAO_CustomField::getFields('Case', FALSE, FALSE, $caseTypeId); + + $customFields = CRM_Utils_Array::crmArrayMerge($customFields, + CRM_Core_BAO_CustomField::getFields('Case', + FALSE, FALSE, NULL, NULL, TRUE + ) + ); + } + //check for custom data + $value['custom'] = CRM_Core_BAO_CustomField::postProcess($params['field'][$key], + $key, + 'Case', + $caseTypeId + ); + + $case = CRM_Case_BAO_Case::add($value); + + // add custom field values + if (!empty($value['custom']) && + is_array($value['custom']) + ) { + CRM_Core_BAO_CustomValueTable::store($value['custom'], 'civicrm_case', $case->id); + } + } + + CRM_Core_Session::setStatus(ts("Your updates have been saved."), ts('Saved'), 'success'); + } + else { + CRM_Core_Session::setStatus(ts("No updates have been saved."), ts('Not Saved'), 'alert'); + } + } + +} diff --git a/CRM/Case/Form/Task/PickProfile.php b/CRM/Case/Form/Task/PickProfile.php new file mode 100644 index 000000000000..55caaddda08f --- /dev/null +++ b/CRM/Case/Form/Task/PickProfile.php @@ -0,0 +1,148 @@ +_userContext = $session->readUserContext(); + + CRM_Utils_System::setTitle(ts('Update multiple cases')); + + $validate = FALSE; + //validations + if (count($this->_caseIds) > $this->_maxCases) { + CRM_Core_Session::setStatus(ts("The maximum number of cases you can select for Update multiple cases is %1. You have selected %2. Please select fewer cases from your search results and try again.", array( + 1 => $this->_maxCases, + 2 => count($this->_caseIds), + )), ts('Update multiple records error'), 'error'); + $validate = TRUE; + } + + // than redirect + if ($validate) { + CRM_Utils_System::redirect($this->_userContext); + } + } + + /** + * Build the form object. + * + * + * @return void + */ + public function buildQuickForm() { + $types = array('Case'); + $profiles = CRM_Core_BAO_UFGroup::getProfiles($types, TRUE); + + if (empty($profiles)) { + CRM_Core_Session::setStatus(ts("You will need to create a Profile containing the %1 fields you want to edit before you can use Update multiple cases. Navigate to Administer CiviCRM >> CiviCRM Profile to configure a Profile. Consult the online Administrator documentation for more information.", array(1 => $types[0])), ts('Update multiple records error'), 'error'); + CRM_Utils_System::redirect($this->_userContext); + } + + $ufGroupElement = $this->add('select', 'uf_group_id', ts('Select Profile'), + array( + '' => ts('- select profile -'), + ) + $profiles, TRUE + ); + $this->addDefaultButtons(ts('Continue')); + } + + /** + * Add local and global form rules. + * + * + * @return void + */ + public function addRules() { + $this->addFormRule(array('CRM_Case_Form_Task_PickProfile', 'formRule')); + } + + /** + * Global validation rules for the form. + * + * @param array $fields + * Posted values of the form. + * + * @return array + * list of errors to be posted back to the form + */ + public static function formRule($fields) { + return TRUE; + } + + /** + * Process the form after the input has been submitted and validated. + * + * + * @return void + */ + public function postProcess() { + $params = $this->exportValues(); + + $this->set('ufGroupId', $params['uf_group_id']); + + // also reset the batch page so it gets new values from the db + $this->controller->resetPage('Batch'); + } + +} diff --git a/CRM/Case/Task.php b/CRM/Case/Task.php index 5af2aaaf1c9d..1b67e4611e83 100644 --- a/CRM/Case/Task.php +++ b/CRM/Case/Task.php @@ -91,6 +91,14 @@ public static function &tasks() { 'class' => 'CRM_Case_Form_Task_PDF', 'result' => FALSE, ), + 6 => array( + 'title' => ts('Update multiple cases'), + 'class' => array( + 'CRM_Case_Form_Task_PickProfile', + 'CRM_Case_Form_Task_Batch', + ), + 'result' => FALSE, + ), ); //CRM-4418, check for delete diff --git a/CRM/Contact/BAO/Contact/Utils.php b/CRM/Contact/BAO/Contact/Utils.php index 662e8662271b..c94d038fc38c 100644 --- a/CRM/Contact/BAO/Contact/Utils.php +++ b/CRM/Contact/BAO/Contact/Utils.php @@ -679,7 +679,7 @@ public static function formatContactIDSToLinks($contactIDs, $addViewLink = TRUE, public static function contactDetails($componentIds, $componentName, $returnProperties = array()) { $contactDetails = array(); if (empty($componentIds) || - !in_array($componentName, array('CiviContribute', 'CiviMember', 'CiviEvent', 'Activity')) + !in_array($componentName, array('CiviContribute', 'CiviMember', 'CiviEvent', 'Activity', 'CiviCase')) ) { return $contactDetails; } @@ -704,6 +704,9 @@ public static function contactDetails($componentIds, $componentName, $returnProp $compTable = 'civicrm_activity'; $activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate'); } + elseif ($componentName == 'CiviCase') { + $compTable = 'civicrm_case'; + } else { $compTable = 'civicrm_participant'; } @@ -723,6 +726,12 @@ public static function contactDetails($componentIds, $componentName, $returnProp $from[$value] = " INNER JOIN civicrm_activity_contact acs ON (acs.activity_id = {$compTable}.id AND acs.record_type_id = {$sourceID}) INNER JOIN civicrm_contact contact ON ( contact.id = acs.contact_id )"; + } + elseif ($componentName == 'CiviCase') { + $select[] = "contact.$property as $property"; + $from[$value] = " +INNER JOIN civicrm_case_contact ccs ON (ccs.case_id = {$compTable}.id) +INNER JOIN civicrm_contact contact ON ( contact.id = ccs.contact_id )"; } else { $select[] = "$property as $property"; diff --git a/CRM/Core/BAO/UFField.php b/CRM/Core/BAO/UFField.php index 10dccc79db12..cf5430293f3c 100644 --- a/CRM/Core/BAO/UFField.php +++ b/CRM/Core/BAO/UFField.php @@ -994,10 +994,7 @@ public static function getAvailableFields($gid = NULL, $defaults = array()) { CRM_Utils_Array::remove($caseFields, 'case_id', 'case_type', - 'case_start_date', - 'case_end_date', 'case_role', - 'case_status', 'case_deleted' ); } diff --git a/CRM/Core/BAO/UFGroup.php b/CRM/Core/BAO/UFGroup.php index 493ec603ec29..89dcbd86a280 100644 --- a/CRM/Core/BAO/UFGroup.php +++ b/CRM/Core/BAO/UFGroup.php @@ -2233,6 +2233,14 @@ public static function buildProfile( $form->add('text', $name, $title, $attributes, $required); $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger'); } + elseif ($fieldName == 'case_status') { + $form->add('select', $name, $title, + array( + '' => ts('- select -'), + ) + CRM_Case_BAO_Case::buildOptions('case_status_id', 'create'), + $required + ); + } else { if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') { $form->add('advcheckbox', $name, $title, $attributes, $required); @@ -2514,6 +2522,11 @@ public static function setProfileDefaults( if ($component == 'Activity') { self::setComponentDefaults($fields, $componentId, $component, $defaults); } + + //Handling Case Part of the batch profile + if (CRM_Core_Permission::access('CiviCase') && $component == 'Case') { + self::setComponentDefaults($fields, $componentId, $component, $defaults); + } } /** @@ -3160,7 +3173,7 @@ public static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_ */ public static function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) { if (!$componentId || - !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity')) + !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity', 'Case')) ) { return; } @@ -3190,6 +3203,12 @@ public static function setComponentDefaults(&$fields, $componentId, $component, $componentBAOName = 'Activity'; $componentSubType = array('activity_type_id'); break; + + case 'Case': + $componentBAO = 'CRM_Case_BAO_Case'; + $componentBAOName = 'Case'; + $componentSubType = array('case_type_id'); + break; } $values = array(); @@ -3229,6 +3248,9 @@ public static function setComponentDefaults(&$fields, $componentId, $component, elseif ($name == 'membership_status') { $defaults[$fldName] = $values['status_id']; } + elseif ($name == 'case_status') { + $defaults[$fldName] = $values['case_status_id']; + } elseif (CRM_Core_BAO_CustomField::getKeyID($name, TRUE) !== array(NULL, NULL)) { if (empty($formattedGroupTree)) { //get the groupTree as per subTypes. diff --git a/templates/CRM/Case/Form/Task/Batch.tpl b/templates/CRM/Case/Form/Task/Batch.tpl new file mode 100644 index 000000000000..4a30553c0981 --- /dev/null +++ b/templates/CRM/Case/Form/Task/Batch.tpl @@ -0,0 +1,66 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2017 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +
+
+ {ts}Update field values for each case as needed. Click Update Cases below to save all your changes. To set a field to the same value for ALL rows, enter that value for the first case and then click the Copy icon (next to the column title).{/ts} +
+
+ {if $fields}{$form._qf_Batch_refresh.html}{/if}  {include file="CRM/common/formButtons.tpl" location="top"} +
+ + + + {foreach from=$readOnlyFields item=fTitle key=fName} + + {/foreach} + + {foreach from=$fields item=field key=fieldName} + + {/foreach} + + + {foreach from=$componentIds item=mid} + + + {foreach from=$readOnlyFields item=fTitle key=fName} + + {/foreach} + + {foreach from=$fields item=field key=fieldName} + {assign var=n value=$field.name} + + {/foreach} + + {/foreach} + +
{$fTitle}{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}{$field.title}
{$contactDetails.$mid.$fName}{$form.field.$mid.$n.html}
+
+ {if $fields}{$form._qf_Batch_refresh.html}{/if}  {include file="CRM/common/formButtons.tpl" location="bottom"} +
+
+ +{*include batch copy js js file*} +{include file="CRM/common/batchCopy.tpl"} diff --git a/templates/CRM/Case/Form/Task/PickProfile.tpl b/templates/CRM/Case/Form/Task/PickProfile.tpl new file mode 100644 index 000000000000..f3e075ecba21 --- /dev/null +++ b/templates/CRM/Case/Form/Task/PickProfile.tpl @@ -0,0 +1,37 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2017 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +
+
{include file="CRM/common/formButtons.tpl" location="top"}
+ + + + + + + +
{$form.uf_group_id.label}{$form.uf_group_id.html}
{include file="CRM/Case/Form/Task.tpl"}
+
{include file="CRM/common/formButtons.tpl" location="bottom"}
+