Merge pull request #10393 from JMAConsulting/exportBatch
[civicrm-core.git] / tests / phpunit / api / v3 / CaseTest.php
1 <?php
2 /**
3 * @file
4 * File for the TestCase class
5 *
6 * (PHP 5)
7 *
8 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
9 * @copyright Copyright CiviCRM LLC (C) 2009
10 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
11 * GNU Affero General Public License version 3
12 * @version $Id: ActivityTest.php 31254 2010-12-15 10:09:29Z eileen $
13 * @package CiviCRM
14 *
15 * This file is part of CiviCRM
16 *
17 * CiviCRM is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Affero General Public License
19 * as published by the Free Software Foundation; either version 3 of
20 * the License, or (at your option) any later version.
21 *
22 * CiviCRM is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
26 *
27 * You should have received a copy of the GNU Affero General Public
28 * License along with this program. If not, see
29 * <http://www.gnu.org/licenses/>.
30 */
31
32 /**
33 * Include class definitions
34 */
35
36 /**
37 * Test APIv3 civicrm_case_* functions
38 *
39 * @package CiviCRM_APIv3
40 * @group headless
41 */
42 class api_v3_CaseTest extends CiviCaseTestCase {
43 protected $_params;
44 protected $_entity;
45 protected $_apiversion = 3;
46 protected $followup_activity_type_value;
47 /**
48 * Activity ID of created case.
49 *
50 * @var int
51 */
52 protected $_caseActivityId;
53
54 /**
55 * @var \Civi\Core\SettingsStack
56 */
57 protected $settingsStack;
58
59 /**
60 * Test setup for every test.
61 *
62 * Connect to the database, truncate the tables that will be used
63 * and redirect stdin to a temporary file.
64 */
65 public function setUp() {
66 $this->_entity = 'case';
67
68 parent::setUp();
69
70 $activityTypes = $this->callAPISuccess('option_value', 'get', array(
71 'option_group_id' => 2,
72 'name' => 'Follow Up',
73 'label' => 'Follow Up',
74 'sequential' => 1,
75 ));
76 $this->followup_activity_type_value = $activityTypes['values'][0]['value'];
77
78 $this->_params = array(
79 'case_type_id' => $this->caseTypeId,
80 'subject' => 'Test case',
81 'contact_id' => 17,
82 );
83
84 $this->settingsStack = new \Civi\Core\SettingsStack();
85 }
86
87 public function tearDown() {
88 $this->settingsStack->popAll();
89 parent::tearDown();
90 }
91
92 /**
93 * Check with empty array.
94 */
95 public function testCaseCreateEmpty() {
96 $this->callAPIFailure('case', 'create', array());
97 }
98
99 /**
100 * Check if required fields are not passed.
101 */
102 public function testCaseCreateWithoutRequired() {
103 $params = array(
104 'subject' => 'this case should fail',
105 'case_type_id' => 1,
106 );
107
108 $this->callAPIFailure('case', 'create', $params);
109 }
110
111 /**
112 * Test Getlist with id and case_id
113 */
114 public function testCaseGetListById() {
115 $params = $this->_params;
116 $params['contact_id'] = $this->individualCreate();
117
118 //Create 3 sample Cases.
119 $case1 = $this->callAPISuccess('case', 'create', $params);
120 $params['subject'] = 'Test Case 2';
121 $case2 = $this->callAPISuccess('case', 'create', $params);
122 $params['subject'] = 'Test Case 3';
123 $case3 = $this->callAPISuccess('case', 'create', $params);
124
125 $getParams = array(
126 'id' => array($case1['id']),
127 'extra' => array('contact_id'),
128 'params' => array(
129 'version' => 3,
130 'case_id' => array('!=' => $case2['id']),
131 'case_id.is_deleted' => 0,
132 'case_id.status_id' => array('!=' => "Closed"),
133 'case_id.end_date' => array('IS NULL' => 1),
134 ),
135 );
136 $result = $this->callAPISuccess('case', 'getlist', $getParams);
137
138 //Only 1 case should be returned.
139 $this->assertEquals(count($result['values']), 1);
140 $this->assertEquals($result['values'][0]['id'], $case1['id']);
141 }
142
143 /**
144 * Test create function with valid parameters.
145 */
146 public function testCaseCreate() {
147 $params = $this->_params;
148 // Test using label instead of value.
149 unset($params['case_type_id']);
150 $params['case_type'] = $this->caseType;
151 $result = $this->callAPIAndDocument('case', 'create', $params, __FUNCTION__, __FILE__);
152 $id = $result['id'];
153
154 // Check result
155 $result = $this->callAPISuccess('case', 'get', array('id' => $id));
156 $this->assertEquals($result['values'][$id]['id'], $id);
157 $this->assertEquals($result['values'][$id]['case_type_id'], $this->caseTypeId);
158 $this->assertEquals($result['values'][$id]['subject'], $params['subject']);
159 }
160
161 /**
162 * Test create function with resolved status.
163 */
164 public function testCaseCreateWithResolvedStatus() {
165 $params = $this->_params;
166 // Test using label instead of value.
167 unset($params['case_type_id']);
168 $params['case_type'] = $this->caseType;
169 $params['status_id'] = 'Closed';
170 $result = $this->callAPISuccess('case', 'create', $params);
171 $id = $result['id'];
172
173 // Check result
174 $result = $this->callAPISuccess('case', 'get', array('id' => $id));
175 $this->assertEquals($result['values'][$id]['id'], $id);
176 $this->assertEquals($result['values'][$id]['case_type_id'], $this->caseTypeId);
177 $this->assertEquals($result['values'][$id]['subject'], $params['subject']);
178 $this->assertEquals($result['values'][$id]['end_date'], date('Y-m-d'));
179
180 //Check all relationship end dates are set to case end date.
181 $relationships = $this->callAPISuccess('Relationship', 'get', array(
182 'sequential' => 1,
183 'case_id' => $id,
184 ));
185 foreach ($relationships['values'] as $key => $values) {
186 $this->assertEquals($values['end_date'], date('Y-m-d'));
187 }
188 }
189
190 /**
191 * Test case create with valid parameters and custom data.
192 */
193 public function testCaseCreateCustom() {
194 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
195 $params = $this->_params;
196 $params['custom_' . $ids['custom_field_id']] = "custom string";
197 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__);
198 $result = $this->callAPISuccess($this->_entity, 'get', array(
199 'return.custom_' . $ids['custom_field_id'] => 1,
200 'id' => $result['id'],
201 ));
202 $this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
203
204 $this->customFieldDelete($ids['custom_field_id']);
205 $this->customGroupDelete($ids['custom_group_id']);
206 }
207
208 /**
209 * Test update (create with id) function with valid parameters.
210 */
211 public function testCaseUpdate() {
212 $params = $this->_params;
213 // Test using name instead of value
214 unset($params['case_type_id']);
215 $params['case_type'] = $this->caseType;
216 $result = $this->callAPISuccess('case', 'create', $params);
217 $id = $result['id'];
218 $case = $this->callAPISuccess('case', 'getsingle', array('id' => $id));
219
220 // Update Case.
221 $params = array('id' => $id);
222 $params['subject'] = $case['subject'] = 'Something Else';
223 $this->callAPISuccess('case', 'create', $params);
224
225 // Verify that updated case is equal to the original with new subject.
226 $result = $this->callAPISuccessGetSingle('Case', array('case_id' => $id));
227 // Modification dates are likely to differ by 0-2 sec. Check manually.
228 $this->assertGreaterThanOrEqual($result['modified_date'], $case['modified_date']);
229 unset($result['modified_date']);
230 unset($case['modified_date']);
231 // Everything else should be identical.
232 $this->assertAPIArrayComparison($result, $case);
233 }
234
235 /**
236 * Test update (create with id) function with valid parameters.
237 */
238 public function testCaseUpdateWithExistingCaseContact() {
239 $params = $this->_params;
240 // Test using name instead of value
241 unset($params['case_type_id']);
242 $params['case_type'] = $this->caseType;
243 $result = $this->callAPISuccess('case', 'create', $params);
244 $id = $result['id'];
245 $case = $this->callAPISuccess('case', 'getsingle', array('id' => $id));
246
247 // Update Case, we specify existing case ID and existing contact ID to verify that CaseContact.create is not called
248 $params = $this->_params;
249 $params['id'] = $id;
250 $this->callAPISuccess('case', 'create', $params);
251
252 // Verify that updated case is equal to the original with new subject.
253 $result = $this->callAPISuccessGetSingle('Case', array('case_id' => $id));
254 // Modification dates are likely to differ by 0-2 sec. Check manually.
255 $this->assertGreaterThanOrEqual($result['modified_date'], $case['modified_date']);
256 unset($result['modified_date']);
257 unset($case['modified_date']);
258 // Everything else should be identical.
259 $this->assertAPIArrayComparison($result, $case);
260 }
261
262 /**
263 * Test case update with custom data
264 */
265 public function testCaseUpdateCustom() {
266 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
267 $params = $this->_params;
268
269 // Create a case with custom data
270 $params['custom_' . $ids['custom_field_id']] = 'custom string';
271 $result = $this->callAPISuccess($this->_entity, 'create', $params);
272
273 $caseId = $result['id'];
274 $result = $this->callAPISuccess($this->_entity, 'get', array(
275 'return.custom_' . $ids['custom_field_id'] => 1,
276 'version' => 3,
277 'id' => $result['id'],
278 ));
279 $this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
280 $fields = $this->callAPISuccess($this->_entity, 'getfields', array('version' => $this->_apiversion));
281 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
282
283 // Update the activity with custom data.
284 $params = array(
285 'id' => $caseId,
286 'custom_' . $ids['custom_field_id'] => 'Updated my test data',
287 'version' => $this->_apiversion,
288 );
289 $result = $this->callAPISuccess($this->_entity, 'create', $params);
290
291 $result = $this->callAPISuccess($this->_entity, 'get', array(
292 'return.custom_' . $ids['custom_field_id'] => 1,
293 'version' => 3,
294 'id' => $result['id'],
295 ));
296 $this->assertEquals("Updated my test data", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
297 }
298
299 /**
300 * Test delete function with valid parameters.
301 */
302 public function testCaseDelete() {
303 // Create Case
304 $result = $this->callAPISuccess('case', 'create', $this->_params);
305
306 // Move Case to Trash
307 $id = $result['id'];
308 $this->callAPISuccess('case', 'delete', array('id' => $id, 'move_to_trash' => 1));
309
310 // Check result - also check that 'case_id' works as well as 'id'
311 $result = $this->callAPISuccess('case', 'get', array('case_id' => $id));
312 $this->assertEquals(1, $result['values'][$id]['is_deleted']);
313
314 // Restore Case from Trash
315 $this->callAPISuccess('case', 'restore', array('id' => $id));
316
317 // Check result
318 $result = $this->callAPISuccess('case', 'get', array('case_id' => $id));
319 $this->assertEquals(0, $result['values'][$id]['is_deleted']);
320
321 // Delete Case Permanently
322 $this->callAPISuccess('case', 'delete', array('case_id' => $id));
323
324 // Check result - case should no longer exist
325 $result = $this->callAPISuccess('case', 'get', array('id' => $id));
326 $this->assertEquals(0, $result['count']);
327 }
328
329 /**
330 * Test get function based on activity.
331 */
332 public function testCaseGetByActivity() {
333 // Create Case
334 $result = $this->callAPISuccess('case', 'create', $this->_params);
335 $id = $result['id'];
336
337 // Check result - we should get a list of activity ids
338 $result = $this->callAPISuccess('case', 'get', array('id' => $id, 'return' => 'activities'));
339 $case = $result['values'][$id];
340 $activity = $case['activities'][0];
341
342 // Fetch case based on an activity id
343 $result = $this->callAPISuccess('case', 'get', array(
344 'activity_id' => $activity,
345 'return' => 'activities',
346 ));
347 $this->assertEquals(FALSE, empty($result['values'][$id]));
348 $this->assertEquals($result['values'][$id], $case);
349 }
350
351 /**
352 * Test get function based on contact id.
353 */
354 public function testCaseGetByContact() {
355 // Create Case
356 $result = $this->callAPISuccess('case', 'create', $this->_params);
357 $id = $result['id'];
358
359 // Store result for later
360 $case = $this->callAPISuccessGetSingle('case', array('id' => $id, 'return' => array('activities', 'contacts')));
361
362 // Fetch case based on client contact id
363 $result = $this->callAPISuccess('case', 'get', array(
364 'client_id' => $this->_params['contact_id'],
365 'return' => array('activities', 'contacts'),
366 ));
367 $this->assertAPIArrayComparison($result['values'][$id], $case);
368 }
369
370 /**
371 * Test get function based on subject.
372 */
373 public function testCaseGetBySubject() {
374 // Create Case
375 $result = $this->callAPISuccess('case', 'create', $this->_params);
376 $id = $result['id'];
377
378 // Store result for later
379 $case = $this->callAPISuccessGetSingle('Case', array('id' => $id, 'return' => 'subject'));
380
381 // Fetch case based on client contact id
382 $result = $this->callAPISuccess('case', 'get', array(
383 'subject' => $this->_params['subject'],
384 'return' => array('subject'),
385 ));
386 $this->assertAPIArrayComparison($result['values'][$id], $case);
387 }
388
389 /**
390 * Test get function based on wrong subject.
391 */
392 public function testCaseGetByWrongSubject() {
393 $result = $this->callAPISuccess('case', 'create', $this->_params);
394
395 // Append 'wrong' to subject so that it is no longer the same.
396 $result = $this->callAPISuccess('case', 'get', array(
397 'subject' => $this->_params['subject'] . 'wrong',
398 'return' => array('activities', 'contacts'),
399 ));
400 $this->assertEquals(0, $result['count']);
401 }
402
403 /**
404 * Test get function with no criteria.
405 */
406 public function testCaseGetNoCriteria() {
407 $result = $this->callAPISuccess('case', 'create', $this->_params);
408 $id = $result['id'];
409
410 // Store result for later
411 $case = $this->callAPISuccessGetSingle('Case', array('id' => $id, 'return' => 'contact_id'));
412
413 $result = $this->callAPISuccess('case', 'get', array('limit' => 0, 'return' => array('contact_id')));
414 $this->assertAPIArrayComparison($result['values'][$id], $case);
415 }
416
417 /**
418 * Test activity api create for case activities.
419 */
420 public function testCaseActivityCreate() {
421 $params = $this->_params;
422 $case = $this->callAPISuccess('case', 'create', $params);
423 $params = array(
424 'case_id' => $case['id'],
425 // follow up
426 'activity_type_id' => $this->followup_activity_type_value,
427 'subject' => 'Test followup 123',
428 'source_contact_id' => $this->_loggedInUser,
429 'target_contact_id' => $this->_params['contact_id'],
430 );
431 $result = $this->callAPISuccess('activity', 'create', $params);
432 $this->assertEquals($result['values'][$result['id']]['activity_type_id'], $params['activity_type_id']);
433
434 // might need this for other tests that piggyback on this one
435 $this->_caseActivityId = $result['values'][$result['id']]['id'];
436
437 // Check other DB tables populated properly - is there a better way to do this? assertDBState() requires that we know the id already.
438 $dao = new CRM_Case_DAO_CaseActivity();
439 $dao->case_id = $case['id'];
440 $dao->activity_id = $this->_caseActivityId;
441 $this->assertEquals($dao->find(), 1, 'case_activity table not populated correctly in line ' . __LINE__);
442 $dao->free();
443
444 $dao = new CRM_Activity_DAO_ActivityContact();
445 $dao->activity_id = $this->_caseActivityId;
446 $dao->contact_id = $this->_params['contact_id'];
447 $dao->record_type_id = 3;
448 $this->assertEquals($dao->find(), 1, 'activity_contact table not populated correctly in line ' . __LINE__);
449 $dao->free();
450
451 // Check that fetching an activity by case id works, as well as returning case_id
452 $result = $this->callAPISuccessGetSingle('Activity', array(
453 'case_id' => $case['id'],
454 'activity_type_id' => $this->followup_activity_type_value,
455 'subject' => 'Test followup 123',
456 'return' => array('case_id'),
457 ));
458 $this->assertContains($case['id'], $result['case_id']);
459 }
460
461 /**
462 * Test activity api update for case activities.
463 */
464 public function testCaseActivityUpdate_Tracked() {
465 $this->settingsStack->push('civicaseActivityRevisions', TRUE);
466
467 // Need to create the case and activity before we can update it
468 $this->testCaseActivityCreate();
469
470 $params = array(
471 'activity_id' => $this->_caseActivityId,
472 'case_id' => 1,
473 'activity_type_id' => 14,
474 'source_contact_id' => $this->_loggedInUser,
475 'subject' => 'New subject',
476 );
477 $result = $this->callAPISuccess('activity', 'create', $params);
478
479 $this->assertEquals($result['values'][$result['id']]['subject'], $params['subject']);
480
481 // id should be one greater, since this is a new revision
482 $this->assertEquals($result['values'][$result['id']]['id'],
483 $this->_caseActivityId + 1,
484 'in line ' . __LINE__
485 );
486 $this->assertEquals($result['values'][$result['id']]['original_id'],
487 $this->_caseActivityId,
488 'in line ' . __LINE__
489 );
490
491 // Check revision is as expected
492 $revParams = array(
493 'activity_id' => $this->_caseActivityId,
494 );
495 $revActivity = $this->callAPISuccess('activity', 'get', $revParams);
496 $this->assertEquals($revActivity['values'][$this->_caseActivityId]['is_current_revision'],
497 0);
498 $this->assertEquals($revActivity['values'][$this->_caseActivityId]['is_deleted'],
499 0
500 );
501
502 //TODO: check some more things
503 }
504
505 /**
506 * If you disable `civicaseActivityRevisions`, then editing an activity
507 * will *not* create or change IDs.
508 */
509 public function testCaseActivityUpdate_Untracked() {
510 $this->settingsStack->push('civicaseActivityRevisions', FALSE);
511
512 // Need to create the case and activity before we can update it
513 $this->testCaseActivityCreate();
514
515 $oldIDs = CRM_Utils_SQL_Select::from('civicrm_activity')
516 ->select('id, original_id, is_current_revision')
517 ->orderBy('id')
518 ->execute()->fetchAll();
519
520 $params = array(
521 'activity_id' => $this->_caseActivityId,
522 'case_id' => 1,
523 'activity_type_id' => 14,
524 'source_contact_id' => $this->_loggedInUser,
525 'subject' => 'New subject',
526 );
527 $result = $this->callAPISuccess('activity', 'create', $params);
528 $this->assertEquals($result['values'][$result['id']]['subject'], $params['subject']);
529
530 // id should not change because we've opted out.
531 $this->assertEquals($this->_caseActivityId, $result['values'][$result['id']]['id']);
532 $this->assertEmpty($result['values'][$result['id']]['original_id']);
533
534 $newIDs = CRM_Utils_SQL_Select::from('civicrm_activity')
535 ->select('id, original_id, is_current_revision')
536 ->orderBy('id')
537 ->execute()->fetchAll();
538 $this->assertEquals($oldIDs, $newIDs);
539 }
540
541 public function testCaseActivityUpdateCustom() {
542 $this->settingsStack->push('civicaseActivityRevisions', TRUE);
543
544 // Create a case first
545 $result = $this->callAPISuccess('case', 'create', $this->_params);
546
547 // Create custom field group
548 // Note the second parameter is Activity on purpose, not Case.
549 $custom_ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, 'ActivityTest.php');
550
551 // create activity
552 $params = array(
553 'case_id' => $result['id'],
554 // follow up
555 'activity_type_id' => 14,
556 'subject' => 'Test followup',
557 'source_contact_id' => $this->_loggedInUser,
558 'target_contact_id' => $this->_params['contact_id'],
559 'custom_' . $custom_ids['custom_field_id'] => "custom string",
560 );
561 $result = $this->callAPISuccess('activity', 'create', $params);
562
563 $aid = $result['values'][$result['id']]['id'];
564
565 // Update activity
566 $params = array(
567 'activity_id' => $aid,
568 'case_id' => 1,
569 'activity_type_id' => 14,
570 'source_contact_id' => $this->_loggedInUser,
571 'subject' => 'New subject',
572 );
573 $this->callAPISuccess('activity', 'create', $params);
574
575 // Retrieve revision and check custom fields got copied.
576 $revParams = array(
577 'activity_id' => $aid + 1,
578 'return.custom_' . $custom_ids['custom_field_id'] => 1,
579 );
580 $revAct = $this->callAPISuccess('activity', 'get', $revParams);
581
582 $this->assertEquals($revAct['values'][$aid + 1]['custom_' . $custom_ids['custom_field_id']], "custom string",
583 "Error message: " . CRM_Utils_Array::value('error_message', $revAct));
584
585 $this->customFieldDelete($custom_ids['custom_field_id']);
586 $this->customGroupDelete($custom_ids['custom_group_id']);
587 }
588
589 public function testCaseGetByStatus() {
590 // Create 2 cases with different status ids.
591 $case1 = $this->callAPISuccess('Case', 'create', array(
592 'contact_id' => 17,
593 'subject' => "Test case 1",
594 'case_type_id' => $this->caseTypeId,
595 'status_id' => "Open",
596 'sequential' => 1,
597 ));
598 $this->callAPISuccess('Case', 'create', array(
599 'contact_id' => 17,
600 'subject' => "Test case 2",
601 'case_type_id' => $this->caseTypeId,
602 'status_id' => "Urgent",
603 'sequential' => 1,
604 ));
605 $result = $this->callAPISuccessGetSingle('Case', array(
606 'sequential' => 1,
607 'contact_id' => 17,
608 'status_id' => "Open",
609 ));
610 $this->assertEquals($case1['id'], $result['id']);
611 }
612
613 public function testCaseGetWithRoles() {
614 $case1 = $this->callAPISuccess('Case', 'create', array(
615 'contact_id' => 17,
616 'subject' => "Test case with roles",
617 'case_type_id' => $this->caseTypeId,
618 'status_id' => "Open",
619 ));
620 $result = $this->callAPISuccessGetSingle('Case', array(
621 'id' => $case1['id'],
622 'status_id' => "Open",
623 'return' => array('contacts'),
624 ));
625 foreach ($result['contacts'] as $contact) {
626 if ($contact['role'] == 'Client') {
627 $this->assertEquals(17, $contact['contact_id']);
628 }
629 elseif ($contact['role'] == 'Homeless Services Coordinator') {
630 $this->assertEquals(1, $contact['creator']);
631 $this->assertEquals(1, $contact['manager']);
632 }
633 }
634 }
635
636 public function testCaseGetWithDefinition() {
637 $case1 = $this->callAPISuccess('Case', 'create', array(
638 'contact_id' => 17,
639 'subject' => "Test case with definition",
640 'case_type_id' => $this->caseTypeId,
641 'status_id' => "Open",
642 ));
643 $result1 = $this->callAPISuccessGetSingle('Case', array(
644 'id' => $case1['id'],
645 'status_id' => "Open",
646 'return' => array('case_type_id.definition'),
647 ));
648 $result2 = $this->callAPISuccessGetSingle('Case', array(
649 'id' => $case1['id'],
650 'status_id' => "Open",
651 'return' => array('case_type_id', 'case_type_id.definition'),
652 ));
653 $this->assertEquals($result1['case_type_id.definition'], $result2['case_type_id.definition']);
654 $def = $result1['case_type_id.definition'];
655 $this->assertEquals(array('name' => 'Open Case', 'max_instances' => 1), $def['activityTypes'][0]);
656 $this->assertNotEmpty($def['activitySets'][0]['activityTypes']);
657 $this->assertNotEmpty($def['caseRoles'][0]['manager']);
658 $this->assertNotEmpty($def['caseRoles'][0]['creator']);
659 }
660
661 public function testCaseGetTags() {
662 $case1 = $this->callAPISuccess('Case', 'create', array(
663 'contact_id' => 17,
664 'subject' => "Test case with tags",
665 'case_type_id' => $this->caseTypeId,
666 'status_id' => "Open",
667 ));
668 $tag1 = $this->tagCreate(array(
669 'name' => 'CaseTag1',
670 'used_for' => 'civicrm_case',
671 ));
672 $tag2 = $this->tagCreate(array(
673 'name' => 'CaseTag2',
674 'used_for' => 'civicrm_case',
675 ));
676 $this->callAPISuccess('EntityTag', 'create', array(
677 'entity_table' => 'civicrm_case',
678 'entity_id' => $case1['id'],
679 'tag_id' => $tag1['id'],
680 ));
681 $this->callAPIFailure('Case', 'getsingle', array(
682 'tag_id' => $tag2['id'],
683 ));
684 $result = $this->callAPISuccessGetSingle('Case', array(
685 'tag_id' => $tag1['id'],
686 'return' => 'tag_id.name',
687 ));
688 $this->assertEquals('CaseTag1', $result['tag_id'][$tag1['id']]['tag_id.name']);
689 }
690
691 /**
692 * Test that a chained api call can use the operator syntax.
693 *
694 * E.g. array('IN' => $value.contact_id)
695 *
696 * @throws \Exception
697 */
698 public function testCaseGetChainedOp() {
699 $contact1 = $this->individualCreate(array(), 1);
700 $contact2 = $this->individualCreate(array(), 2);
701 $case1 = $this->callAPISuccess('Case', 'create', array(
702 'contact_id' => $contact1,
703 'subject' => "Test case 1",
704 'case_type_id' => $this->caseTypeId,
705 ));
706 $case2 = $this->callAPISuccess('Case', 'create', array(
707 'contact_id' => $contact2,
708 'subject' => "Test case 2",
709 'case_type_id' => $this->caseTypeId,
710 ));
711 $case3 = $this->callAPISuccess('Case', 'create', array(
712 'contact_id' => array($contact1, $contact2),
713 'subject' => "Test case 3",
714 'case_type_id' => $this->caseTypeId,
715 ));
716
717 // Fetch case 1 and all cases with the same client. Chained get should return case 3.
718 $result = $this->callAPISuccessGetSingle('Case', array(
719 'id' => $case1['id'],
720 'return' => 'contact_id',
721 'api.Case.get' => array(
722 'contact_id' => array('IN' => "\$value.contact_id"),
723 'id' => array('!=' => "\$value.id"),
724 ),
725 ));
726 $this->assertEquals($case3['id'], $result['api.Case.get']['id']);
727
728 // Fetch case 3 and all cases with the same clients. Chained get should return case 1&2.
729 $result = $this->callAPISuccessGetSingle('Case', array(
730 'id' => $case3['id'],
731 'return' => array('contact_id'),
732 'api.Case.get' => array(
733 'return' => 'id',
734 'contact_id' => array('IN' => "\$value.contact_id"),
735 'id' => array('!=' => "\$value.id"),
736 ),
737 ));
738 $this->assertEquals(array($case1['id'], $case2['id']), array_keys(CRM_Utils_Array::rekey($result['api.Case.get']['values'], 'id')));
739 }
740
741 /**
742 * Test the ability to order by client using the join syntax.
743 *
744 * For multi-client cases, should order by the first client.
745 */
746 public function testCaseGetOrderByClient() {
747 $contact1 = $this->individualCreate(array('first_name' => 'Aa', 'last_name' => 'Zz'));
748 $contact2 = $this->individualCreate(array('first_name' => 'Bb', 'last_name' => 'Zz'));
749 $contact3 = $this->individualCreate(array('first_name' => 'Cc', 'last_name' => 'Xx'));
750
751 $case1 = $this->callAPISuccess('Case', 'create', array(
752 'contact_id' => $contact1,
753 'subject' => "Test case 1",
754 'case_type_id' => $this->caseTypeId,
755 ));
756 $case2 = $this->callAPISuccess('Case', 'create', array(
757 'contact_id' => $contact2,
758 'subject' => "Test case 2",
759 'case_type_id' => $this->caseTypeId,
760 ));
761 $case3 = $this->callAPISuccess('Case', 'create', array(
762 'contact_id' => array($contact3, $contact1),
763 'subject' => "Test case 3",
764 'case_type_id' => $this->caseTypeId,
765 ));
766
767 $result = $this->callAPISuccess('Case', 'get', array(
768 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
769 'sequential' => 1,
770 'return' => 'id',
771 'options' => array('sort' => 'contact_id.first_name'),
772 ));
773 $this->assertEquals($case3['id'], $result['values'][2]['id']);
774 $this->assertEquals($case2['id'], $result['values'][1]['id']);
775 $this->assertEquals($case1['id'], $result['values'][0]['id']);
776
777 $result = $this->callAPISuccess('Case', 'get', array(
778 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
779 'sequential' => 1,
780 'return' => 'id',
781 'options' => array('sort' => 'contact_id.last_name ASC, contact_id.first_name DESC'),
782 ));
783 $this->assertEquals($case1['id'], $result['values'][2]['id']);
784 $this->assertEquals($case2['id'], $result['values'][1]['id']);
785 $this->assertEquals($case3['id'], $result['values'][0]['id']);
786
787 $result = $this->callAPISuccess('Case', 'get', array(
788 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
789 'sequential' => 1,
790 'return' => 'id',
791 'options' => array('sort' => 'contact_id.first_name DESC'),
792 ));
793 $this->assertEquals($case1['id'], $result['values'][2]['id']);
794 $this->assertEquals($case2['id'], $result['values'][1]['id']);
795 $this->assertEquals($case3['id'], $result['values'][0]['id']);
796
797 $result = $this->callAPISuccess('Case', 'get', array(
798 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
799 'sequential' => 1,
800 'return' => 'id',
801 'options' => array('sort' => 'case_type_id, contact_id DESC, status_id'),
802 ));
803 $this->assertEquals($case1['id'], $result['values'][2]['id']);
804 $this->assertEquals($case2['id'], $result['values'][1]['id']);
805 $this->assertEquals($case3['id'], $result['values'][0]['id']);
806 $this->assertCount(3, $result['values']);
807 }
808
809 /**
810 * Test the ability to add a timeline to an existing case.
811 *
812 * See the case.addtimeline api.
813 *
814 * @dataProvider caseActivityRevisionExamples
815 * @throws \Exception
816 */
817 public function testCaseAddtimeline($enableRevisions) {
818 $this->settingsStack->push('civicaseActivityRevisions', $enableRevisions);
819
820 $caseSpec = array(
821 'title' => 'Application with Definition',
822 'name' => 'Application_with_Definition',
823 'is_active' => 1,
824 'weight' => 4,
825 'definition' => array(
826 'activityTypes' => array(
827 array('name' => 'Follow up'),
828 ),
829 'activitySets' => array(
830 array(
831 'name' => 'set1',
832 'label' => 'Label 1',
833 'timeline' => 1,
834 'activityTypes' => array(
835 array('name' => 'Open Case', 'status' => 'Completed'),
836 ),
837 ),
838 array(
839 'name' => 'set2',
840 'label' => 'Label 2',
841 'timeline' => 1,
842 'activityTypes' => array(
843 array('name' => 'Follow up'),
844 ),
845 ),
846 ),
847 'caseRoles' => array(
848 array('name' => 'Homeless Services Coordinator', 'creator' => 1, 'manager' => 1),
849 ),
850 ),
851 );
852 $cid = $this->individualCreate();
853 $caseType = $this->callAPISuccess('CaseType', 'create', $caseSpec);
854 $case = $this->callAPISuccess('Case', 'create', array(
855 'case_type_id' => $caseType['id'],
856 'contact_id' => $cid,
857 'subject' => 'Test case with timeline',
858 ));
859 // Created case should only have 1 activity per the spec
860 $result = $this->callAPISuccessGetSingle('Activity', array('case_id' => $case['id'], 'return' => 'activity_type_id.name'));
861 $this->assertEquals('Open Case', $result['activity_type_id.name']);
862 // Add timeline
863 $timeline = civicrm_api('Case', 'addtimeline', array(
864 'case_id' => $case['id'],
865 'timeline' => 'set2',
866 'version' => 3,
867 ));
868 $result = $this->callAPISuccess('Activity', 'get', array(
869 'case_id' => $case['id'],
870 'return' => 'activity_type_id.name',
871 'sequential' => 1,
872 'options' => array('sort' => 'id'),
873 ));
874 $this->assertEquals(2, $result['count']);
875 $this->assertEquals('Follow up', $result['values'][1]['activity_type_id.name']);
876 }
877
878 /**
879 * Test the case merge function.
880 *
881 * 2 cases should be mergeable into 1
882 *
883 * @throws \Exception
884 */
885 public function testCaseMerge() {
886 $contact1 = $this->individualCreate(array(), 1);
887 $case1 = $this->callAPISuccess('Case', 'create', array(
888 'contact_id' => $contact1,
889 'subject' => "Test case 1",
890 'case_type_id' => $this->caseTypeId,
891 ));
892 $case2 = $this->callAPISuccess('Case', 'create', array(
893 'contact_id' => $contact1,
894 'subject' => "Test case 2",
895 'case_type_id' => $this->caseTypeId,
896 ));
897 $result = $this->callAPISuccess('Case', 'getcount', array('contact_id' => $contact1));
898 $this->assertEquals(2, $result);
899
900 $this->callAPISuccess('Case', 'merge', array('case_id_1' => $case1['id'], 'case_id_2' => $case2['id']));
901
902 $result = $this->callAPISuccess('Case', 'getsingle', array('id' => $case2['id']));
903 $this->assertEquals(1, $result['is_deleted']);
904 }
905
906 public function caseActivityRevisionExamples() {
907 $examples = array();
908 $examples[] = array(FALSE);
909 $examples[] = array(TRUE);
910 return $examples;
911 }
912
913 public function testTimestamps() {
914 $params = $this->_params;
915 $case_created = $this->callAPISuccess('case', 'create', $params);
916
917 $case_1 = $this->callAPISuccess('Case', 'getsingle', array(
918 'id' => $case_created['id'],
919 ));
920 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_1['created_date']);
921 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_1['modified_date']);
922 $this->assertApproxEquals(strtotime($case_1['created_date']), strtotime($case_1['modified_date']), 2);
923
924 $activity_1 = $this->callAPISuccess('activity', 'getsingle', array(
925 'case_id' => $case_created['id'],
926 'options' => array(
927 'limit' => 1,
928 ),
929 ));
930 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_1['created_date']);
931 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_1['modified_date']);
932 $this->assertApproxEquals(strtotime($activity_1['created_date']), strtotime($activity_1['modified_date']), 2);
933
934 usleep(1.5 * 1000000);
935 $this->callAPISuccess('activity', 'create', array(
936 'id' => $activity_1['id'],
937 'subject' => 'Make cheese',
938 ));
939
940 $activity_2 = $this->callAPISuccess('activity', 'getsingle', array(
941 'id' => $activity_1['id'],
942 ));
943 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_2['created_date']);
944 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_2['modified_date']);
945 $this->assertNotEquals($activity_2['created_date'], $activity_2['modified_date']);
946
947 $this->assertEquals($activity_1['created_date'], $activity_2['created_date']);
948 $this->assertNotEquals($activity_1['modified_date'], $activity_2['modified_date']);
949 $this->assertLessThan($activity_2['modified_date'], $activity_1['modified_date'],
950 sprintf("Original modification time (%s) should predate later modification time (%s)", $activity_1['modified_date'], $activity_2['modified_date']));
951
952 $case_2 = $this->callAPISuccess('Case', 'getsingle', array(
953 'id' => $case_created['id'],
954 ));
955 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_2['created_date']);
956 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_2['modified_date']);
957 $this->assertEquals($case_1['created_date'], $case_2['created_date']);
958 $this->assertNotEquals($case_2['created_date'], $case_2['modified_date']);
959 }
960
961 }