Merge pull request #11736 from jitendrapurohit/CRM-21815
[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 //Verify there are no active relationships.
190 $activeCaseRelationships = CRM_Case_BAO_Case::getCaseRoles($result['values'][$id]['client_id'][1], $id);
191 $this->assertEquals(count($activeCaseRelationships), 0, "Checking for empty array");
192
193 //Check if getCaseRoles() is able to return inactive relationships.
194 $caseRelationships = CRM_Case_BAO_Case::getCaseRoles($result['values'][$id]['client_id'][1], $id, NULL, FALSE);
195 $this->assertEquals(count($caseRelationships), 1);
196 }
197
198 /**
199 * Test case create with valid parameters and custom data.
200 */
201 public function testCaseCreateCustom() {
202 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
203 $params = $this->_params;
204 $params['custom_' . $ids['custom_field_id']] = "custom string";
205 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__);
206 $result = $this->callAPISuccess($this->_entity, 'get', array(
207 'return.custom_' . $ids['custom_field_id'] => 1,
208 'id' => $result['id'],
209 ));
210 $this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
211
212 $this->customFieldDelete($ids['custom_field_id']);
213 $this->customGroupDelete($ids['custom_group_id']);
214 }
215
216 /**
217 * Test update (create with id) function with valid parameters.
218 */
219 public function testCaseUpdate() {
220 $params = $this->_params;
221 // Test using name instead of value
222 unset($params['case_type_id']);
223 $params['case_type'] = $this->caseType;
224 $result = $this->callAPISuccess('case', 'create', $params);
225 $id = $result['id'];
226 $case = $this->callAPISuccess('case', 'getsingle', array('id' => $id));
227
228 // Update Case.
229 $params = array('id' => $id);
230 $params['subject'] = $case['subject'] = 'Something Else';
231 $this->callAPISuccess('case', 'create', $params);
232
233 // Verify that updated case is equal to the original with new subject.
234 $result = $this->callAPISuccessGetSingle('Case', array('case_id' => $id));
235 // Modification dates are likely to differ by 0-2 sec. Check manually.
236 $this->assertGreaterThanOrEqual($case['modified_date'], $result['modified_date']);
237 unset($result['modified_date'], $case['modified_date']);
238 // Everything else should be identical.
239 $this->assertAPIArrayComparison($result, $case);
240 }
241
242 /**
243 * Test update (create with id) function with valid parameters.
244 */
245 public function testCaseUpdateWithExistingCaseContact() {
246 $params = $this->_params;
247 // Test using name instead of value
248 unset($params['case_type_id']);
249 $params['case_type'] = $this->caseType;
250 $result = $this->callAPISuccess('case', 'create', $params);
251 $id = $result['id'];
252 $case = $this->callAPISuccess('case', 'getsingle', array('id' => $id));
253
254 // Update Case, we specify existing case ID and existing contact ID to verify that CaseContact.create is not called
255 $params = $this->_params;
256 $params['id'] = $id;
257 $this->callAPISuccess('case', 'create', $params);
258
259 // Verify that updated case is equal to the original with new subject.
260 $result = $this->callAPISuccessGetSingle('Case', array('case_id' => $id));
261 // Modification dates are likely to differ by 0-2 sec. Check manually.
262 $this->assertGreaterThanOrEqual($case['modified_date'], $result['modified_date']);
263 unset($result['modified_date'], $case['modified_date']);
264 // Everything else should be identical.
265 $this->assertAPIArrayComparison($result, $case);
266 }
267
268 /**
269 * Test case update with custom data
270 */
271 public function testCaseUpdateCustom() {
272 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
273 $params = $this->_params;
274
275 // Create a case with custom data
276 $params['custom_' . $ids['custom_field_id']] = 'custom string';
277 $result = $this->callAPISuccess($this->_entity, 'create', $params);
278
279 $caseId = $result['id'];
280 $result = $this->callAPISuccess($this->_entity, 'get', array(
281 'return.custom_' . $ids['custom_field_id'] => 1,
282 'version' => 3,
283 'id' => $result['id'],
284 ));
285 $this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
286 $fields = $this->callAPISuccess($this->_entity, 'getfields', array('version' => $this->_apiversion));
287 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
288
289 // Update the activity with custom data.
290 $params = array(
291 'id' => $caseId,
292 'custom_' . $ids['custom_field_id'] => 'Updated my test data',
293 'version' => $this->_apiversion,
294 );
295 $result = $this->callAPISuccess($this->_entity, 'create', $params);
296
297 $result = $this->callAPISuccess($this->_entity, 'get', array(
298 'return.custom_' . $ids['custom_field_id'] => 1,
299 'version' => 3,
300 'id' => $result['id'],
301 ));
302 $this->assertEquals("Updated my test data", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
303 }
304
305 /**
306 * Test delete function with valid parameters.
307 */
308 public function testCaseDelete() {
309 // Create Case
310 $result = $this->callAPISuccess('case', 'create', $this->_params);
311
312 // Move Case to Trash
313 $id = $result['id'];
314 $this->callAPISuccess('case', 'delete', array('id' => $id, 'move_to_trash' => 1));
315
316 // Check result - also check that 'case_id' works as well as 'id'
317 $result = $this->callAPISuccess('case', 'get', array('case_id' => $id));
318 $this->assertEquals(1, $result['values'][$id]['is_deleted']);
319
320 // Restore Case from Trash
321 $this->callAPISuccess('case', 'restore', array('id' => $id));
322
323 // Check result
324 $result = $this->callAPISuccess('case', 'get', array('case_id' => $id));
325 $this->assertEquals(0, $result['values'][$id]['is_deleted']);
326
327 // Delete Case Permanently
328 $this->callAPISuccess('case', 'delete', array('case_id' => $id));
329
330 // Check result - case should no longer exist
331 $result = $this->callAPISuccess('case', 'get', array('id' => $id));
332 $this->assertEquals(0, $result['count']);
333 }
334
335 /**
336 * Test Case role relationship is correctly created
337 * for contacts.
338 */
339 public function testCaseRoleRelationships() {
340 // Create Case
341 $case = $this->callAPISuccess('case', 'create', $this->_params);
342 $relType = $this->relationshipTypeCreate(array('name_a_b' => 'Test AB', 'name_b_a' => 'Test BA', 'contact_type_b' => 'Individual'));
343 $relContact = $this->individualCreate(array('first_name' => 'First', 'last_name' => 'Last'));
344
345 $_REQUEST = array(
346 'rel_type' => "{$relType}_b_a",
347 'rel_contact' => $relContact,
348 'case_id' => $case['id'],
349 'is_unit_test' => TRUE,
350 );
351 $ret = CRM_Contact_Page_AJAX::relationship();
352 $this->assertEquals(0, $ret['is_error']);
353 //Check if relationship exist for the case.
354 $relationship = $this->callAPISuccess('Relationship', 'get', array(
355 'sequential' => 1,
356 'relationship_type_id' => $relType,
357 'case_id' => $case['id'],
358 ));
359 $this->assertEquals($relContact, $relationship['values'][0]['contact_id_a']);
360 $this->assertEquals($this->_params['contact_id'], $relationship['values'][0]['contact_id_b']);
361
362 //Check if activity is assigned to correct contact.
363 $activity = $this->callAPISuccess('Activity', 'get', array(
364 'subject' => 'Test BA : Mr. First Last II',
365 ));
366 $activityContact = $this->callAPISuccess('ActivityContact', 'get', array(
367 'contact_id' => $relContact,
368 'activity_id' => $activity['id'],
369 ));
370 }
371
372 /**
373 * Test get function based on activity.
374 */
375 public function testCaseGetByActivity() {
376 // Create Case
377 $result = $this->callAPISuccess('case', 'create', $this->_params);
378 $id = $result['id'];
379
380 // Check result - we should get a list of activity ids
381 $result = $this->callAPISuccess('case', 'get', array('id' => $id, 'return' => 'activities'));
382 $case = $result['values'][$id];
383 $activity = $case['activities'][0];
384
385 // Fetch case based on an activity id
386 $result = $this->callAPISuccess('case', 'get', array(
387 'activity_id' => $activity,
388 'return' => 'activities',
389 ));
390 $this->assertEquals(FALSE, empty($result['values'][$id]));
391 $this->assertEquals($result['values'][$id], $case);
392 }
393
394 /**
395 * Test get function based on contact id.
396 */
397 public function testCaseGetByContact() {
398 // Create Case
399 $result = $this->callAPISuccess('case', 'create', $this->_params);
400 $id = $result['id'];
401
402 // Store result for later
403 $case = $this->callAPISuccessGetSingle('case', array('id' => $id, 'return' => array('activities', 'contacts')));
404
405 // Fetch case based on client contact id
406 $result = $this->callAPISuccess('case', 'get', array(
407 'client_id' => $this->_params['contact_id'],
408 'return' => array('activities', 'contacts'),
409 ));
410 $this->assertAPIArrayComparison($result['values'][$id], $case);
411 }
412
413 /**
414 * Test get function based on subject.
415 */
416 public function testCaseGetBySubject() {
417 // Create Case
418 $result = $this->callAPISuccess('case', 'create', $this->_params);
419 $id = $result['id'];
420
421 // Store result for later
422 $case = $this->callAPISuccessGetSingle('Case', array('id' => $id, 'return' => 'subject'));
423
424 // Fetch case based on client contact id
425 $result = $this->callAPISuccess('case', 'get', array(
426 'subject' => $this->_params['subject'],
427 'return' => array('subject'),
428 ));
429 $this->assertAPIArrayComparison($result['values'][$id], $case);
430 }
431
432 /**
433 * Test get function based on wrong subject.
434 */
435 public function testCaseGetByWrongSubject() {
436 $result = $this->callAPISuccess('case', 'create', $this->_params);
437
438 // Append 'wrong' to subject so that it is no longer the same.
439 $result = $this->callAPISuccess('case', 'get', array(
440 'subject' => $this->_params['subject'] . 'wrong',
441 'return' => array('activities', 'contacts'),
442 ));
443 $this->assertEquals(0, $result['count']);
444 }
445
446 /**
447 * Test get function with no criteria.
448 */
449 public function testCaseGetNoCriteria() {
450 $result = $this->callAPISuccess('case', 'create', $this->_params);
451 $id = $result['id'];
452
453 // Store result for later
454 $case = $this->callAPISuccessGetSingle('Case', array('id' => $id, 'return' => 'contact_id'));
455
456 $result = $this->callAPISuccess('case', 'get', array('limit' => 0, 'return' => array('contact_id')));
457 $this->assertAPIArrayComparison($result['values'][$id], $case);
458 }
459
460 /**
461 * Test activity api create for case activities.
462 */
463 public function testCaseActivityCreate() {
464 $params = $this->_params;
465 $case = $this->callAPISuccess('case', 'create', $params);
466 $params = array(
467 'case_id' => $case['id'],
468 // follow up
469 'activity_type_id' => $this->followup_activity_type_value,
470 'subject' => 'Test followup 123',
471 'source_contact_id' => $this->_loggedInUser,
472 'target_contact_id' => $this->_params['contact_id'],
473 );
474 $result = $this->callAPISuccess('activity', 'create', $params);
475 $this->assertEquals($result['values'][$result['id']]['activity_type_id'], $params['activity_type_id']);
476
477 // might need this for other tests that piggyback on this one
478 $this->_caseActivityId = $result['values'][$result['id']]['id'];
479
480 // Check other DB tables populated properly - is there a better way to do this? assertDBState() requires that we know the id already.
481 $dao = new CRM_Case_DAO_CaseActivity();
482 $dao->case_id = $case['id'];
483 $dao->activity_id = $this->_caseActivityId;
484 $this->assertEquals($dao->find(), 1, 'case_activity table not populated correctly in line ' . __LINE__);
485 $dao->free();
486
487 $dao = new CRM_Activity_DAO_ActivityContact();
488 $dao->activity_id = $this->_caseActivityId;
489 $dao->contact_id = $this->_params['contact_id'];
490 $dao->record_type_id = 3;
491 $this->assertEquals($dao->find(), 1, 'activity_contact table not populated correctly in line ' . __LINE__);
492 $dao->free();
493
494 // Check that fetching an activity by case id works, as well as returning case_id
495 $result = $this->callAPISuccessGetSingle('Activity', array(
496 'case_id' => $case['id'],
497 'activity_type_id' => $this->followup_activity_type_value,
498 'subject' => 'Test followup 123',
499 'return' => array('case_id'),
500 ));
501 $this->assertContains($case['id'], $result['case_id']);
502 }
503
504 /**
505 * Test activity api update for case activities.
506 */
507 public function testCaseActivityUpdate_Tracked() {
508 $this->settingsStack->push('civicaseActivityRevisions', TRUE);
509
510 // Need to create the case and activity before we can update it
511 $this->testCaseActivityCreate();
512
513 $params = array(
514 'activity_id' => $this->_caseActivityId,
515 'case_id' => 1,
516 'activity_type_id' => 14,
517 'source_contact_id' => $this->_loggedInUser,
518 'subject' => 'New subject',
519 );
520 $result = $this->callAPISuccess('activity', 'create', $params);
521
522 $this->assertEquals($result['values'][$result['id']]['subject'], $params['subject']);
523
524 // id should be one greater, since this is a new revision
525 $this->assertEquals($result['values'][$result['id']]['id'],
526 $this->_caseActivityId + 1,
527 'in line ' . __LINE__
528 );
529 $this->assertEquals($result['values'][$result['id']]['original_id'],
530 $this->_caseActivityId,
531 'in line ' . __LINE__
532 );
533
534 // Check revision is as expected
535 $revParams = array(
536 'activity_id' => $this->_caseActivityId,
537 );
538 $revActivity = $this->callAPISuccess('activity', 'get', $revParams);
539 $this->assertEquals($revActivity['values'][$this->_caseActivityId]['is_current_revision'],
540 0);
541 $this->assertEquals($revActivity['values'][$this->_caseActivityId]['is_deleted'],
542 0
543 );
544
545 //TODO: check some more things
546 }
547
548 /**
549 * If you disable `civicaseActivityRevisions`, then editing an activity
550 * will *not* create or change IDs.
551 */
552 public function testCaseActivityUpdate_Untracked() {
553 $this->settingsStack->push('civicaseActivityRevisions', FALSE);
554
555 // Need to create the case and activity before we can update it
556 $this->testCaseActivityCreate();
557
558 $oldIDs = CRM_Utils_SQL_Select::from('civicrm_activity')
559 ->select('id, original_id, is_current_revision')
560 ->orderBy('id')
561 ->execute()->fetchAll();
562
563 $params = array(
564 'activity_id' => $this->_caseActivityId,
565 'case_id' => 1,
566 'activity_type_id' => 14,
567 'source_contact_id' => $this->_loggedInUser,
568 'subject' => 'New subject',
569 );
570 $result = $this->callAPISuccess('activity', 'create', $params);
571 $this->assertEquals($result['values'][$result['id']]['subject'], $params['subject']);
572
573 // id should not change because we've opted out.
574 $this->assertEquals($this->_caseActivityId, $result['values'][$result['id']]['id']);
575 $this->assertEmpty($result['values'][$result['id']]['original_id']);
576
577 $newIDs = CRM_Utils_SQL_Select::from('civicrm_activity')
578 ->select('id, original_id, is_current_revision')
579 ->orderBy('id')
580 ->execute()->fetchAll();
581 $this->assertEquals($oldIDs, $newIDs);
582 }
583
584 public function testCaseActivityUpdateCustom() {
585 $this->settingsStack->push('civicaseActivityRevisions', TRUE);
586
587 // Create a case first
588 $result = $this->callAPISuccess('case', 'create', $this->_params);
589
590 // Create custom field group
591 // Note the second parameter is Activity on purpose, not Case.
592 $custom_ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, 'ActivityTest.php');
593
594 // create activity
595 $params = array(
596 'case_id' => $result['id'],
597 // follow up
598 'activity_type_id' => 14,
599 'subject' => 'Test followup',
600 'source_contact_id' => $this->_loggedInUser,
601 'target_contact_id' => $this->_params['contact_id'],
602 'custom_' . $custom_ids['custom_field_id'] => "custom string",
603 );
604 $result = $this->callAPISuccess('activity', 'create', $params);
605
606 $aid = $result['values'][$result['id']]['id'];
607
608 // Update activity
609 $params = array(
610 'activity_id' => $aid,
611 'case_id' => 1,
612 'activity_type_id' => 14,
613 'source_contact_id' => $this->_loggedInUser,
614 'subject' => 'New subject',
615 );
616 $this->callAPISuccess('activity', 'create', $params);
617
618 // Retrieve revision and check custom fields got copied.
619 $revParams = array(
620 'activity_id' => $aid + 1,
621 'return.custom_' . $custom_ids['custom_field_id'] => 1,
622 );
623 $revAct = $this->callAPISuccess('activity', 'get', $revParams);
624
625 $this->assertEquals($revAct['values'][$aid + 1]['custom_' . $custom_ids['custom_field_id']], "custom string",
626 "Error message: " . CRM_Utils_Array::value('error_message', $revAct));
627
628 $this->customFieldDelete($custom_ids['custom_field_id']);
629 $this->customGroupDelete($custom_ids['custom_group_id']);
630 }
631
632 public function testCaseGetByStatus() {
633 // Create 2 cases with different status ids.
634 $case1 = $this->callAPISuccess('Case', 'create', array(
635 'contact_id' => 17,
636 'subject' => "Test case 1",
637 'case_type_id' => $this->caseTypeId,
638 'status_id' => "Open",
639 'sequential' => 1,
640 ));
641 $this->callAPISuccess('Case', 'create', array(
642 'contact_id' => 17,
643 'subject' => "Test case 2",
644 'case_type_id' => $this->caseTypeId,
645 'status_id' => "Urgent",
646 'sequential' => 1,
647 ));
648 $result = $this->callAPISuccessGetSingle('Case', array(
649 'sequential' => 1,
650 'contact_id' => 17,
651 'status_id' => "Open",
652 ));
653 $this->assertEquals($case1['id'], $result['id']);
654 }
655
656 public function testCaseGetWithRoles() {
657 $case1 = $this->callAPISuccess('Case', 'create', array(
658 'contact_id' => 17,
659 'subject' => "Test case with roles",
660 'case_type_id' => $this->caseTypeId,
661 'status_id' => "Open",
662 ));
663 $result = $this->callAPISuccessGetSingle('Case', array(
664 'id' => $case1['id'],
665 'status_id' => "Open",
666 'return' => array('contacts'),
667 ));
668 foreach ($result['contacts'] as $contact) {
669 if ($contact['role'] == 'Client') {
670 $this->assertEquals(17, $contact['contact_id']);
671 }
672 elseif ($contact['role'] == 'Homeless Services Coordinator') {
673 $this->assertEquals(1, $contact['creator']);
674 $this->assertEquals(1, $contact['manager']);
675 }
676 }
677 }
678
679 public function testCaseGetWithDefinition() {
680 $case1 = $this->callAPISuccess('Case', 'create', array(
681 'contact_id' => 17,
682 'subject' => "Test case with definition",
683 'case_type_id' => $this->caseTypeId,
684 'status_id' => "Open",
685 ));
686 $result1 = $this->callAPISuccessGetSingle('Case', array(
687 'id' => $case1['id'],
688 'status_id' => "Open",
689 'return' => array('case_type_id.definition'),
690 ));
691 $result2 = $this->callAPISuccessGetSingle('Case', array(
692 'id' => $case1['id'],
693 'status_id' => "Open",
694 'return' => array('case_type_id', 'case_type_id.definition'),
695 ));
696 $this->assertEquals($result1['case_type_id.definition'], $result2['case_type_id.definition']);
697 $def = $result1['case_type_id.definition'];
698 $this->assertEquals(array('name' => 'Open Case', 'max_instances' => 1), $def['activityTypes'][0]);
699 $this->assertNotEmpty($def['activitySets'][0]['activityTypes']);
700 $this->assertNotEmpty($def['caseRoles'][0]['manager']);
701 $this->assertNotEmpty($def['caseRoles'][0]['creator']);
702 }
703
704 public function testCaseGetTags() {
705 $case1 = $this->callAPISuccess('Case', 'create', array(
706 'contact_id' => 17,
707 'subject' => "Test case with tags",
708 'case_type_id' => $this->caseTypeId,
709 'status_id' => "Open",
710 ));
711 $tag1 = $this->tagCreate(array(
712 'name' => 'CaseTag1',
713 'used_for' => 'civicrm_case',
714 ));
715 $tag2 = $this->tagCreate(array(
716 'name' => 'CaseTag2',
717 'used_for' => 'civicrm_case',
718 ));
719 $this->callAPISuccess('EntityTag', 'create', array(
720 'entity_table' => 'civicrm_case',
721 'entity_id' => $case1['id'],
722 'tag_id' => $tag1['id'],
723 ));
724 $this->callAPIFailure('Case', 'getsingle', array(
725 'tag_id' => $tag2['id'],
726 ));
727 $result = $this->callAPISuccessGetSingle('Case', array(
728 'tag_id' => $tag1['id'],
729 'return' => 'tag_id.name',
730 ));
731 $this->assertEquals('CaseTag1', $result['tag_id'][$tag1['id']]['tag_id.name']);
732 }
733
734 /**
735 * Test that a chained api call can use the operator syntax.
736 *
737 * E.g. array('IN' => $value.contact_id)
738 *
739 * @throws \Exception
740 */
741 public function testCaseGetChainedOp() {
742 $contact1 = $this->individualCreate(array(), 1);
743 $contact2 = $this->individualCreate(array(), 2);
744 $case1 = $this->callAPISuccess('Case', 'create', array(
745 'contact_id' => $contact1,
746 'subject' => "Test case 1",
747 'case_type_id' => $this->caseTypeId,
748 ));
749 $case2 = $this->callAPISuccess('Case', 'create', array(
750 'contact_id' => $contact2,
751 'subject' => "Test case 2",
752 'case_type_id' => $this->caseTypeId,
753 ));
754 $case3 = $this->callAPISuccess('Case', 'create', array(
755 'contact_id' => array($contact1, $contact2),
756 'subject' => "Test case 3",
757 'case_type_id' => $this->caseTypeId,
758 ));
759
760 // Fetch case 1 and all cases with the same client. Chained get should return case 3.
761 $result = $this->callAPISuccessGetSingle('Case', array(
762 'id' => $case1['id'],
763 'return' => 'contact_id',
764 'api.Case.get' => array(
765 'contact_id' => array('IN' => "\$value.contact_id"),
766 'id' => array('!=' => "\$value.id"),
767 ),
768 ));
769 $this->assertEquals($case3['id'], $result['api.Case.get']['id']);
770
771 // Fetch case 3 and all cases with the same clients. Chained get should return case 1&2.
772 $result = $this->callAPISuccessGetSingle('Case', array(
773 'id' => $case3['id'],
774 'return' => array('contact_id'),
775 'api.Case.get' => array(
776 'return' => 'id',
777 'contact_id' => array('IN' => "\$value.contact_id"),
778 'id' => array('!=' => "\$value.id"),
779 ),
780 ));
781 $this->assertEquals(array($case1['id'], $case2['id']), array_keys(CRM_Utils_Array::rekey($result['api.Case.get']['values'], 'id')));
782 }
783
784 /**
785 * Test the ability to order by client using the join syntax.
786 *
787 * For multi-client cases, should order by the first client.
788 */
789 public function testCaseGetOrderByClient() {
790 $contact1 = $this->individualCreate(array('first_name' => 'Aa', 'last_name' => 'Zz'));
791 $contact2 = $this->individualCreate(array('first_name' => 'Bb', 'last_name' => 'Zz'));
792 $contact3 = $this->individualCreate(array('first_name' => 'Cc', 'last_name' => 'Xx'));
793
794 $case1 = $this->callAPISuccess('Case', 'create', array(
795 'contact_id' => $contact1,
796 'subject' => "Test case 1",
797 'case_type_id' => $this->caseTypeId,
798 ));
799 $case2 = $this->callAPISuccess('Case', 'create', array(
800 'contact_id' => $contact2,
801 'subject' => "Test case 2",
802 'case_type_id' => $this->caseTypeId,
803 ));
804 $case3 = $this->callAPISuccess('Case', 'create', array(
805 'contact_id' => array($contact3, $contact1),
806 'subject' => "Test case 3",
807 'case_type_id' => $this->caseTypeId,
808 ));
809
810 $result = $this->callAPISuccess('Case', 'get', array(
811 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
812 'sequential' => 1,
813 'return' => 'id',
814 'options' => array('sort' => 'contact_id.first_name'),
815 ));
816 $this->assertEquals($case3['id'], $result['values'][2]['id']);
817 $this->assertEquals($case2['id'], $result['values'][1]['id']);
818 $this->assertEquals($case1['id'], $result['values'][0]['id']);
819
820 $result = $this->callAPISuccess('Case', 'get', array(
821 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
822 'sequential' => 1,
823 'return' => 'id',
824 'options' => array('sort' => 'contact_id.last_name ASC, contact_id.first_name DESC'),
825 ));
826 $this->assertEquals($case1['id'], $result['values'][2]['id']);
827 $this->assertEquals($case2['id'], $result['values'][1]['id']);
828 $this->assertEquals($case3['id'], $result['values'][0]['id']);
829
830 $result = $this->callAPISuccess('Case', 'get', array(
831 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
832 'sequential' => 1,
833 'return' => 'id',
834 'options' => array('sort' => 'contact_id.first_name DESC'),
835 ));
836 $this->assertEquals($case1['id'], $result['values'][2]['id']);
837 $this->assertEquals($case2['id'], $result['values'][1]['id']);
838 $this->assertEquals($case3['id'], $result['values'][0]['id']);
839
840 $result = $this->callAPISuccess('Case', 'get', array(
841 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
842 'sequential' => 1,
843 'return' => 'id',
844 'options' => array('sort' => 'case_type_id, contact_id DESC, status_id'),
845 ));
846 $this->assertEquals($case1['id'], $result['values'][2]['id']);
847 $this->assertEquals($case2['id'], $result['values'][1]['id']);
848 $this->assertEquals($case3['id'], $result['values'][0]['id']);
849 $this->assertCount(3, $result['values']);
850 }
851
852 /**
853 * Test the ability to add a timeline to an existing case.
854 *
855 * See the case.addtimeline api.
856 *
857 * @dataProvider caseActivityRevisionExamples
858 * @throws \Exception
859 */
860 public function testCaseAddtimeline($enableRevisions) {
861 $this->settingsStack->push('civicaseActivityRevisions', $enableRevisions);
862
863 $caseSpec = array(
864 'title' => 'Application with Definition',
865 'name' => 'Application_with_Definition',
866 'is_active' => 1,
867 'weight' => 4,
868 'definition' => array(
869 'activityTypes' => array(
870 array('name' => 'Follow up'),
871 ),
872 'activitySets' => array(
873 array(
874 'name' => 'set1',
875 'label' => 'Label 1',
876 'timeline' => 1,
877 'activityTypes' => array(
878 array('name' => 'Open Case', 'status' => 'Completed'),
879 ),
880 ),
881 array(
882 'name' => 'set2',
883 'label' => 'Label 2',
884 'timeline' => 1,
885 'activityTypes' => array(
886 array('name' => 'Follow up'),
887 ),
888 ),
889 ),
890 'caseRoles' => array(
891 array('name' => 'Homeless Services Coordinator', 'creator' => 1, 'manager' => 1),
892 ),
893 ),
894 );
895 $cid = $this->individualCreate();
896 $caseType = $this->callAPISuccess('CaseType', 'create', $caseSpec);
897 $case = $this->callAPISuccess('Case', 'create', array(
898 'case_type_id' => $caseType['id'],
899 'contact_id' => $cid,
900 'subject' => 'Test case with timeline',
901 ));
902 // Created case should only have 1 activity per the spec
903 $result = $this->callAPISuccessGetSingle('Activity', array('case_id' => $case['id'], 'return' => 'activity_type_id.name'));
904 $this->assertEquals('Open Case', $result['activity_type_id.name']);
905 // Add timeline
906 $timeline = civicrm_api('Case', 'addtimeline', array(
907 'case_id' => $case['id'],
908 'timeline' => 'set2',
909 'version' => 3,
910 ));
911 $result = $this->callAPISuccess('Activity', 'get', array(
912 'case_id' => $case['id'],
913 'return' => 'activity_type_id.name',
914 'sequential' => 1,
915 'options' => array('sort' => 'id'),
916 ));
917 $this->assertEquals(2, $result['count']);
918 $this->assertEquals('Follow up', $result['values'][1]['activity_type_id.name']);
919 }
920
921 /**
922 * Test the case merge function.
923 *
924 * 2 cases should be mergeable into 1
925 *
926 * @throws \Exception
927 */
928 public function testCaseMerge() {
929 $contact1 = $this->individualCreate(array(), 1);
930 $case1 = $this->callAPISuccess('Case', 'create', array(
931 'contact_id' => $contact1,
932 'subject' => "Test case 1",
933 'case_type_id' => $this->caseTypeId,
934 ));
935 $case2 = $this->callAPISuccess('Case', 'create', array(
936 'contact_id' => $contact1,
937 'subject' => "Test case 2",
938 'case_type_id' => $this->caseTypeId,
939 ));
940 $result = $this->callAPISuccess('Case', 'getcount', array('contact_id' => $contact1));
941 $this->assertEquals(2, $result);
942
943 $this->callAPISuccess('Case', 'merge', array('case_id_1' => $case1['id'], 'case_id_2' => $case2['id']));
944
945 $result = $this->callAPISuccess('Case', 'getsingle', array('id' => $case2['id']));
946 $this->assertEquals(1, $result['is_deleted']);
947 }
948
949 public function caseActivityRevisionExamples() {
950 $examples = array();
951 $examples[] = array(FALSE);
952 $examples[] = array(TRUE);
953 return $examples;
954 }
955
956 public function testTimestamps() {
957 $params = $this->_params;
958 $case_created = $this->callAPISuccess('case', 'create', $params);
959
960 $case_1 = $this->callAPISuccess('Case', 'getsingle', array(
961 'id' => $case_created['id'],
962 ));
963 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_1['created_date']);
964 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_1['modified_date']);
965 $this->assertApproxEquals(strtotime($case_1['created_date']), strtotime($case_1['modified_date']), 2);
966
967 $activity_1 = $this->callAPISuccess('activity', 'getsingle', array(
968 'case_id' => $case_created['id'],
969 'options' => array(
970 'limit' => 1,
971 ),
972 ));
973 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_1['created_date']);
974 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_1['modified_date']);
975 $this->assertApproxEquals(strtotime($activity_1['created_date']), strtotime($activity_1['modified_date']), 2);
976
977 usleep(1.5 * 1000000);
978 $this->callAPISuccess('activity', 'create', array(
979 'id' => $activity_1['id'],
980 'subject' => 'Make cheese',
981 ));
982
983 $activity_2 = $this->callAPISuccess('activity', 'getsingle', array(
984 'id' => $activity_1['id'],
985 ));
986 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_2['created_date']);
987 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $activity_2['modified_date']);
988 $this->assertNotEquals($activity_2['created_date'], $activity_2['modified_date']);
989
990 $this->assertEquals($activity_1['created_date'], $activity_2['created_date']);
991 $this->assertNotEquals($activity_1['modified_date'], $activity_2['modified_date']);
992 $this->assertLessThan($activity_2['modified_date'], $activity_1['modified_date'],
993 sprintf("Original modification time (%s) should predate later modification time (%s)", $activity_1['modified_date'], $activity_2['modified_date']));
994
995 $case_2 = $this->callAPISuccess('Case', 'getsingle', array(
996 'id' => $case_created['id'],
997 ));
998 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_2['created_date']);
999 $this->assertRegExp(';^\d\d\d\d-\d\d-\d\d \d\d:\d\d;', $case_2['modified_date']);
1000 $this->assertEquals($case_1['created_date'], $case_2['created_date']);
1001 $this->assertNotEquals($case_2['created_date'], $case_2['modified_date']);
1002 }
1003
1004 }