Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 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 | | |
6a488035 TO |
9 | +--------------------------------------------------------------------+ |
10 | */ | |
11 | ||
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
ce064e4f | 19 | * Batch BAO class. |
6a488035 TO |
20 | */ |
21 | class CRM_Batch_BAO_Batch extends CRM_Batch_DAO_Batch { | |
22 | ||
23 | /** | |
eceb18cc | 24 | * Cache for the current batch object. |
62d3ee27 | 25 | * @var object |
6a488035 | 26 | */ |
62d3ee27 | 27 | public static $_batch = NULL; |
6a488035 TO |
28 | |
29 | /** | |
30 | * Not sure this is the best way to do this. Depends on how exportFinancialBatch() below gets called. | |
31 | * Maybe a parameter to that function is better. | |
62d3ee27 | 32 | * @var string |
6a488035 | 33 | */ |
62d3ee27 | 34 | public static $_exportFormat = NULL; |
6a488035 TO |
35 | |
36 | /** | |
eceb18cc | 37 | * Create a new batch. |
6a488035 | 38 | * |
82d480a5 | 39 | * @param array $params |
6a488035 | 40 | * |
a6c01b45 CW |
41 | * @return object |
42 | * $batch batch object | |
6a488035 | 43 | */ |
92e088c9 | 44 | public static function create(&$params) { |
debff434 | 45 | $op = 'edit'; |
9c1bc317 | 46 | $batchId = $params['id'] ?? NULL; |
debff434 PN |
47 | if (!$batchId) { |
48 | $op = 'create'; | |
6a488035 TO |
49 | $params['name'] = CRM_Utils_String::titleToVar($params['title']); |
50 | } | |
debff434 | 51 | CRM_Utils_Hook::pre($op, 'Batch', $batchId, $params); |
6a488035 TO |
52 | $batch = new CRM_Batch_DAO_Batch(); |
53 | $batch->copyValues($params); | |
6a488035 TO |
54 | $batch->save(); |
55 | ||
debff434 PN |
56 | CRM_Utils_Hook::post($op, 'Batch', $batch->id, $batch); |
57 | ||
6a488035 TO |
58 | return $batch; |
59 | } | |
60 | ||
61 | /** | |
eceb18cc | 62 | * Retrieve the information about the batch. |
6a488035 | 63 | * |
82d480a5 TO |
64 | * @param array $params |
65 | * (reference ) an assoc array of name/value pairs. | |
66 | * @param array $defaults | |
67 | * (reference ) an assoc array to hold the flattened values. | |
6a488035 | 68 | * |
a6c01b45 CW |
69 | * @return array |
70 | * CRM_Batch_BAO_Batch object on success, null otherwise | |
6a488035 | 71 | */ |
00be9182 | 72 | public static function retrieve(&$params, &$defaults) { |
6a488035 TO |
73 | $batch = new CRM_Batch_DAO_Batch(); |
74 | $batch->copyValues($params); | |
75 | if ($batch->find(TRUE)) { | |
76 | CRM_Core_DAO::storeValues($batch, $defaults); | |
77 | return $batch; | |
78 | } | |
79 | return NULL; | |
80 | } | |
81 | ||
82 | /** | |
eceb18cc | 83 | * Get profile id associated with the batch type. |
6a488035 | 84 | * |
82d480a5 TO |
85 | * @param int $batchTypeId |
86 | * Batch type id. | |
6a488035 | 87 | * |
a6c01b45 CW |
88 | * @return int |
89 | * $profileId profile id | |
6a488035 | 90 | */ |
00be9182 | 91 | public static function getProfileId($batchTypeId) { |
6a488035 TO |
92 | //retrieve the profile specific to batch type |
93 | switch ($batchTypeId) { | |
94 | case 1: | |
9fa00ed1 | 95 | case 3: |
96 | //batch profile used for pledges | |
6a488035 TO |
97 | $profileName = "contribution_batch_entry"; |
98 | break; | |
99 | ||
100 | case 2: | |
101 | //batch profile used for memberships | |
102 | $profileName = "membership_batch_entry"; | |
04e6444d | 103 | break; |
6a488035 TO |
104 | } |
105 | ||
106 | // get and return the profile id | |
107 | return CRM_Core_DAO::getFieldValue('CRM_Core_BAO_UFGroup', $profileName, 'id', 'name'); | |
108 | } | |
109 | ||
110 | /** | |
eceb18cc | 111 | * Generate batch name. |
6a488035 | 112 | * |
72b3a70c CW |
113 | * @return string |
114 | * batch name | |
6a488035 | 115 | */ |
00be9182 | 116 | public static function generateBatchName() { |
6a488035 TO |
117 | $sql = "SELECT max(id) FROM civicrm_batch"; |
118 | $batchNo = CRM_Core_DAO::singleValueQuery($sql) + 1; | |
be2fb01f | 119 | return ts('Batch %1', [1 => $batchNo]) . ': ' . date('Y-m-d'); |
6a488035 TO |
120 | } |
121 | ||
6a488035 | 122 | /** |
eceb18cc | 123 | * Delete batch entry. |
6a488035 | 124 | * |
82d480a5 TO |
125 | * @param int $batchId |
126 | * Batch id. | |
6a488035 | 127 | * |
72b3a70c | 128 | * @return bool |
6a488035 | 129 | */ |
00be9182 | 130 | public static function deleteBatch($batchId) { |
6a488035 | 131 | // delete entry from batch table |
8f30d0b9 | 132 | CRM_Utils_Hook::pre('delete', 'Batch', $batchId, CRM_Core_DAO::$_nullArray); |
6a488035 TO |
133 | $batch = new CRM_Batch_DAO_Batch(); |
134 | $batch->id = $batchId; | |
135 | $batch->delete(); | |
8f30d0b9 | 136 | CRM_Utils_Hook::post('delete', 'Batch', $batch->id, $batch); |
691df66d | 137 | return TRUE; |
6a488035 TO |
138 | } |
139 | ||
6a488035 | 140 | /** |
eceb18cc | 141 | * wrapper for ajax batch selector. |
6a488035 | 142 | * |
82d480a5 TO |
143 | * @param array $params |
144 | * Associated array for params record id. | |
6a488035 | 145 | * |
a6c01b45 CW |
146 | * @return array |
147 | * associated array of batch list | |
6a488035 | 148 | */ |
3fab79d8 | 149 | public static function getBatchListSelector(&$params) { |
6a488035 TO |
150 | // format the params |
151 | $params['offset'] = ($params['page'] - 1) * $params['rp']; | |
152 | $params['rowCount'] = $params['rp']; | |
9c1bc317 | 153 | $params['sort'] = $params['sortBy'] ?? NULL; |
6a488035 TO |
154 | |
155 | // get batches | |
156 | $batches = self::getBatchList($params); | |
157 | ||
158 | // get batch totals for open batches | |
be2fb01f CW |
159 | $fetchTotals = []; |
160 | $batchStatus = CRM_Core_PseudoConstant::get('CRM_Batch_DAO_Batch', 'status_id', ['labelColumn' => 'name']); | |
161 | $batchStatus = [ | |
2d818e4a PN |
162 | array_search('Open', $batchStatus), |
163 | array_search('Reopened', $batchStatus), | |
be2fb01f | 164 | ]; |
6a488035 TO |
165 | if ($params['context'] == 'financialBatch') { |
166 | foreach ($batches as $id => $batch) { | |
2d818e4a | 167 | if (in_array($batch['status_id'], $batchStatus)) { |
6a488035 TO |
168 | $fetchTotals[] = $id; |
169 | } | |
170 | } | |
171 | } | |
172 | $totals = self::batchTotals($fetchTotals); | |
173 | ||
174 | // add count | |
175 | $params['total'] = self::getBatchCount($params); | |
176 | ||
177 | // format params and add links | |
be2fb01f | 178 | $batchList = []; |
6a488035 TO |
179 | |
180 | foreach ($batches as $id => $value) { | |
be2fb01f | 181 | $batch = []; |
6a488035 TO |
182 | if ($params['context'] == 'financialBatch') { |
183 | $batch['check'] = $value['check']; | |
184 | } | |
185 | $batch['batch_name'] = $value['title']; | |
957bbb1d | 186 | $batch['total'] = ''; |
6a488035 | 187 | $batch['payment_instrument'] = $value['payment_instrument']; |
9c1bc317 CW |
188 | $batch['item_count'] = $value['item_count'] ?? NULL; |
189 | $batch['type'] = $value['batch_type'] ?? NULL; | |
a7488080 | 190 | if (!empty($value['total'])) { |
def0f6ae BS |
191 | // CRM-21205 |
192 | $batch['total'] = CRM_Utils_Money::format($value['total'], $value['currency']); | |
6a488035 TO |
193 | } |
194 | ||
195 | // Compare totals with actuals | |
196 | if (isset($totals[$id])) { | |
197 | $batch['item_count'] = self::displayTotals($totals[$id]['item_count'], $batch['item_count']); | |
198 | $batch['total'] = self::displayTotals(CRM_Utils_Money::format($totals[$id]['total']), $batch['total']); | |
199 | } | |
200 | $batch['status'] = $value['batch_status']; | |
201 | $batch['created_by'] = $value['created_by']; | |
202 | $batch['links'] = $value['action']; | |
203 | $batchList[$id] = $batch; | |
204 | } | |
205 | return $batchList; | |
206 | } | |
207 | ||
208 | /** | |
eceb18cc | 209 | * Get list of batches. |
6a488035 | 210 | * |
82d480a5 TO |
211 | * @param array $params |
212 | * Associated array for params. | |
102fe859 EM |
213 | * |
214 | * @return array | |
6a488035 | 215 | */ |
00be9182 | 216 | public static function getBatchList(&$params) { |
857236d0 | 217 | $apiParams = self::whereClause($params); |
6a488035 TO |
218 | |
219 | if (!empty($params['rowCount']) && is_numeric($params['rowCount']) | |
220 | && is_numeric($params['offset']) && $params['rowCount'] > 0 | |
221 | ) { | |
be2fb01f | 222 | $apiParams['options'] = ['offset' => $params['offset'], 'limit' => $params['rowCount']]; |
6a488035 | 223 | } |
857236d0 | 224 | $apiParams['options']['sort'] = 'id DESC'; |
6a488035 | 225 | if (!empty($params['sort'])) { |
857236d0 | 226 | $apiParams['options']['sort'] = CRM_Utils_Type::escape($params['sort'], 'String'); |
6a488035 TO |
227 | } |
228 | ||
be2fb01f | 229 | $return = [ |
857236d0 PN |
230 | "id", |
231 | "name", | |
232 | "title", | |
233 | "description", | |
234 | "created_date", | |
235 | "status_id", | |
236 | "modified_id", | |
237 | "modified_date", | |
238 | "type_id", | |
239 | "mode_id", | |
240 | "total", | |
241 | "item_count", | |
242 | "exported_date", | |
243 | "payment_instrument_id", | |
244 | "created_id.sort_name", | |
245 | "created_id", | |
be2fb01f | 246 | ]; |
857236d0 PN |
247 | $apiParams['return'] = $return; |
248 | $batches = civicrm_api3('Batch', 'get', $apiParams); | |
3fab79d8 | 249 | $obj = new CRM_Batch_BAO_Batch(); |
a7488080 | 250 | if (!empty($params['context'])) { |
3fab79d8 | 251 | $links = $obj->links($params['context']); |
6a488035 TO |
252 | } |
253 | else { | |
3fab79d8 | 254 | $links = $obj->links(); |
6a488035 TO |
255 | } |
256 | ||
97afa853 AS |
257 | $batchTypes = CRM_Core_PseudoConstant::get('CRM_Batch_DAO_Batch', 'type_id'); |
258 | $batchStatus = CRM_Core_PseudoConstant::get('CRM_Batch_DAO_Batch', 'status_id'); | |
be2fb01f | 259 | $batchStatusByName = CRM_Core_PseudoConstant::get('CRM_Batch_DAO_Batch', 'status_id', ['labelColumn' => 'name']); |
6a488035 TO |
260 | $paymentInstrument = CRM_Contribute_PseudoConstant::paymentInstrument(); |
261 | ||
be2fb01f | 262 | $results = []; |
857236d0 | 263 | foreach ($batches['values'] as $values) { |
6a488035 | 264 | $newLinks = $links; |
6a488035 TO |
265 | $action = array_sum(array_keys($newLinks)); |
266 | ||
2d818e4a | 267 | if ($values['status_id'] == array_search('Closed', $batchStatusByName) && $params['context'] != 'financialBatch') { |
be2fb01f | 268 | $newLinks = []; |
6a488035 TO |
269 | } |
270 | elseif ($params['context'] == 'financialBatch') { | |
6c552737 | 271 | $values['check'] = "<input type='checkbox' id='check_" . |
857236d0 | 272 | $values['id'] . |
0b0941e2 | 273 | "' name='check_" . |
857236d0 | 274 | $values['id'] . |
0b0941e2 | 275 | "' value='1' data-status_id='" . |
92fcb95f | 276 | $values['status_id'] . "' class='select-row'></input>"; |
6a488035 | 277 | |
2d818e4a PN |
278 | switch ($batchStatusByName[$values['status_id']]) { |
279 | case 'Open': | |
ca0e2dda | 280 | case 'Reopened': |
6a488035 TO |
281 | CRM_Utils_Array::remove($newLinks, 'reopen', 'download'); |
282 | break; | |
691df66d | 283 | |
2d818e4a | 284 | case 'Closed': |
6a488035 TO |
285 | CRM_Utils_Array::remove($newLinks, 'close', 'edit', 'download'); |
286 | break; | |
691df66d | 287 | |
2d818e4a | 288 | case 'Exported': |
6a488035 TO |
289 | CRM_Utils_Array::remove($newLinks, 'close', 'edit', 'reopen', 'export'); |
290 | } | |
ca0e2dda | 291 | if (!CRM_Batch_BAO_Batch::checkBatchPermission('edit', $values['created_id'])) { |
f07fc4c9 PN |
292 | CRM_Utils_Array::remove($newLinks, 'edit'); |
293 | } | |
294 | if (!CRM_Batch_BAO_Batch::checkBatchPermission('close', $values['created_id'])) { | |
295 | CRM_Utils_Array::remove($newLinks, 'close', 'export'); | |
296 | } | |
297 | if (!CRM_Batch_BAO_Batch::checkBatchPermission('reopen', $values['created_id'])) { | |
298 | CRM_Utils_Array::remove($newLinks, 'reopen'); | |
ca0e2dda PN |
299 | } |
300 | if (!CRM_Batch_BAO_Batch::checkBatchPermission('export', $values['created_id'])) { | |
301 | CRM_Utils_Array::remove($newLinks, 'export', 'download'); | |
302 | } | |
303 | if (!CRM_Batch_BAO_Batch::checkBatchPermission('delete', $values['created_id'])) { | |
304 | CRM_Utils_Array::remove($newLinks, 'delete'); | |
305 | } | |
6a488035 | 306 | } |
a7488080 | 307 | if (!empty($values['type_id'])) { |
6a488035 TO |
308 | $values['batch_type'] = $batchTypes[$values['type_id']]; |
309 | } | |
310 | $values['batch_status'] = $batchStatus[$values['status_id']]; | |
857236d0 | 311 | $values['created_by'] = $values['created_id.sort_name']; |
6a488035 | 312 | $values['payment_instrument'] = ''; |
857236d0 PN |
313 | if (!empty($values['payment_instrument_id'])) { |
314 | $values['payment_instrument'] = $paymentInstrument[$values['payment_instrument_id']]; | |
6a488035 | 315 | } |
be2fb01f | 316 | $tokens = ['id' => $values['id'], 'status' => $values['status_id']]; |
2d818e4a | 317 | if ($values['status_id'] == array_search('Exported', $batchStatusByName)) { |
857236d0 | 318 | $aid = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Export Accounting Batch'); |
be2fb01f | 319 | $activityParams = ['source_record_id' => $values['id'], 'activity_type_id' => $aid]; |
6a488035 | 320 | $exportActivity = CRM_Activity_BAO_Activity::retrieve($activityParams, $val); |
83cab05a JG |
321 | if ($exportActivity) { |
322 | $fid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_EntityFile', $exportActivity->id, 'file_id', 'entity_id'); | |
323 | $fileHash = CRM_Core_BAO_File::generateFileHash($exportActivity->id, $fid); | |
324 | $tokens = array_merge(['eid' => $exportActivity->id, 'fid' => $fid, 'fcs' => $fileHash], $tokens); | |
325 | } | |
326 | else { | |
327 | CRM_Utils_Array::remove($newLinks, 'export', 'download'); | |
328 | } | |
6a488035 TO |
329 | } |
330 | $values['action'] = CRM_Core_Action::formLink( | |
331 | $newLinks, | |
332 | $action, | |
c51d1602 | 333 | $tokens, |
87dab4a4 AH |
334 | ts('more'), |
335 | FALSE, | |
336 | 'batch.selector.row', | |
337 | 'Batch', | |
857236d0 | 338 | $values['id'] |
6a488035 | 339 | ); |
def0f6ae BS |
340 | // CRM-21205 |
341 | $values['currency'] = CRM_Core_DAO::singleValueQuery(" | |
342 | SELECT GROUP_CONCAT(DISTINCT ft.currency) | |
343 | FROM civicrm_batch batch | |
344 | JOIN civicrm_entity_batch eb | |
345 | ON batch.id = eb.batch_id | |
346 | JOIN civicrm_financial_trxn ft | |
347 | ON eb.entity_id = ft.id | |
348 | WHERE batch.id = %1 | |
349 | GROUP BY batch.id | |
be2fb01f | 350 | ", [1 => [$values['id'], 'Positive']]); |
857236d0 | 351 | $results[$values['id']] = $values; |
6a488035 TO |
352 | } |
353 | ||
354 | return $results; | |
355 | } | |
356 | ||
357 | /** | |
eceb18cc | 358 | * Get count of batches. |
6a488035 | 359 | * |
82d480a5 TO |
360 | * @param array $params |
361 | * Associated array for params. | |
102fe859 EM |
362 | * |
363 | * @return null|string | |
6a488035 | 364 | */ |
b11c92be | 365 | public static function getBatchCount(&$params) { |
857236d0 PN |
366 | $apiParams = self::whereClause($params); |
367 | return civicrm_api3('Batch', 'getCount', $apiParams); | |
6a488035 TO |
368 | } |
369 | ||
370 | /** | |
eceb18cc | 371 | * Format where clause for getting lists of batches. |
6a488035 | 372 | * |
82d480a5 TO |
373 | * @param array $params |
374 | * Associated array for params. | |
102fe859 EM |
375 | * |
376 | * @return string | |
6a488035 | 377 | */ |
b11c92be | 378 | public static function whereClause($params) { |
be2fb01f | 379 | $clauses = []; |
6a488035 | 380 | // Exclude data-entry batches |
be2fb01f | 381 | $batchStatus = CRM_Core_PseudoConstant::get('CRM_Batch_DAO_Batch', 'status_id', ['labelColumn' => 'name']); |
6a488035 | 382 | if (empty($params['status_id'])) { |
be2fb01f | 383 | $clauses['status_id'] = ['NOT IN' => ["Data Entry"]]; |
6a488035 TO |
384 | } |
385 | ||
be2fb01f | 386 | $return = [ |
857236d0 PN |
387 | "id", |
388 | "name", | |
389 | "title", | |
390 | "description", | |
391 | "created_date", | |
392 | "status_id", | |
393 | "modified_id", | |
394 | "modified_date", | |
395 | "type_id", | |
396 | "mode_id", | |
397 | "total", | |
398 | "item_count", | |
399 | "exported_date", | |
400 | "payment_instrument_id", | |
401 | "created_id.sort_name", | |
402 | "created_id", | |
be2fb01f | 403 | ]; |
d2738983 PN |
404 | if (!CRM_Core_Permission::check("view all manual batches")) { |
405 | if (CRM_Core_Permission::check("view own manual batches")) { | |
406 | $loggedInContactId = CRM_Core_Session::singleton()->get('userID'); | |
407 | $params['created_id'] = $loggedInContactId; | |
408 | } | |
409 | else { | |
410 | $params['created_id'] = 0; | |
411 | } | |
412 | } | |
857236d0 PN |
413 | foreach ($return as $field) { |
414 | if (!isset($params[$field])) { | |
415 | continue; | |
416 | } | |
417 | $value = CRM_Utils_Type::escape($params[$field], 'String', FALSE); | |
be2fb01f CW |
418 | if (in_array($field, ['name', 'title', 'description', 'created_id.sort_name'])) { |
419 | $clauses[$field] = ['LIKE' => "%{$value}%"]; | |
857236d0 PN |
420 | } |
421 | elseif ($field == 'status_id' && $value == array_search('Open', $batchStatus)) { | |
be2fb01f | 422 | $clauses['status_id'] = ['IN' => ["Open", 'Reopened']]; |
857236d0 PN |
423 | } |
424 | else { | |
425 | $clauses[$field] = $value; | |
6a488035 TO |
426 | } |
427 | } | |
857236d0 | 428 | return $clauses; |
6a488035 TO |
429 | } |
430 | ||
431 | /** | |
eceb18cc | 432 | * Define action links. |
6a488035 | 433 | * |
102fe859 EM |
434 | * @param null $context |
435 | * | |
a6c01b45 CW |
436 | * @return array |
437 | * array of action links | |
6a488035 | 438 | */ |
00be9182 | 439 | public function links($context = NULL) { |
6a488035 | 440 | if ($context == 'financialBatch') { |
be2fb01f CW |
441 | $links = [ |
442 | 'transaction' => [ | |
353ffa53 TO |
443 | 'name' => ts('Transactions'), |
444 | 'url' => 'civicrm/batchtransaction', | |
445 | 'qs' => 'reset=1&bid=%%id%%', | |
6a488035 | 446 | 'title' => ts('View/Add Transactions to Batch'), |
be2fb01f CW |
447 | ], |
448 | 'edit' => [ | |
353ffa53 TO |
449 | 'name' => ts('Edit'), |
450 | 'url' => 'civicrm/financial/batch', | |
451 | 'qs' => 'reset=1&action=update&id=%%id%%&context=1', | |
6a488035 | 452 | 'title' => ts('Edit Batch'), |
be2fb01f CW |
453 | ], |
454 | 'close' => [ | |
353ffa53 | 455 | 'name' => ts('Close'), |
6a488035 | 456 | 'title' => ts('Close Batch'), |
353ffa53 | 457 | 'url' => '#', |
6a488035 | 458 | 'extra' => 'rel="close"', |
be2fb01f CW |
459 | ], |
460 | 'export' => [ | |
353ffa53 | 461 | 'name' => ts('Export'), |
6a488035 | 462 | 'title' => ts('Export Batch'), |
353ffa53 | 463 | 'url' => '#', |
6a488035 | 464 | 'extra' => 'rel="export"', |
be2fb01f CW |
465 | ], |
466 | 'reopen' => [ | |
353ffa53 | 467 | 'name' => ts('Re-open'), |
6a488035 | 468 | 'title' => ts('Re-open Batch'), |
353ffa53 | 469 | 'url' => '#', |
6a488035 | 470 | 'extra' => 'rel="reopen"', |
be2fb01f CW |
471 | ], |
472 | 'delete' => [ | |
353ffa53 | 473 | 'name' => ts('Delete'), |
6a488035 | 474 | 'title' => ts('Delete Batch'), |
353ffa53 | 475 | 'url' => '#', |
6a488035 | 476 | 'extra' => 'rel="delete"', |
be2fb01f CW |
477 | ], |
478 | 'download' => [ | |
353ffa53 TO |
479 | 'name' => ts('Download'), |
480 | 'url' => 'civicrm/file', | |
ff9aeadb | 481 | 'qs' => 'reset=1&id=%%fid%%&eid=%%eid%%&fcs=%%fcs%%', |
6a488035 | 482 | 'title' => ts('Download Batch'), |
be2fb01f CW |
483 | ], |
484 | ]; | |
6a488035 TO |
485 | } |
486 | else { | |
be2fb01f CW |
487 | $links = [ |
488 | CRM_Core_Action::COPY => [ | |
6a488035 TO |
489 | 'name' => ts('Enter records'), |
490 | 'url' => 'civicrm/batch/entry', | |
491 | 'qs' => 'id=%%id%%&reset=1', | |
492 | 'title' => ts('Batch Data Entry'), | |
be2fb01f CW |
493 | ], |
494 | CRM_Core_Action::UPDATE => [ | |
6a488035 TO |
495 | 'name' => ts('Edit'), |
496 | 'url' => 'civicrm/batch', | |
497 | 'qs' => 'action=update&id=%%id%%&reset=1', | |
498 | 'title' => ts('Edit Batch'), | |
be2fb01f CW |
499 | ], |
500 | CRM_Core_Action::DELETE => [ | |
6a488035 TO |
501 | 'name' => ts('Delete'), |
502 | 'url' => 'civicrm/batch', | |
503 | 'qs' => 'action=delete&id=%%id%%', | |
504 | 'title' => ts('Delete Batch'), | |
be2fb01f CW |
505 | ], |
506 | ]; | |
6a488035 TO |
507 | } |
508 | return $links; | |
509 | } | |
510 | ||
511 | /** | |
eceb18cc | 512 | * Get batch list. |
6a488035 | 513 | * |
a6c01b45 | 514 | * @return array |
72b3a70c | 515 | * all batches excluding batches with data entry in progress |
6a488035 | 516 | */ |
00be9182 | 517 | public static function getBatches() { |
a28ce73f | 518 | $dataEntryStatusId = CRM_Core_PseudoConstant::getKey('CRM_Batch_BAO_Batch', 'status_id', 'Data Entry'); |
acb4ca2f | 519 | $query = "SELECT id, title |
6a488035 | 520 | FROM civicrm_batch |
acb4ca2f DG |
521 | WHERE item_count >= 1 |
522 | AND status_id != {$dataEntryStatusId} | |
433465bc | 523 | ORDER BY title"; |
6a488035 | 524 | |
be2fb01f | 525 | $batches = []; |
6a488035 | 526 | $dao = CRM_Core_DAO::executeQuery($query); |
481a74f4 | 527 | while ($dao->fetch()) { |
6a488035 TO |
528 | $batches[$dao->id] = $dao->title; |
529 | } | |
530 | return $batches; | |
531 | } | |
532 | ||
6a488035 | 533 | /** |
eceb18cc | 534 | * Calculate sum of all entries in a batch. |
6a488035 TO |
535 | * Used to validate and update item_count and total when closing an accounting batch |
536 | * | |
537 | * @param array $batchIds | |
538 | * @return array | |
539 | */ | |
00be9182 | 540 | public static function batchTotals($batchIds) { |
be2fb01f | 541 | $totals = array_fill_keys($batchIds, ['item_count' => 0, 'total' => 0]); |
6a488035 TO |
542 | if ($batchIds) { |
543 | $sql = "SELECT eb.batch_id, COUNT(tx.id) AS item_count, SUM(tx.total_amount) AS total | |
544 | FROM civicrm_entity_batch eb | |
545 | INNER JOIN civicrm_financial_trxn tx ON tx.id = eb.entity_id AND eb.entity_table = 'civicrm_financial_trxn' | |
546 | WHERE eb.batch_id IN (" . implode(',', $batchIds) . ") | |
547 | GROUP BY eb.batch_id"; | |
548 | $dao = CRM_Core_DAO::executeQuery($sql); | |
549 | while ($dao->fetch()) { | |
550 | $totals[$dao->batch_id] = (array) $dao; | |
551 | } | |
6a488035 TO |
552 | } |
553 | return $totals; | |
554 | } | |
555 | ||
556 | /** | |
eceb18cc | 557 | * Format markup for comparing two totals. |
6a488035 | 558 | * |
72b3a70c CW |
559 | * @param $actual |
560 | * calculated total | |
561 | * @param $expected | |
562 | * user-entered total | |
6a488035 TO |
563 | * @return array |
564 | */ | |
00be9182 | 565 | public static function displayTotals($actual, $expected) { |
6a488035 TO |
566 | $class = 'actual-value'; |
567 | if ($expected && $expected != $actual) { | |
568 | $class .= ' crm-error'; | |
569 | } | |
570 | $actualTitle = ts('Current Total'); | |
571 | $output = "<span class='$class' title='$actualTitle'>$actual</span>"; | |
572 | if ($expected) { | |
573 | $expectedTitle = ts('Expected Total'); | |
574 | $output .= " / <span class='expected-value' title='$expectedTitle'>$expected</span>"; | |
575 | } | |
576 | return $output; | |
577 | } | |
578 | ||
579 | /** | |
580 | * Function for exporting financial accounts, currently we support CSV and IIF format | |
581 | * @see http://wiki.civicrm.org/confluence/display/CRM/CiviAccounts+Specifications+-++Batches#CiviAccountsSpecifications-Batches-%C2%A0Overviewofimplementation | |
582 | * | |
82d480a5 TO |
583 | * @param array $batchIds |
584 | * Associated array of batch ids. | |
585 | * @param string $exportFormat | |
586 | * Export format. | |
f3d529fc PN |
587 | * @param bool $downloadFile |
588 | * Download export file?. | |
6a488035 | 589 | */ |
f3d529fc | 590 | public static function exportFinancialBatch($batchIds, $exportFormat, $downloadFile) { |
6a488035 TO |
591 | if (empty($batchIds)) { |
592 | CRM_Core_Error::fatal(ts('No batches were selected.')); | |
593 | return; | |
594 | } | |
595 | if (empty($exportFormat)) { | |
596 | CRM_Core_Error::fatal(ts('No export format selected.')); | |
597 | return; | |
598 | } | |
599 | self::$_exportFormat = $exportFormat; | |
600 | ||
601 | // Instantiate appropriate exporter based on user-selected format. | |
602 | $exporterClass = "CRM_Financial_BAO_ExportFormat_" . self::$_exportFormat; | |
481a74f4 | 603 | if (class_exists($exporterClass)) { |
6a488035 TO |
604 | $exporter = new $exporterClass(); |
605 | } | |
606 | else { | |
607 | CRM_Core_Error::fatal("Could not locate exporter: $exporterClass"); | |
608 | } | |
be2fb01f | 609 | $export = []; |
f3d529fc | 610 | $exporter->_isDownloadFile = $downloadFile; |
9b05de29 | 611 | foreach ($batchIds as $batchId) { |
f091b037 | 612 | // export only batches whose status is set to Exported. |
be2fb01f | 613 | $result = civicrm_api3('Batch', 'getcount', [ |
f091b037 PN |
614 | 'id' => $batchId, |
615 | 'status_id' => "Exported", | |
be2fb01f | 616 | ]); |
f091b037 PN |
617 | if (!$result) { |
618 | continue; | |
619 | } | |
9b05de29 | 620 | $export[$batchId] = $exporter->generateExportQuery($batchId); |
6a488035 | 621 | } |
f091b037 PN |
622 | if ($export) { |
623 | $exporter->makeExport($export); | |
624 | } | |
6a488035 TO |
625 | } |
626 | ||
e0ef6999 EM |
627 | /** |
628 | * @param array $batchIds | |
629 | * @param $status | |
630 | */ | |
be2fb01f | 631 | public static function closeReOpen($batchIds = [], $status) { |
f0ebbc90 | 632 | $batchStatus = CRM_Core_PseudoConstant::get('CRM_Batch_DAO_Batch', 'status_id'); |
481a74f4 TO |
633 | $params['status_id'] = CRM_Utils_Array::key($status, $batchStatus); |
634 | $session = CRM_Core_Session::singleton(); | |
6a488035 | 635 | $params['modified_date'] = date('YmdHis'); |
481a74f4 | 636 | $params['modified_id'] = $session->get('userID'); |
6a488035 TO |
637 | foreach ($batchIds as $key => $value) { |
638 | $params['id'] = $ids['batchID'] = $value; | |
639 | self::create($params, $ids); | |
640 | } | |
691df66d | 641 | $url = CRM_Utils_System::url('civicrm/financial/financialbatches', "reset=1&batchStatus={$params['status_id']}"); |
6a488035 TO |
642 | CRM_Utils_System::redirect($url); |
643 | } | |
644 | ||
645 | /** | |
eceb18cc | 646 | * Retrieve financial items assigned for a batch. |
6a488035 TO |
647 | * |
648 | * @param int $entityID | |
649 | * @param array $returnValues | |
72b3a70c | 650 | * @param bool $notPresent |
100fef9d | 651 | * @param array $params |
102fe859 EM |
652 | * @param bool $getCount |
653 | * | |
72b3a70c | 654 | * @return CRM_Core_DAO |
6a488035 | 655 | */ |
00be9182 | 656 | public static function getBatchFinancialItems($entityID, $returnValues, $notPresent = NULL, $params = NULL, $getCount = FALSE) { |
6a488035 TO |
657 | if (!$getCount) { |
658 | if (!empty($params['rowCount']) && | |
659 | $params['rowCount'] > 0 | |
660 | ) { | |
661 | $limit = " LIMIT {$params['offset']}, {$params['rowCount']} "; | |
662 | } | |
663 | } | |
664 | // action is taken depending upon the mode | |
665 | $select = 'civicrm_financial_trxn.id '; | |
481a74f4 | 666 | if (!empty($returnValues)) { |
92fcb95f | 667 | $select .= " , " . implode(' , ', $returnValues); |
6a488035 TO |
668 | } |
669 | ||
670 | $orderBy = " ORDER BY civicrm_financial_trxn.id"; | |
21d32567 DL |
671 | if (!empty($params['sort'])) { |
672 | $orderBy = ' ORDER BY ' . CRM_Utils_Type::escape($params['sort'], 'String'); | |
6a488035 TO |
673 | } |
674 | ||
675 | $from = "civicrm_financial_trxn | |
c4b067f6 PN |
676 | INNER JOIN civicrm_entity_financial_trxn ON civicrm_entity_financial_trxn.financial_trxn_id = civicrm_financial_trxn.id |
677 | INNER JOIN civicrm_contribution ON (civicrm_contribution.id = civicrm_entity_financial_trxn.entity_id | |
678 | AND civicrm_entity_financial_trxn.entity_table='civicrm_contribution') | |
cc55c603 DG |
679 | LEFT JOIN civicrm_entity_batch ON civicrm_entity_batch.entity_table = 'civicrm_financial_trxn' |
680 | AND civicrm_entity_batch.entity_id = civicrm_financial_trxn.id | |
6a488035 TO |
681 | LEFT JOIN civicrm_financial_type ON civicrm_financial_type.id = civicrm_contribution.financial_type_id |
682 | LEFT JOIN civicrm_contact contact_a ON contact_a.id = civicrm_contribution.contact_id | |
683 | LEFT JOIN civicrm_contribution_soft ON civicrm_contribution_soft.contribution_id = civicrm_contribution.id | |
684 | "; | |
685 | ||
be2fb01f | 686 | $searchFields = [ |
6c552737 TO |
687 | 'sort_name', |
688 | 'financial_type_id', | |
689 | 'contribution_page_id', | |
5712c3b9 | 690 | 'contribution_payment_instrument_id', |
30d46f2f | 691 | 'contribution_trxn_id', |
6c552737 TO |
692 | 'contribution_source', |
693 | 'contribution_currency_type', | |
694 | 'contribution_pay_later', | |
695 | 'contribution_recurring', | |
696 | 'contribution_test', | |
697 | 'contribution_thankyou_date_is_not_null', | |
698 | 'contribution_receipt_date_is_not_null', | |
699 | 'contribution_pcp_made_through_id', | |
700 | 'contribution_pcp_display_in_roll', | |
6c552737 TO |
701 | 'contribution_amount_low', |
702 | 'contribution_amount_high', | |
703 | 'contribution_in_honor_of', | |
704 | 'contact_tags', | |
705 | 'group', | |
5d7e6440 SL |
706 | 'receive_date_relative', |
707 | 'receive_date_high', | |
708 | 'receive_date_low', | |
6c552737 TO |
709 | 'contribution_check_number', |
710 | 'contribution_status_id', | |
eb71b3f2 | 711 | 'financial_trxn_card_type_id', |
712 | 'financial_trxn_pan_truncation', | |
be2fb01f CW |
713 | ]; |
714 | $values = []; | |
6a488035 TO |
715 | foreach ($searchFields as $field) { |
716 | if (isset($params[$field])) { | |
717 | $values[$field] = $params[$field]; | |
718 | if ($field == 'sort_name') { | |
719 | $from .= " LEFT JOIN civicrm_contact contact_b ON contact_b.id = civicrm_contribution.contact_id | |
720 | LEFT JOIN civicrm_email ON contact_b.id = civicrm_email.contact_id"; | |
721 | } | |
722 | if ($field == 'contribution_in_honor_of') { | |
723 | $from .= " LEFT JOIN civicrm_contact contact_b ON contact_b.id = civicrm_contribution.contact_id"; | |
724 | } | |
725 | if ($field == 'contact_tags') { | |
726 | $from .= " LEFT JOIN civicrm_entity_tag `civicrm_entity_tag-{$params[$field]}` ON `civicrm_entity_tag-{$params[$field]}`.entity_id = contact_a.id"; | |
727 | } | |
728 | if ($field == 'group') { | |
729 | $from .= " LEFT JOIN civicrm_group_contact `civicrm_group_contact-{$params[$field]}` ON contact_a.id = `civicrm_group_contact-{$params[$field]}`.contact_id "; | |
730 | } | |
5d7e6440 | 731 | if ($field == 'receive_date_relative') { |
6a488035 TO |
732 | $relativeDate = explode('.', $params[$field]); |
733 | $date = CRM_Utils_Date::relativeToAbsolute($relativeDate[0], $relativeDate[1]); | |
5d7e6440 SL |
734 | $values['receive_date_low'] = $date['from']; |
735 | $values['receive_date_high'] = $date['to']; | |
6a488035 | 736 | } |
6a488035 TO |
737 | } |
738 | } | |
639e74e5 | 739 | |
977196f2 PN |
740 | $searchParams = CRM_Contact_BAO_Query::convertFormValues( |
741 | $values, | |
742 | 0, | |
743 | FALSE, | |
744 | NULL, | |
745 | [ | |
746 | 'financial_type_id', | |
747 | 'contribution_soft_credit_type_id', | |
748 | 'contribution_status_id', | |
749 | 'contribution_page_id', | |
750 | 'financial_trxn_card_type_id', | |
751 | 'contribution_payment_instrument_id', | |
752 | ] | |
753 | ); | |
639e74e5 PN |
754 | // @todo the use of defaultReturnProperties means the search will be inefficient |
755 | // as slow-unneeded properties are included. | |
756 | $query = new CRM_Contact_BAO_Query($searchParams, | |
757 | CRM_Contribute_BAO_Query::defaultReturnProperties(CRM_Contact_BAO_Query::MODE_CONTRIBUTE, | |
758 | FALSE | |
759 | ), NULL, FALSE, FALSE, CRM_Contact_BAO_Query::MODE_CONTRIBUTE | |
760 | ); | |
761 | ||
6a488035 | 762 | if (!empty($query->_where[0])) { |
0b0941e2 | 763 | $where = implode(' AND ', $query->_where[0]) . |
c4b067f6 | 764 | " AND civicrm_entity_batch.batch_id IS NULL "; |
30d46f2f | 765 | $where = str_replace('civicrm_contribution.payment_instrument_id', 'civicrm_financial_trxn.payment_instrument_id', $where); |
6a488035 TO |
766 | } |
767 | else { | |
6a488035 | 768 | if (!$notPresent) { |
c4b067f6 | 769 | $where = " civicrm_entity_batch.batch_id = {$entityID} "; |
6a488035 TO |
770 | } |
771 | else { | |
c4b067f6 | 772 | $where = " civicrm_entity_batch.batch_id IS NULL "; |
6a488035 TO |
773 | } |
774 | } | |
775 | ||
0b0941e2 DL |
776 | $sql = " |
777 | SELECT {$select} | |
778 | FROM {$from} | |
779 | WHERE {$where} | |
780 | {$orderBy} | |
6a488035 TO |
781 | "; |
782 | ||
783 | if (isset($limit)) { | |
784 | $sql .= "{$limit}"; | |
785 | } | |
786 | ||
787 | $result = CRM_Core_DAO::executeQuery($sql); | |
788 | return $result; | |
789 | } | |
790 | ||
791 | /** | |
eceb18cc | 792 | * Get batch names. |
6a488035 TO |
793 | * @param string $batchIds |
794 | * | |
a6c01b45 CW |
795 | * @return array |
796 | * array of batches | |
6a488035 | 797 | */ |
00be9182 | 798 | public static function getBatchNames($batchIds) { |
6a488035 TO |
799 | $query = 'SELECT id, title |
800 | FROM civicrm_batch | |
86bfa4f6 | 801 | WHERE id IN (' . $batchIds . ')'; |
6a488035 | 802 | |
be2fb01f | 803 | $batches = []; |
6a488035 | 804 | $dao = CRM_Core_DAO::executeQuery($query); |
481a74f4 | 805 | while ($dao->fetch()) { |
6a488035 TO |
806 | $batches[$dao->id] = $dao->title; |
807 | } | |
808 | return $batches; | |
809 | } | |
810 | ||
811 | /** | |
eceb18cc | 812 | * Function get batch statuses. |
6a488035 TO |
813 | * |
814 | * @param string $batchIds | |
815 | * | |
a6c01b45 CW |
816 | * @return array |
817 | * array of batches | |
6a488035 | 818 | */ |
00be9182 | 819 | public static function getBatchStatuses($batchIds) { |
6a488035 TO |
820 | $query = 'SELECT id, status_id |
821 | FROM civicrm_batch | |
92fcb95f | 822 | WHERE id IN (' . $batchIds . ')'; |
6a488035 | 823 | |
be2fb01f | 824 | $batches = []; |
6a488035 | 825 | $dao = CRM_Core_DAO::executeQuery($query); |
481a74f4 | 826 | while ($dao->fetch()) { |
6a488035 TO |
827 | $batches[$dao->id] = $dao->status_id; |
828 | } | |
829 | return $batches; | |
830 | } | |
96025800 | 831 | |
ca0e2dda PN |
832 | /** |
833 | * Function to check permission for batch. | |
834 | * | |
835 | * @param string $action | |
836 | * @param int $batchCreatedId | |
837 | * batch created by contact id | |
838 | * | |
839 | * @return bool | |
840 | */ | |
841 | public static function checkBatchPermission($action, $batchCreatedId = NULL) { | |
ca0e2dda PN |
842 | if (CRM_Core_Permission::check("{$action} all manual batches")) { |
843 | return TRUE; | |
844 | } | |
845 | if (CRM_Core_Permission::check("{$action} own manual batches")) { | |
846 | $loggedInContactId = CRM_Core_Session::singleton()->get('userID'); | |
847 | if ($batchCreatedId == $loggedInContactId) { | |
848 | return TRUE; | |
849 | } | |
850 | elseif (CRM_Utils_System::isNull($batchCreatedId)) { | |
851 | return TRUE; | |
852 | } | |
853 | } | |
854 | return FALSE; | |
855 | } | |
856 | ||
6a488035 | 857 | } |