From 395794c3bab8dd4b7a9b9dec6e4846c49d4287f2 Mon Sep 17 00:00:00 2001 From: Ahed Date: Tue, 29 Dec 2020 11:55:30 +0200 Subject: [PATCH 1/6] MAE-360: Rewrite subquery as join --- CRM/ManualDirectDebit/Hook/QueryObjects/Contribution.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CRM/ManualDirectDebit/Hook/QueryObjects/Contribution.php b/CRM/ManualDirectDebit/Hook/QueryObjects/Contribution.php index 1445cff9..7f0a03e3 100644 --- a/CRM/ManualDirectDebit/Hook/QueryObjects/Contribution.php +++ b/CRM/ManualDirectDebit/Hook/QueryObjects/Contribution.php @@ -25,12 +25,9 @@ public function from($fieldName, $mode, $side) { $from = ''; if ($fieldName == 'contribution_batch') { $from = " - $side JOIN ( - SELECT civicrm_entity_batch.entity_id, civicrm_entity_batch.batch_id - FROM civicrm_entity_batch, civicrm_batch - WHERE civicrm_entity_batch.entity_table = 'civicrm_contribution' - AND civicrm_entity_batch.batch_id = civicrm_batch.id - ) payment_batches ON payment_batches.entity_id = civicrm_contribution.id + $side JOIN civicrm_entity_batch payment_batches + ON (payment_batches.entity_table = 'civicrm_contribution' + AND payment_batches.entity_id = civicrm_contribution.id) "; } From 804bf09edeaa846403b22e66e10baba95bb7928d Mon Sep 17 00:00:00 2001 From: Ahed Date: Fri, 1 Jan 2021 19:56:32 +0200 Subject: [PATCH 2/6] MAE-360: Count batch items on submission --- .../Queue/Task/BatchSubmission/Completion.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CRM/ManualDirectDebit/Queue/Task/BatchSubmission/Completion.php b/CRM/ManualDirectDebit/Queue/Task/BatchSubmission/Completion.php index 00a782dc..32ddf903 100644 --- a/CRM/ManualDirectDebit/Queue/Task/BatchSubmission/Completion.php +++ b/CRM/ManualDirectDebit/Queue/Task/BatchSubmission/Completion.php @@ -6,11 +6,19 @@ public static function run(CRM_Queue_TaskContext $ctx, $batchId) { $session = CRM_Core_Session::singleton(); $loggedInUserId = $session->get('userID'); + $sqlQuery = 'SELECT COUNT(*) AS item_count + FROM civicrm_entity_batch + WHERE civicrm_entity_batch.batch_id = %1;'; + $itemCount = CRM_Core_DAO::singleValueQuery($sqlQuery, [ + 1 => [$batchId, 'Integer'], + ]); + civicrm_api3('Batch', 'create', [ 'id' => $batchId, 'status_id' => 'Submitted', 'modified_date' => date('YmdHis'), - 'modified_id' => $loggedInUserId + 'modified_id' => $loggedInUserId, + 'item_count' => $itemCount, ]); $ctx->log->info('Changing batch with Id : ' . $batchId . ' to Submitted'); From c993ca89f2ab6987f4e794bc7a231c9671d4df62 Mon Sep 17 00:00:00 2001 From: Ahed Date: Fri, 1 Jan 2021 22:53:11 +0200 Subject: [PATCH 3/6] MAE-360: Add instruction batch to constituent detail report --- .../Hook/Alter/ContactDetailReport.php | 157 ++++++++++++++++++ manualdirectdebit.php | 13 ++ 2 files changed, 170 insertions(+) create mode 100644 CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php diff --git a/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php b/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php new file mode 100644 index 00000000..ac4f21dc --- /dev/null +++ b/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php @@ -0,0 +1,157 @@ +shouldHandle(get_class($reportForm))) { + return; + } + + $methodName = 'update' . ucfirst($varType); + call_user_func_array([$this, $methodName], array(&$var)); + } + + /** + * Checks if the hook should be handled. + * + * @param class $reportFormClass + * + * @return bool + */ + protected function shouldHandle($reportFormClass) { + if ($reportFormClass === CRM_Report_Form_Contact_Detail::class) { + return TRUE; + } + return FALSE; + } + + /** + * Checks if the SQL should be updated. + * + * @param CRM_Report_Form_Contact_Detail $reportForm + * + * @return bool + */ + protected function shouldUpdate($reportForm) { + if ( + isset($reportForm->getVar('_params')['fields']['dd_instruction_batch_id']) + || isset($reportForm->getVar('_params')['dd_instruction_batch_id_value']) + || isset($reportForm->getVar('_params')['dd_instruction_batch_id_op']) + ) { + return TRUE; + } + return FALSE; + } + + /** + * Update column list + * + * @param array $columns + */ + protected function updateColumns(&$columns) { + $batches = $this->getBatches(); + $columns['civicrm_value_dd_mandate']['fields']['dd_instruction_batch_id'] = [ + 'title' => ts('Instruction Batch'), + 'dbAlias' => "instruction_batches.batch_id", + ]; + + $columns['civicrm_value_dd_mandate']['filters']['dd_instruction_batch_id'] = [ + 'title' => ts('Instruction Batch'), + 'dbAlias' => 'instruction_batches.batch_id', + 'type' => CRM_Utils_Type::T_INT, + 'operatorType' => CRM_Report_Form::OP_MULTISELECT, + 'options' => $batches, + ]; + } + + /** + * update the SQL Query + * + * @param CRM_Report_Form_Contact_Detail $reportForm + */ + protected function updateSql(&$reportForm) { + if (!$this->shouldUpdate($reportForm)) { + return; + } + + $from = $reportForm->getVar('_from'); + + // prevent double left join with civicrm_value_dd_mandate + if (strpos($from, 'civicrm_value_dd_mandate') === FALSE) { + $from .= " + LEFT JOIN civicrm_value_dd_mandate value_dd_mandate_civireport + ON (value_dd_mandate_civireport.entity_id = contact_civireport.id) + "; + } + + $from .= " + LEFT JOIN civicrm_entity_batch instruction_batches + ON (instruction_batches.entity_table = 'civicrm_value_dd_mandate' + AND instruction_batches.entity_id = value_dd_mandate_civireport.id) + "; + + $reportForm->setVar('_from', $from); + } + + /** + * Update rows for display + * + * @param array $rows + */ + protected function updateRows(&$rows) { + $batches = $this->getBatches(); + foreach ($rows as $rowNum => $row) { + if (isset($rows[$rowNum]['civicrm_value_dd_mandate_dd_instruction_batch_id'])) { + $rows[$rowNum]['civicrm_value_dd_mandate_dd_instruction_batch_id'] = $batches[$row['civicrm_value_dd_mandate_dd_instruction_batch_id']] ?? NULL; + } + } + } + + /** + * Get Batches + * + * @return array $batches + */ + protected function getBatches() { + if (count($this->_batches)) { + return $this->_batches; + } + + $condition = " AND ( + v.name = '" . BatchHandler::BATCH_TYPE_INSTRUCTIONS . "' + OR v.name = '" . BatchHandler::BATCH_TYPE_PAYMENTS . "' + OR v.name = '" . BatchHandler::BATCH_TYPE_CANCELLATIONS . "' + )"; + $batchTypeIds = CRM_Core_OptionGroup::values('batch_type', FALSE, FALSE, FALSE, $condition, 'value'); + + $params = [ + 'type_id' => ['IN' => $batchTypeIds], + 'return' => ['id', 'title'], + ]; + $result = civicrm_api3('Batch', 'get', $params); + + foreach ($result['values'] as $batch) { + $this->_batches[$batch['id']] = $batch['title']; + } + return $this->_batches; + } + +} diff --git a/manualdirectdebit.php b/manualdirectdebit.php index f828883f..565ebc8a 100755 --- a/manualdirectdebit.php +++ b/manualdirectdebit.php @@ -441,3 +441,16 @@ function manualdirectdebit_civicrm_queryObjects(&$queryObjects, $type) { $queryObjects[] = new CRM_ManualDirectDebit_Hook_QueryObjects_Contribution(); } } + +/** + * Implements hook_civicrm_alterReportVar(). + */ +function manualdirectdebit_civicrm_alterReportVar($varType, &$var, $reportForm) { + $listeners = [ + new CRM_ManualDirectDebit_Hook_Alter_ContactDetailReport(), + ]; + + foreach ($listeners as $currentListener) { + $currentListener->handle($varType, $var, $reportForm); + } +} From 4b0a613d0bad475528d59f9bf30ab3cfc0b509e6 Mon Sep 17 00:00:00 2001 From: Ahed Date: Fri, 1 Jan 2021 22:53:58 +0200 Subject: [PATCH 4/6] MAE-360: Add payment batch to contribution detail report --- .../Hook/Alter/ContributeDetailReport.php | 159 ++++++++++++++++++ manualdirectdebit.php | 1 + 2 files changed, 160 insertions(+) create mode 100644 CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php diff --git a/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php b/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php new file mode 100644 index 00000000..265438c8 --- /dev/null +++ b/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php @@ -0,0 +1,159 @@ +shouldHandle(get_class($reportForm))) { + return; + } + + $methodName = 'update' . ucfirst($varType); + call_user_func_array([$this, $methodName], array(&$var)); + + // @note Bug1: Updating columns and sql will not work the same way like in ContactDetailReport.php + // because the changes that have done by sql hook will be lost in + // https://github.com/civicrm/civicrm-core/blob/3662d5a75d79d6c259b632df748b1beb66db6faf/CRM/Report/Form/Contribute/Detail.php#L956 + + // @note Bug2: The sql query wil not work if the user used this column or filter + // so the column will not be availbe in the form and in the POST request + if ($varType === 'columns') { + // we have to use the request because reportForm->_params variable is null + $fields = CRM_Utils_Request::retrieveValue('fields', 'String', []); + if (isset($fields['dd_payment_batch_id'])) { + unset($var['civicrm_value_dd_information']['fields']['dd_payment_batch_id']); + } + } + } + + /** + * Checks if the hook should be handled. + * + * @param class $reportFormClass + * + * @return bool + */ + protected function shouldHandle($reportFormClass) { + if ($reportFormClass === CRM_Report_Form_Contribute_Detail::class) { + return TRUE; + } + return FALSE; + } + + /** + * Checks if the SQL should be updated. + * + * @param CRM_Report_Form_Contribute_Detail $reportForm + * + * @return bool + */ + protected function shouldUpdate($reportForm) { + // @note related to Bug2 + $fields = CRM_Utils_Request::retrieveValue('fields', 'String', []); + if (isset($fields['dd_payment_batch_id'])) { + return TRUE; + } + + return FALSE; + } + + /** + * Update column list + * + * @param array $columns + */ + protected function updateColumns(&$columns) { + $batches = $this->getBatches(); + + $columns['civicrm_value_dd_information']['fields']['dd_payment_batch_id'] = [ + 'title' => ts('Payment Batch'), + 'dbAlias' => "payment_batches.batch_id", + ]; + } + + /** + * update the SQL Query + * + * @param CRM_Report_Form_Contact_Detail $reportForm + */ + protected function updateSql(&$reportForm) { + if (!$this->shouldUpdate($reportForm)) { + return; + } + + // @note related to Bug2 + $reportForm->_columnHeaders['civicrm_value_dd_information_dd_payment_batch_id'] = array( + 'title' => ts('Payment Batch'), + ); + + $reportForm->_select .= ' , GROUP_CONCAT(DISTINCT payment_batches.batch_id) as civicrm_value_dd_information_dd_payment_batch_id '; + $from = $reportForm->getVar('_from'); + $from .= " + LEFT JOIN civicrm_entity_batch payment_batches + ON (payment_batches.entity_table = 'civicrm_contribution' + AND payment_batches.entity_id = contribution_civireport.id) + "; + $reportForm->setVar('_from', $from); + } + + /** + * Update rows for display + * + * @param array $rows + */ + protected function updateRows(&$rows) { + $batches = $this->getBatches(); + foreach ($rows as $rowNum => $row) { + if (isset($rows[$rowNum]['civicrm_value_dd_information_dd_payment_batch_id'])) { + $rows[$rowNum]['civicrm_value_dd_information_dd_payment_batch_id'] = $batches[$row['civicrm_value_dd_information_dd_payment_batch_id']] ?? NULL; + } + } + } + + /** + * Get Batches + * + * @return array $batches + */ + protected function getBatches() { + if (count($this->_batches)) { + return $this->_batches; + } + + $condition = " AND ( + v.name = '" . BatchHandler::BATCH_TYPE_INSTRUCTIONS . "' + OR v.name = '" . BatchHandler::BATCH_TYPE_PAYMENTS . "' + OR v.name = '" . BatchHandler::BATCH_TYPE_CANCELLATIONS . "' + )"; + $batchTypeIds = CRM_Core_OptionGroup::values('batch_type', FALSE, FALSE, FALSE, $condition, 'value'); + + $params = [ + 'type_id' => ['IN' => $batchTypeIds], + 'return' => ['id', 'title'], + ]; + $result = civicrm_api3('Batch', 'get', $params); + + foreach ($result['values'] as $batch) { + $this->_batches[$batch['id']] = $batch['title']; + } + return $this->_batches; + } + +} diff --git a/manualdirectdebit.php b/manualdirectdebit.php index 565ebc8a..4121e30a 100755 --- a/manualdirectdebit.php +++ b/manualdirectdebit.php @@ -448,6 +448,7 @@ function manualdirectdebit_civicrm_queryObjects(&$queryObjects, $type) { function manualdirectdebit_civicrm_alterReportVar($varType, &$var, $reportForm) { $listeners = [ new CRM_ManualDirectDebit_Hook_Alter_ContactDetailReport(), + new CRM_ManualDirectDebit_Hook_Alter_ContributeDetailReport(), ]; foreach ($listeners as $currentListener) { From 09c40fa68772482c992ff4701f39caee2d70d8f6 Mon Sep 17 00:00:00 2001 From: Ahed Date: Mon, 4 Jan 2021 17:59:04 +0200 Subject: [PATCH 5/6] MAE-360: change methods/attributes visibility and set the api limit --- .../Hook/Alter/ContactDetailReport.php | 15 ++++++++------- .../Hook/Alter/ContributeDetailReport.php | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php b/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php index ac4f21dc..161a4796 100644 --- a/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php +++ b/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php @@ -11,7 +11,7 @@ class CRM_ManualDirectDebit_Hook_Alter_ContactDetailReport { * * @var array */ - protected $_batches = []; + private $_batches = []; /** * Handle the hook. @@ -36,7 +36,7 @@ public function handle($varType, &$var, &$reportForm) { * * @return bool */ - protected function shouldHandle($reportFormClass) { + private function shouldHandle($reportFormClass) { if ($reportFormClass === CRM_Report_Form_Contact_Detail::class) { return TRUE; } @@ -50,7 +50,7 @@ protected function shouldHandle($reportFormClass) { * * @return bool */ - protected function shouldUpdate($reportForm) { + private function shouldUpdate($reportForm) { if ( isset($reportForm->getVar('_params')['fields']['dd_instruction_batch_id']) || isset($reportForm->getVar('_params')['dd_instruction_batch_id_value']) @@ -66,7 +66,7 @@ protected function shouldUpdate($reportForm) { * * @param array $columns */ - protected function updateColumns(&$columns) { + private function updateColumns(&$columns) { $batches = $this->getBatches(); $columns['civicrm_value_dd_mandate']['fields']['dd_instruction_batch_id'] = [ 'title' => ts('Instruction Batch'), @@ -87,7 +87,7 @@ protected function updateColumns(&$columns) { * * @param CRM_Report_Form_Contact_Detail $reportForm */ - protected function updateSql(&$reportForm) { + private function updateSql(&$reportForm) { if (!$this->shouldUpdate($reportForm)) { return; } @@ -116,7 +116,7 @@ protected function updateSql(&$reportForm) { * * @param array $rows */ - protected function updateRows(&$rows) { + private function updateRows(&$rows) { $batches = $this->getBatches(); foreach ($rows as $rowNum => $row) { if (isset($rows[$rowNum]['civicrm_value_dd_mandate_dd_instruction_batch_id'])) { @@ -130,7 +130,7 @@ protected function updateRows(&$rows) { * * @return array $batches */ - protected function getBatches() { + private function getBatches() { if (count($this->_batches)) { return $this->_batches; } @@ -144,6 +144,7 @@ protected function getBatches() { $params = [ 'type_id' => ['IN' => $batchTypeIds], + 'options' => ['limit' => 0], 'return' => ['id', 'title'], ]; $result = civicrm_api3('Batch', 'get', $params); diff --git a/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php b/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php index 265438c8..428542e9 100644 --- a/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php +++ b/CRM/ManualDirectDebit/Hook/Alter/ContributeDetailReport.php @@ -11,7 +11,7 @@ class CRM_ManualDirectDebit_Hook_Alter_ContributeDetailReport { * * @var array */ - protected $_batches = []; + private $_batches = []; /** * Handle the hook. @@ -50,7 +50,7 @@ public function handle($varType, &$var, &$reportForm) { * * @return bool */ - protected function shouldHandle($reportFormClass) { + private function shouldHandle($reportFormClass) { if ($reportFormClass === CRM_Report_Form_Contribute_Detail::class) { return TRUE; } @@ -64,7 +64,7 @@ protected function shouldHandle($reportFormClass) { * * @return bool */ - protected function shouldUpdate($reportForm) { + private function shouldUpdate($reportForm) { // @note related to Bug2 $fields = CRM_Utils_Request::retrieveValue('fields', 'String', []); if (isset($fields['dd_payment_batch_id'])) { @@ -79,7 +79,7 @@ protected function shouldUpdate($reportForm) { * * @param array $columns */ - protected function updateColumns(&$columns) { + private function updateColumns(&$columns) { $batches = $this->getBatches(); $columns['civicrm_value_dd_information']['fields']['dd_payment_batch_id'] = [ @@ -93,7 +93,7 @@ protected function updateColumns(&$columns) { * * @param CRM_Report_Form_Contact_Detail $reportForm */ - protected function updateSql(&$reportForm) { + private function updateSql(&$reportForm) { if (!$this->shouldUpdate($reportForm)) { return; } @@ -118,7 +118,7 @@ protected function updateSql(&$reportForm) { * * @param array $rows */ - protected function updateRows(&$rows) { + private function updateRows(&$rows) { $batches = $this->getBatches(); foreach ($rows as $rowNum => $row) { if (isset($rows[$rowNum]['civicrm_value_dd_information_dd_payment_batch_id'])) { @@ -132,7 +132,7 @@ protected function updateRows(&$rows) { * * @return array $batches */ - protected function getBatches() { + private function getBatches() { if (count($this->_batches)) { return $this->_batches; } @@ -146,6 +146,7 @@ protected function getBatches() { $params = [ 'type_id' => ['IN' => $batchTypeIds], + 'options' => ['limit' => 0], 'return' => ['id', 'title'], ]; $result = civicrm_api3('Batch', 'get', $params); From 6d68493016e2f9f9b667e8cca98bd40bcc1e9893 Mon Sep 17 00:00:00 2001 From: Ahed Date: Mon, 4 Jan 2021 23:29:07 +0200 Subject: [PATCH 6/6] MAE-360: Refactor shouldUpdate check This refactor will help checking filters properly and to prevent handling any filter with missing or improper value --- .../Hook/Alter/ContactDetailReport.php | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php b/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php index 161a4796..387565ff 100644 --- a/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php +++ b/CRM/ManualDirectDebit/Hook/Alter/ContactDetailReport.php @@ -51,10 +51,49 @@ private function shouldHandle($reportFormClass) { * @return bool */ private function shouldUpdate($reportForm) { - if ( - isset($reportForm->getVar('_params')['fields']['dd_instruction_batch_id']) - || isset($reportForm->getVar('_params')['dd_instruction_batch_id_value']) - || isset($reportForm->getVar('_params')['dd_instruction_batch_id_op']) + $params = $reportForm->getVar('_params'); + if ($this->checkField($params, 'dd_instruction_batch_id') + || $this->checkFilter($params, 'dd_instruction_batch_id') + ) { + return TRUE; + } + return FALSE; + } + + /** + * Checks if field exists + * + * @param array $params + * @param string $field + * + * @return bool + */ + private function checkField($params, $field) { + if (isset(($params['fields'][$field]))) { + return TRUE; + } + return FALSE; + } + + /** + * Checks if filter exists + * + * @param array $params + * @param string $filter + * + * @return bool + */ + private function checkFilter($params, $filter) { + $filterName = $filter . '_value'; + $filterOpName = $filter . '_op'; + if (isset($params[$filterOpName]) + && in_array($params[$filterOpName], ['nll', 'nnll']) + ) { + return TRUE; + } + if (isset($params[$filterOpName]) + && in_array($params[$filterOpName], ['in', 'notin']) + && !empty($params[$filterName]) ) { return TRUE; }