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