Add case ID and make subject optional for case detail report
[civicrm-core.git] / CRM / Report / Form / Contribute / Recur.php
CommitLineData
c1413e28
DG
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
c1413e28 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
c1413e28 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
c1413e28
DG
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
c1413e28
DG
16 */
17class CRM_Report_Form_Contribute_Recur extends CRM_Report_Form {
18
1728e9a0 19 /**
20 * This report has not been optimised for group filtering.
21 *
22 * The functionality for group filtering has been improved but not
23 * all reports have been adjusted to take care of it. This report has not
24 * and will run an inefficient query until fixed.
25 *
1728e9a0 26 * @var bool
0e480632 27 * @see https://issues.civicrm.org/jira/browse/CRM-19170
1728e9a0 28 */
29 protected $groupFilterNotOptimised = TRUE;
30
ced9bfed
EM
31 /**
32 * Class constructor.
33 */
00be9182 34 public function __construct() {
be2fb01f
CW
35 $this->_columns = [
36 'civicrm_contact' => [
c1413e28 37 'dao' => 'CRM_Contact_DAO_Contact',
be2fb01f
CW
38 'order_bys' => [
39 'sort_name' => [
c1413e28 40 'title' => ts("Last name, First name"),
be2fb01f
CW
41 ],
42 ],
43 'fields' => [
44 'sort_name' => [
c1413e28
DG
45 'title' => ts('Contact Name'),
46 'no_repeat' => TRUE,
47 'default' => TRUE,
be2fb01f
CW
48 ],
49 'id' => [
c1413e28
DG
50 'no_display' => TRUE,
51 'required' => TRUE,
be2fb01f
CW
52 ],
53 ],
54 ],
55 'civicrm_email' => [
c1413e28 56 'dao' => 'CRM_Core_DAO_Email',
be2fb01f
CW
57 'fields' => [
58 'email' => [
c1413e28
DG
59 'title' => ts('Email'),
60 'no_repeat' => TRUE,
be2fb01f
CW
61 ],
62 ],
c1413e28 63 'grouping' => 'contact-fields',
be2fb01f
CW
64 ],
65 'civicrm_phone' => [
c1413e28 66 'dao' => 'CRM_Core_DAO_Phone',
be2fb01f
CW
67 'fields' => [
68 'phone' => [
c1413e28
DG
69 'title' => ts('Phone'),
70 'no_repeat' => TRUE,
be2fb01f
CW
71 ],
72 ],
c1413e28 73 'grouping' => 'contact-fields',
be2fb01f
CW
74 ],
75 'civicrm_contribution' => [
c1413e28 76 'dao' => 'CRM_Contribute_DAO_Contribution',
be2fb01f
CW
77 'fields' => [
78 'id' => [
c1413e28
DG
79 'no_display' => TRUE,
80 'required' => TRUE,
be2fb01f
CW
81 ],
82 'total_amount' => [
c1413e28 83 'title' => ts('Amount Contributed to Date'),
be2fb01f 84 'statistics' => [
21dfd5f5 85 'sum' => ts("Total Amount Contributed"),
be2fb01f
CW
86 ],
87 ],
6dce38a5
AM
88 'source' => [
89 'title' => ts('Contribution Source'),
90 ],
be2fb01f
CW
91 ],
92 ],
93 'civicrm_financial_trxn' => [
96b82f45 94 'dao' => 'CRM_Financial_DAO_FinancialTrxn',
be2fb01f
CW
95 'fields' => [
96 'card_type_id' => [
d72b084a 97 'title' => ts('Credit Card Type'),
5e0343e8 98 'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
be2fb01f
CW
99 ],
100 ],
101 'filters' => [
102 'card_type_id' => [
d72b084a 103 'title' => ts('Credit Card Type'),
96b82f45 104 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
5e0343e8 105 'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
96b82f45
E
106 'default' => NULL,
107 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
108 ],
109 ],
110 ],
111 'civicrm_contribution_recur' => [
c1413e28 112 'dao' => 'CRM_Contribute_DAO_ContributionRecur',
be2fb01f
CW
113 'fields' => [
114 'id' => [
c1413e28
DG
115 'no_display' => TRUE,
116 'required' => TRUE,
be2fb01f
CW
117 ],
118 'currency' => [
c1413e28
DG
119 'title' => ts("Currency"),
120 'required' => TRUE,
121 'no_display' => TRUE,
be2fb01f
CW
122 ],
123 'contribution_status_id' => [
be205937 124 'title' => ts('Contribution Status'),
be2fb01f
CW
125 ],
126 'frequency_interval' => [
c1413e28
DG
127 'title' => ts('Frequency interval'),
128 'default' => TRUE,
be2fb01f
CW
129 ],
130 'frequency_unit' => [
c1413e28
DG
131 'title' => ts('Frequency unit'),
132 'default' => TRUE,
be2fb01f
CW
133 ],
134 'amount' => [
979f1561 135 'title' => ts('Installment Amount'),
2006e4c4 136 'default' => TRUE,
be2fb01f
CW
137 ],
138 'installments' => [
c1413e28
DG
139 'title' => ts('Installments'),
140 'default' => TRUE,
be2fb01f
CW
141 ],
142 'start_date' => [
c1413e28 143 'title' => ts('Start Date'),
be2fb01f
CW
144 ],
145 'create_date' => [
c1413e28 146 'title' => ts('Create Date'),
be2fb01f
CW
147 ],
148 'modified_date' => [
c1413e28 149 'title' => ts('Modified Date'),
be2fb01f
CW
150 ],
151 'cancel_date' => [
c1413e28 152 'title' => ts('Cancel Date'),
be2fb01f
CW
153 ],
154 'end_date' => [
c1413e28 155 'title' => ts('End Date'),
be2fb01f
CW
156 ],
157 'next_sched_contribution_date' => [
c1413e28 158 'title' => ts('Next Scheduled Contribution Date'),
be2fb01f
CW
159 ],
160 'failure_count' => [
c1413e28 161 'title' => ts('Failure Count'),
be2fb01f
CW
162 ],
163 'failure_retry_date' => [
c1413e28 164 'title' => ts('Failure Retry Date'),
be2fb01f
CW
165 ],
166 'payment_processor_id' => [
b7327f07 167 'title' => ts('Payment Processor'),
be2fb01f
CW
168 ],
169 ],
170 'filters' => [
171 'contribution_status_id' => [
be205937 172 'title' => ts('Contribution Status'),
c1413e28 173 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
c0aaecf9 174 'options' => CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'search'),
be2fb01f 175 'default' => [5],
c1413e28 176 'type' => CRM_Utils_Type::T_INT,
be2fb01f
CW
177 ],
178 'currency' => [
fd6a6828 179 'title' => ts('Currency'),
c1413e28
DG
180 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
181 'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
182 'default' => NULL,
183 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
184 ],
185 'financial_type_id' => [
c1413e28
DG
186 'title' => ts('Financial Type'),
187 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
51d1f926 188 'options' => CRM_Contribute_BAO_Contribution::buildOptions('financial_type_id', 'search'),
c1413e28 189 'type' => CRM_Utils_Type::T_INT,
be2fb01f
CW
190 ],
191 'frequency_unit' => [
c1413e28
DG
192 'title' => ts('Frequency Unit'),
193 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
84178120 194 'options' => CRM_Core_OptionGroup::values('recur_frequency_units'),
d3f09acb 195 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
196 ],
197 'frequency_interval' => [
c1413e28
DG
198 'title' => ts('Frequency Interval'),
199 'type' => CRM_Utils_Type::T_INT,
be2fb01f
CW
200 ],
201 'amount' => [
2006e4c4 202 'title' => ts('Installment Amount'),
203 'type' => CRM_Utils_Type::T_MONEY,
be2fb01f
CW
204 ],
205 'installments' => [
c1413e28
DG
206 'title' => ts('Installments'),
207 'type' => CRM_Utils_Type::T_INT,
be2fb01f
CW
208 ],
209 'start_date' => [
c1413e28
DG
210 'title' => ts('Start Date'),
211 'operatorType' => CRM_Report_Form::OP_DATE,
8fea776b 212 'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
be2fb01f
CW
213 ],
214 'next_sched_contribution_date' => [
c1413e28
DG
215 'title' => ts('Next Scheduled Contribution Date'),
216 'operatorType' => CRM_Report_Form::OP_DATE,
8fea776b 217 'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
be2fb01f
CW
218 ],
219 'end_date' => [
c1413e28
DG
220 'title' => ts('End Date'),
221 'operatorType' => CRM_Report_Form::OP_DATE,
8fea776b 222 'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
be2fb01f
CW
223 ],
224 'modified_date' => [
979f1561 225 'title' => ts('Last Contribution Processed'),
226 'operatorType' => CRM_Report_Form::OP_DATE,
8fea776b 227 'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
be2fb01f
CW
228 ],
229 'calculated_end_date' => [
c1413e28
DG
230 'title' => ts('Calculated end date (either end date or date all installments will be made)'),
231 'description' => "does this work?",
232 'operatorType' => CRM_Report_Form::OP_DATE,
21dfd5f5 233 'pseudofield' => TRUE,
be2fb01f
CW
234 ],
235 'payment_processor_id' => [
b7327f07
MWMC
236 'title' => ts('Payment Processor'),
237 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
238 'options' => CRM_Contribute_BAO_ContributionRecur::buildOptions('payment_processor_id', 'get'),
239 'default' => NULL,
240 'type' => CRM_Utils_Type::T_INT,
be2fb01f
CW
241 ],
242 ],
243 ],
244 ];
c1413e28 245 $this->_currencyColumn = 'civicrm_contribution_recur_currency';
979f1561 246 $this->_groupFilter = TRUE;
c1413e28
DG
247 parent::__construct();
248 }
353ffa53 249
ced9bfed
EM
250 /**
251 * Get template file name.
252 *
253 * @return string
254 */
00be9182 255 public function getTemplateName() {
84178120 256 return 'CRM/Report/Form.tpl';
c1413e28
DG
257 }
258
ced9bfed
EM
259 /**
260 * Generate FROM SQL clause.
261 */
00be9182 262 public function from() {
c1413e28
DG
263 $this->_from = "
264 FROM civicrm_contact {$this->_aliases['civicrm_contact']}
265 INNER JOIN civicrm_contribution_recur {$this->_aliases['civicrm_contribution_recur']}
266 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution_recur']}.contact_id";
267 $this->_from .= "
268 LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
269 ON {$this->_aliases['civicrm_contribution_recur']}.id = {$this->_aliases['civicrm_contribution']}.contribution_recur_id";
3b2bbbfb 270
271 $this->joinPhoneFromContact();
272 $this->joinEmailFromContact();
96b82f45
E
273
274 // for credit card type
987c1844 275 $this->addFinancialTrxnFromClause();
c1413e28
DG
276 }
277
00be9182 278 public function groupBy() {
b708c08d 279 $this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_contribution_recur']}.id");
c1413e28
DG
280 }
281
00be9182 282 public function where() {
c1413e28
DG
283 parent::where();
284 // Handle calculated end date. This can come from one of two sources:
285 // Either there is a specified end date for the end_date field
286 // Or, we calculate the end date based on the start date +
287 // installments * intervals using the mysql date_add function, along
288 // with the interval unit (e.g. DATE_ADD(start_date, INTERVAL 12 * 1 MONTH)
be2fb01f 289 $date_suffixes = ['relative', 'from', 'to'];
e34af001 290 foreach ($date_suffixes as $suffix) {
979f1561 291 $isBreak = FALSE;
c1413e28 292 // Check to see if the user wants to search by calculated date.
22e263ad 293 if (!empty($this->_params['calculated_end_date_' . $suffix])) {
c1413e28
DG
294 // The calculated date field is in use - spring into action
295 // Gather values
9c1bc317
CW
296 $relative = $this->_params["calculated_end_date_relative"] ?? NULL;
297 $from = $this->_params["calculated_end_date_from"] ?? NULL;
298 $to = $this->_params["calculated_end_date_to"] ?? NULL;
c1413e28
DG
299 $end_date_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['end_date']['dbAlias'];
300 $end_date_type = $this->_columns['civicrm_contribution_recur']['filters']['end_date']['type'];
301 $start_date_type = $this->_columns['civicrm_contribution_recur']['filters']['start_date']['type'];
302 $frequency_unit_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['frequency_unit']['dbAlias'];
303 $frequency_interval_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['frequency_interval']['dbAlias'];
304 $installments_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['installments']['dbAlias'];
305 $start_date_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['start_date']['dbAlias'];
306
307 // The end date clause is simple to construct
353ffa53 308 $end_date_clause = $this->dateClause($end_date_db_alias, $relative, $from, $to, $end_date_type, NULL, NULL);
c1413e28
DG
309
310 // NOTE: For the calculation based on installment, there doesn't
311 // seem to be a way to include the interval unit (e.g. month,
312 // date, etc) as a field name - so we have to build a complex
313 // OR statement instead.
314
979f1561 315 $this->_where .= 'AND (' .
c1413e28 316 $this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias,1) month)",
353ffa53 317 $relative, $from, $to, $start_date_type, NULL, NULL);
979f1561 318 $this->_where .= " AND $frequency_unit_db_alias = 'month' ) OR \n";
c1413e28 319
979f1561 320 $this->_where .= '(' .
c1413e28 321 $this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias,1) day)",
353ffa53 322 $relative, $from, $to, $start_date_type, NULL, NULL);
979f1561 323 $this->_where .= " AND $frequency_unit_db_alias = 'day' ) OR \n";
c1413e28 324
979f1561 325 $this->_where .= '(' .
c1413e28 326 $this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias, 1) week)",
353ffa53 327 $relative, $from, $to, $start_date_type, NULL, NULL);
cc3360ca 328 $this->_where .= " AND $frequency_unit_db_alias = 'week' ) OR \n";
c1413e28 329
979f1561 330 $this->_where .= '(' .
c1413e28 331 $this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias, 1) year)",
353ffa53 332 $relative, $from, $to, $start_date_type, NULL, NULL);
979f1561 333 $this->_where .= " AND $frequency_unit_db_alias = 'year' )
334 AND (($end_date_db_alias IS NOT NULL AND $end_date_clause)
335 OR ($installments_db_alias IS NOT NULL))
336";
337 $isBreak = TRUE;
338 }
8fea776b 339 if (!empty($this->_params['modified_date_' . $suffix])) {
340 $this->_where .= " AND {$this->_aliases['civicrm_contribution_recur']}.contribution_status_id = 1";
979f1561 341 $isBreak = TRUE;
342 }
343 if (!empty($isBreak)) {
c1413e28
DG
344 break;
345 }
346 }
347 }
348
ced9bfed
EM
349 /**
350 * Alter display of rows.
351 *
352 * Iterate through the rows retrieved via SQL and make changes for display purposes,
353 * such as rendering contacts as links.
354 *
355 * @param array $rows
356 * Rows generated by SQL, with an array for each row.
357 */
00be9182 358 public function alterDisplay(&$rows) {
c3b82060 359 $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'label');
c1413e28
DG
360 foreach ($rows as $rowNum => $row) {
361 // convert display name to links
362 if (array_key_exists('civicrm_contact_sort_name', $row) &&
363 CRM_Utils_Array::value('civicrm_contact_sort_name', $rows[$rowNum]) &&
364 array_key_exists('civicrm_contact_id', $row)
365 ) {
366 $url = CRM_Utils_System::url('civicrm/contact/view',
367 'reset=1&cid=' . $row['civicrm_contact_id'],
368 $this->_absoluteUrl
369 );
370 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
371 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Summary for this Contact.');
372 }
373
374 // handle contribution status id
375 if ($value = CRM_Utils_Array::value('civicrm_contribution_recur_contribution_status_id', $row)) {
376 $rows[$rowNum]['civicrm_contribution_recur_contribution_status_id'] = $contributionStatus[$value];
377 }
84178120 378
c1413e28 379 if ($value = CRM_Utils_Array::value('civicrm_contribution_recur_amount', $row)) {
84178120 380 $rows[$rowNum]['civicrm_contribution_recur_amount'] = CRM_Utils_Money::format($rows[$rowNum]['civicrm_contribution_recur_amount'], $rows[$rowNum]['civicrm_contribution_recur_currency']);
44fd0292 381 }
96b82f45 382
5e0343e8 383 if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
384 $rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
96b82f45 385 }
b7327f07
MWMC
386
387 if (!empty($row['civicrm_contribution_recur_payment_processor_id'])) {
388 $rows[$rowNum]['civicrm_contribution_recur_payment_processor_id'] = $this->getLabels($row['civicrm_contribution_recur_payment_processor_id'], 'CRM_Contribute_BAO_ContributionRecur', 'payment_processor_id');
389 }
c1413e28
DG
390 }
391 }
96025800 392
ef10e0b5 393}