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