Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
7865d848 EM |
2 | /* |
3 | +--------------------------------------------------------------------+ | |
2fe49090 | 4 | | CiviCRM version 5 | |
7865d848 | 5 | +--------------------------------------------------------------------+ |
6b83d5bd | 6 | | Copyright CiviCRM LLC (c) 2004-2019 | |
7865d848 EM |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
26 | */ | |
6a488035 TO |
27 | |
28 | /** | |
29 | * File for the MembershipTest class | |
30 | * | |
31 | * (PHP 5) | |
32 | * | |
6c6e6187 | 33 | * @author Walt Haas <walt@dharmatech.org> (801) 534-1262 |
6a488035 TO |
34 | */ |
35 | ||
6a488035 | 36 | /** |
7865d848 | 37 | * Test CRM_Member_Form_Membership functions. |
6a488035 | 38 | * |
6c6e6187 | 39 | * @package CiviCRM |
acb109b7 | 40 | * @group headless |
6a488035 TO |
41 | */ |
42 | class CRM_Member_Form_MembershipTest extends CiviUnitTestCase { | |
43 | ||
7865d848 EM |
44 | protected $_individualId; |
45 | protected $_contribution; | |
46 | protected $_financialTypeId = 1; | |
47 | protected $_apiversion; | |
48 | protected $_entity = 'Membership'; | |
49 | protected $_params; | |
9099cab3 | 50 | protected $_ids = []; |
7865d848 EM |
51 | protected $_paymentProcessorID; |
52 | ||
08fd4b45 EM |
53 | /** |
54 | * Membership type ID for annual fixed membership. | |
55 | * | |
56 | * @var int | |
57 | */ | |
58 | protected $membershipTypeAnnualFixedID; | |
59 | ||
7865d848 EM |
60 | /** |
61 | * Parameters to create payment processor. | |
62 | * | |
63 | * @var array | |
64 | */ | |
9099cab3 | 65 | protected $_processorParams = []; |
7865d848 EM |
66 | |
67 | /** | |
68 | * ID of created membership. | |
69 | * | |
70 | * @var int | |
71 | */ | |
72 | protected $_membershipID; | |
73 | ||
74 | /** | |
75 | * Payment instrument mapping. | |
76 | * | |
77 | * @var array | |
78 | */ | |
9099cab3 | 79 | protected $paymentInstruments = []; |
7865d848 | 80 | |
bbaa79ff EM |
81 | /** |
82 | * @var CiviMailUtils | |
83 | */ | |
84 | protected $mut; | |
85 | ||
6a488035 | 86 | /** |
41709813 | 87 | * Test setup for every test. |
6a488035 | 88 | * |
41709813 EM |
89 | * Connect to the database, truncate the tables that will be used |
90 | * and redirect stdin to a temporary file. | |
6a488035 TO |
91 | */ |
92 | public function setUp() { | |
cb447e7a | 93 | $this->_apiversion = 3; |
6a488035 TO |
94 | parent::setUp(); |
95 | ||
cb447e7a | 96 | $this->_individualId = $this->individualCreate(); |
8950ecdc | 97 | $this->_paymentProcessorID = $this->processorCreate(); |
1d291c60 | 98 | |
99 | $this->loadXMLDataSet(dirname(__FILE__) . '/dataset/data.xml'); | |
100 | ||
9099cab3 | 101 | $membershipTypeAnnualFixed = $this->callAPISuccess('membership_type', 'create', [ |
08fd4b45 EM |
102 | 'domain_id' => 1, |
103 | 'name' => "AnnualFixed", | |
104 | 'member_of_contact_id' => 23, | |
105 | 'duration_unit' => "year", | |
268a84f2 | 106 | 'minimum_fee' => 50, |
08fd4b45 EM |
107 | 'duration_interval' => 1, |
108 | 'period_type' => "fixed", | |
109 | 'fixed_period_start_day' => "101", | |
110 | 'fixed_period_rollover_day' => "1231", | |
111 | 'relationship_type_id' => 20, | |
112 | 'financial_type_id' => 2, | |
9099cab3 | 113 | ]); |
08fd4b45 | 114 | $this->membershipTypeAnnualFixedID = $membershipTypeAnnualFixed['id']; |
7865d848 | 115 | |
9099cab3 | 116 | $instruments = $this->callAPISuccess('contribution', 'getoptions', ['field' => 'payment_instrument_id']); |
7865d848 EM |
117 | $this->paymentInstruments = $instruments['values']; |
118 | } | |
119 | ||
cb447e7a EM |
120 | /** |
121 | * Clean up after each test. | |
122 | */ | |
123 | public function tearDown() { | |
124 | $this->quickCleanUpFinancialEntities(); | |
125 | $this->quickCleanup( | |
9099cab3 | 126 | [ |
cb447e7a EM |
127 | 'civicrm_relationship', |
128 | 'civicrm_membership_type', | |
129 | 'civicrm_membership', | |
a8215a8d | 130 | 'civicrm_uf_match', |
360a0925 | 131 | 'civicrm_email', |
9099cab3 | 132 | ] |
cb447e7a | 133 | ); |
9099cab3 CW |
134 | foreach ([17, 18, 23, 32] as $contactID) { |
135 | $this->callAPISuccess('contact', 'delete', ['id' => $contactID, 'skip_undelete' => TRUE]); | |
e2ce0d88 | 136 | } |
9099cab3 | 137 | $this->callAPISuccess('relationship_type', 'delete', ['id' => 20]); |
cb447e7a EM |
138 | } |
139 | ||
6a488035 TO |
140 | /** |
141 | * Test CRM_Member_Form_Membership::formRule() with a parameter | |
142 | * that has an empty contact_select_id value | |
143 | */ | |
00be9182 | 144 | public function testFormRuleEmptyContact() { |
9099cab3 | 145 | $params = [ |
6a488035 | 146 | 'contact_select_id' => 0, |
9099cab3 CW |
147 | 'membership_type_id' => [1 => NULL], |
148 | ]; | |
149 | $files = []; | |
a130e045 | 150 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 151 | $rc = $obj->formRule($params, $files, $obj); |
cb447e7a EM |
152 | $this->assertType('array', $rc); |
153 | $this->assertTrue(array_key_exists('membership_type_id', $rc)); | |
6a488035 | 154 | |
9099cab3 | 155 | $params['membership_type_id'] = [1 => 3]; |
6a488035 | 156 | $rc = $obj->formRule($params, $files, $obj); |
cb447e7a EM |
157 | $this->assertType('array', $rc); |
158 | $this->assertTrue(array_key_exists('join_date', $rc)); | |
6a488035 TO |
159 | } |
160 | ||
161 | /** | |
cb447e7a EM |
162 | * Test that form rule fails if start date is before join date. |
163 | * | |
164 | * Test CRM_Member_Form_Membership::formRule() with a parameter | |
165 | * that has an start date before the join date and a rolling | |
166 | * membership type. | |
6a488035 | 167 | */ |
00be9182 | 168 | public function testFormRuleRollingEarlyStart() { |
92915c55 | 169 | $unixNow = time(); |
6a488035 | 170 | $unixYesterday = $unixNow - (24 * 60 * 60); |
8b408447 | 171 | $ymdYesterday = date('Y-m-d', $unixYesterday); |
9099cab3 | 172 | $params = [ |
8b408447 | 173 | 'join_date' => date('Y-m-d'), |
6a488035 TO |
174 | 'start_date' => $ymdYesterday, |
175 | 'end_date' => '', | |
9099cab3 CW |
176 | 'membership_type_id' => ['23', '15'], |
177 | ]; | |
178 | $files = []; | |
a130e045 | 179 | $obj = new CRM_Member_Form_Membership(); |
9099cab3 | 180 | $rc = call_user_func(['CRM_Member_Form_Membership', 'formRule'], |
6a488035 TO |
181 | $params, $files, $obj |
182 | ); | |
cb447e7a EM |
183 | $this->assertType('array', $rc); |
184 | $this->assertTrue(array_key_exists('start_date', $rc)); | |
6a488035 TO |
185 | } |
186 | ||
187 | /** | |
188 | * Test CRM_Member_Form_Membership::formRule() with a parameter | |
189 | * that has an end date before the start date and a rolling | |
190 | * membership type | |
191 | */ | |
00be9182 | 192 | public function testFormRuleRollingEarlyEnd() { |
92915c55 | 193 | $unixNow = time(); |
6a488035 | 194 | $unixYesterday = $unixNow - (24 * 60 * 60); |
8b408447 | 195 | $ymdYesterday = date('Y-m-d', $unixYesterday); |
9099cab3 | 196 | $params = [ |
8b408447 | 197 | 'join_date' => date('Y-m-d'), |
198 | 'start_date' => date('Y-m-d'), | |
6a488035 | 199 | 'end_date' => $ymdYesterday, |
9099cab3 CW |
200 | 'membership_type_id' => ['23', '15'], |
201 | ]; | |
202 | $files = []; | |
a130e045 | 203 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 204 | $rc = $obj->formRule($params, $files, $obj); |
08fd4b45 EM |
205 | $this->assertType('array', $rc); |
206 | $this->assertTrue(array_key_exists('end_date', $rc)); | |
6a488035 TO |
207 | } |
208 | ||
209 | /** | |
41709813 | 210 | * Test CRM_Member_Form_Membership::formRule() with end date but no start date and a rolling membership type. |
6a488035 | 211 | */ |
00be9182 | 212 | public function testFormRuleRollingEndNoStart() { |
92915c55 | 213 | $unixNow = time(); |
6a488035 | 214 | $unixYearFromNow = $unixNow + (365 * 24 * 60 * 60); |
8b408447 | 215 | $ymdYearFromNow = date('Y-m-d', $unixYearFromNow); |
9099cab3 | 216 | $params = [ |
8b408447 | 217 | 'join_date' => date('Y-m-d'), |
6a488035 TO |
218 | 'start_date' => '', |
219 | 'end_date' => $ymdYearFromNow, | |
9099cab3 CW |
220 | 'membership_type_id' => ['23', '15'], |
221 | ]; | |
222 | $files = []; | |
a130e045 | 223 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 224 | $rc = $obj->formRule($params, $files, $obj); |
08fd4b45 EM |
225 | $this->assertType('array', $rc); |
226 | $this->assertTrue(array_key_exists('start_date', $rc)); | |
6a488035 TO |
227 | } |
228 | ||
229 | /** | |
230 | * Test CRM_Member_Form_Membership::formRule() with a parameter | |
231 | * that has an end date and a lifetime membership type | |
232 | */ | |
00be9182 | 233 | public function testFormRuleRollingLifetimeEnd() { |
92915c55 | 234 | $unixNow = time(); |
6a488035 | 235 | $unixYearFromNow = $unixNow + (365 * 24 * 60 * 60); |
9099cab3 | 236 | $params = [ |
8b408447 | 237 | 'join_date' => date('Y-m-d'), |
238 | 'start_date' => date('Y-m-d'), | |
239 | 'end_date' => date('Y-m-d', | |
6a488035 TO |
240 | $unixYearFromNow |
241 | ), | |
9099cab3 CW |
242 | 'membership_type_id' => ['23', '25'], |
243 | ]; | |
244 | $files = []; | |
a130e045 | 245 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 246 | $rc = $obj->formRule($params, $files, $obj); |
fada2199 EM |
247 | $this->assertType('array', $rc); |
248 | $this->assertTrue(array_key_exists('status_id', $rc)); | |
6a488035 TO |
249 | } |
250 | ||
251 | /** | |
252 | * Test CRM_Member_Form_Membership::formRule() with a parameter | |
e136f704 | 253 | * that has permanent override and no status |
6a488035 | 254 | */ |
e136f704 | 255 | public function testFormRulePermanentOverrideWithNoStatus() { |
92915c55 | 256 | $unixNow = time(); |
9099cab3 | 257 | $params = [ |
8b408447 | 258 | 'join_date' => date('Y-m-d'), |
9099cab3 | 259 | 'membership_type_id' => ['23', '25'], |
6a488035 | 260 | 'is_override' => TRUE, |
9099cab3 CW |
261 | ]; |
262 | $files = []; | |
a130e045 | 263 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 264 | $rc = $obj->formRule($params, $files, $obj); |
41709813 EM |
265 | $this->assertType('array', $rc); |
266 | $this->assertTrue(array_key_exists('status_id', $rc)); | |
6a488035 TO |
267 | } |
268 | ||
e136f704 | 269 | public function testFormRuleUntilDateOverrideWithValidOverrideEndDate() { |
9099cab3 | 270 | $params = [ |
8b408447 | 271 | 'join_date' => date('Y-m-d'), |
9099cab3 | 272 | 'membership_type_id' => ['23', '25'], |
e136f704 O |
273 | 'is_override' => TRUE, |
274 | 'status_id' => 1, | |
8b408447 | 275 | 'status_override_end_date' => date('Y-m-d'), |
9099cab3 CW |
276 | ]; |
277 | $files = []; | |
e136f704 O |
278 | $membershipForm = new CRM_Member_Form_Membership(); |
279 | $validationResponse = $membershipForm->formRule($params, $files, $membershipForm); | |
280 | $this->assertTrue($validationResponse); | |
281 | } | |
282 | ||
283 | public function testFormRuleUntilDateOverrideWithNoOverrideEndDate() { | |
9099cab3 | 284 | $params = [ |
8b408447 | 285 | 'join_date' => date('Y-m-d'), |
9099cab3 | 286 | 'membership_type_id' => ['23', '25'], |
e136f704 O |
287 | 'is_override' => CRM_Member_StatusOverrideTypes::UNTIL_DATE, |
288 | 'status_id' => 1, | |
9099cab3 CW |
289 | ]; |
290 | $files = []; | |
e136f704 O |
291 | $membershipForm = new CRM_Member_Form_Membership(); |
292 | $validationResponse = $membershipForm->formRule($params, $files, $membershipForm); | |
293 | $this->assertType('array', $validationResponse); | |
294 | $this->assertEquals('Please enter the Membership override end date.', $validationResponse['status_override_end_date']); | |
295 | } | |
296 | ||
6a488035 TO |
297 | /** |
298 | * Test CRM_Member_Form_Membership::formRule() with a join date | |
299 | * of one month from now and a rolling membership type | |
300 | */ | |
00be9182 | 301 | public function testFormRuleRollingJoin1MonthFromNow() { |
92915c55 | 302 | $unixNow = time(); |
6a488035 | 303 | $unix1MFmNow = $unixNow + (31 * 24 * 60 * 60); |
9099cab3 | 304 | $params = [ |
8b408447 | 305 | 'join_date' => date('Y-m-d', $unix1MFmNow), |
6a488035 TO |
306 | 'start_date' => '', |
307 | 'end_date' => '', | |
9099cab3 CW |
308 | 'membership_type_id' => ['23', '15'], |
309 | ]; | |
310 | $files = []; | |
a130e045 | 311 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 312 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 | 313 | |
41709813 EM |
314 | // Should have found no valid membership status. |
315 | $this->assertType('array', $rc); | |
316 | $this->assertTrue(array_key_exists('_qf_default', $rc)); | |
6a488035 TO |
317 | } |
318 | ||
319 | /** | |
41709813 | 320 | * Test CRM_Member_Form_Membership::formRule() with a join date of today and a rolling membership type. |
6a488035 | 321 | */ |
00be9182 | 322 | public function testFormRuleRollingJoinToday() { |
9099cab3 | 323 | $params = [ |
8b408447 | 324 | 'join_date' => date('Y-m-d'), |
6a488035 TO |
325 | 'start_date' => '', |
326 | 'end_date' => '', | |
9099cab3 CW |
327 | 'membership_type_id' => ['23', '15'], |
328 | ]; | |
329 | $files = []; | |
a130e045 | 330 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 331 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 TO |
332 | |
333 | // Should have found New membership status | |
a15773db | 334 | $this->assertTrue($rc); |
6a488035 TO |
335 | } |
336 | ||
337 | /** | |
338 | * Test CRM_Member_Form_Membership::formRule() with a join date | |
339 | * of one month ago and a rolling membership type | |
340 | */ | |
00be9182 | 341 | public function testFormRuleRollingJoin1MonthAgo() { |
92915c55 | 342 | $unixNow = time(); |
6a488035 | 343 | $unix1MAgo = $unixNow - (31 * 24 * 60 * 60); |
9099cab3 | 344 | $params = [ |
8b408447 | 345 | 'join_date' => date('Y-m-d', $unix1MAgo), |
6a488035 TO |
346 | 'start_date' => '', |
347 | 'end_date' => '', | |
9099cab3 CW |
348 | 'membership_type_id' => ['23', '15'], |
349 | ]; | |
350 | $files = []; | |
a130e045 | 351 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 352 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 | 353 | |
41709813 EM |
354 | // Should have found New membership status. |
355 | $this->assertTrue($rc); | |
6a488035 TO |
356 | } |
357 | ||
358 | /** | |
41709813 | 359 | * Test CRM_Member_Form_Membership::formRule() with a join date of six months ago and a rolling membership type. |
6a488035 | 360 | */ |
00be9182 | 361 | public function testFormRuleRollingJoin6MonthsAgo() { |
92915c55 | 362 | $unixNow = time(); |
6a488035 | 363 | $unix6MAgo = $unixNow - (180 * 24 * 60 * 60); |
9099cab3 | 364 | $params = [ |
8b408447 | 365 | 'join_date' => date('Y-m-d', $unix6MAgo), |
6a488035 TO |
366 | 'start_date' => '', |
367 | 'end_date' => '', | |
9099cab3 CW |
368 | 'membership_type_id' => ['23', '15'], |
369 | ]; | |
370 | $files = []; | |
a130e045 | 371 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 372 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 | 373 | |
41709813 EM |
374 | // Should have found Current membership status. |
375 | $this->assertTrue($rc); | |
6a488035 TO |
376 | } |
377 | ||
378 | /** | |
379 | * Test CRM_Member_Form_Membership::formRule() with a join date | |
380 | * of one year+ ago and a rolling membership type | |
381 | */ | |
00be9182 | 382 | public function testFormRuleRollingJoin1YearAgo() { |
92915c55 | 383 | $unixNow = time(); |
6a488035 | 384 | $unix1YAgo = $unixNow - (370 * 24 * 60 * 60); |
9099cab3 | 385 | $params = [ |
8b408447 | 386 | 'join_date' => date('Y-m-d', $unix1YAgo), |
6a488035 TO |
387 | 'start_date' => '', |
388 | 'end_date' => '', | |
9099cab3 CW |
389 | 'membership_type_id' => ['23', '15'], |
390 | ]; | |
391 | $files = []; | |
a130e045 | 392 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 393 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 TO |
394 | |
395 | // Should have found Grace membership status | |
a15773db | 396 | $this->assertTrue($rc); |
6a488035 TO |
397 | } |
398 | ||
399 | /** | |
400 | * Test CRM_Member_Form_Membership::formRule() with a join date | |
401 | * of two years ago and a rolling membership type | |
402 | */ | |
00be9182 | 403 | public function testFormRuleRollingJoin2YearsAgo() { |
92915c55 | 404 | $unixNow = time(); |
6a488035 | 405 | $unix2YAgo = $unixNow - (2 * 365 * 24 * 60 * 60); |
9099cab3 | 406 | $params = [ |
8b408447 | 407 | 'join_date' => date('Y-m-d', $unix2YAgo), |
6a488035 TO |
408 | 'start_date' => '', |
409 | 'end_date' => '', | |
9099cab3 CW |
410 | 'membership_type_id' => ['23', '15'], |
411 | ]; | |
412 | $files = []; | |
a130e045 | 413 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 414 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 TO |
415 | |
416 | // Should have found Expired membership status | |
a15773db | 417 | $this->assertTrue($rc); |
6a488035 TO |
418 | } |
419 | ||
420 | /** | |
421 | * Test CRM_Member_Form_Membership::formRule() with a join date | |
422 | * of six months ago and a fixed membership type | |
423 | */ | |
00be9182 | 424 | public function testFormRuleFixedJoin6MonthsAgo() { |
92915c55 | 425 | $unixNow = time(); |
6a488035 | 426 | $unix6MAgo = $unixNow - (180 * 24 * 60 * 60); |
9099cab3 | 427 | $params = [ |
8b408447 | 428 | 'join_date' => date('Y-m-d', $unix6MAgo), |
6a488035 TO |
429 | 'start_date' => '', |
430 | 'end_date' => '', | |
9099cab3 CW |
431 | 'membership_type_id' => ['23', '7'], |
432 | ]; | |
433 | $files = []; | |
a130e045 | 434 | $obj = new CRM_Member_Form_Membership(); |
92915c55 | 435 | $rc = $obj->formRule($params, $files, $obj); |
6a488035 TO |
436 | |
437 | // Should have found Current membership status | |
cb447e7a | 438 | $this->assertTrue($rc); |
6a488035 | 439 | } |
96025800 | 440 | |
7865d848 EM |
441 | /** |
442 | * Test the submit function of the membership form. | |
f8df19bb | 443 | * |
444 | * @param string $thousandSeparator | |
445 | * | |
446 | * @dataProvider getThousandSeparators | |
7865d848 | 447 | */ |
f8df19bb | 448 | public function testSubmit($thousandSeparator) { |
6d5b9c63 | 449 | CRM_Core_Session::singleton()->getStatus(TRUE); |
f8df19bb | 450 | $this->setCurrencySeparators($thousandSeparator); |
08fd4b45 | 451 | $form = $this->getForm(); |
0dc4ef42 | 452 | $form->preProcess(); |
bbaa79ff | 453 | $this->mut = new CiviMailUtils($this, TRUE); |
08fd4b45 | 454 | $form->_mode = 'test'; |
c41bfe2b | 455 | $this->createLoggedInUser(); |
9099cab3 | 456 | $params = [ |
7865d848 | 457 | 'cid' => $this->_individualId, |
6d5b9c63 | 458 | 'join_date' => date('2/d/Y', time()), |
7865d848 EM |
459 | 'start_date' => '', |
460 | 'end_date' => '', | |
08fd4b45 | 461 | // This format reflects the 23 being the organisation & the 25 being the type. |
9099cab3 | 462 | 'membership_type_id' => [23, $this->membershipTypeAnnualFixedID], |
7865d848 EM |
463 | 'auto_renew' => '0', |
464 | 'max_related' => '', | |
465 | 'num_terms' => '1', | |
466 | 'source' => '', | |
f8df19bb | 467 | 'total_amount' => $this->formatMoneyInput(1234.56), |
39b959db SL |
468 | //Member dues, see data.xml |
469 | 'financial_type_id' => '2', | |
7865d848 EM |
470 | 'soft_credit_type_id' => '', |
471 | 'soft_credit_contact_id' => '', | |
472 | 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>', | |
7865d848 EM |
473 | 'payment_processor_id' => $this->_paymentProcessorID, |
474 | 'credit_card_number' => '4111111111111111', | |
475 | 'cvv2' => '123', | |
9099cab3 | 476 | 'credit_card_exp_date' => [ |
7865d848 | 477 | 'M' => '9', |
39b959db SL |
478 | // TODO: Future proof |
479 | 'Y' => '2024', | |
9099cab3 | 480 | ], |
41709813 EM |
481 | 'credit_card_type' => 'Visa', |
482 | 'billing_first_name' => 'Test', | |
483 | 'billing_middlename' => 'Last', | |
484 | 'billing_street_address-5' => '10 Test St', | |
485 | 'billing_city-5' => 'Test', | |
486 | 'billing_state_province_id-5' => '1003', | |
487 | 'billing_postal_code-5' => '90210', | |
488 | 'billing_country_id-5' => '1228', | |
bbaa79ff EM |
489 | 'send_receipt' => TRUE, |
490 | 'receipt_text' => 'Receipt text', | |
9099cab3 | 491 | ]; |
09108d7d | 492 | $form->_contactID = $this->_individualId; |
493 | $form->testSubmit($params); | |
9099cab3 CW |
494 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
495 | $this->callAPISuccessGetCount('ContributionRecur', ['contact_id' => $this->_individualId], 0); | |
496 | $contribution = $this->callAPISuccess('Contribution', 'get', [ | |
08fd4b45 EM |
497 | 'contact_id' => $this->_individualId, |
498 | 'is_test' => TRUE, | |
9099cab3 | 499 | ]); |
08fd4b45 | 500 | |
a7f2d5fd | 501 | //CRM-20264 : Check that CC type and number (last 4 digit) is stored during backoffice membership payment |
502 | $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC'); | |
503 | $financialTrxn = $this->callAPISuccessGetSingle( | |
504 | 'FinancialTrxn', | |
9099cab3 | 505 | [ |
a7f2d5fd | 506 | 'id' => $lastFinancialTrxnId['financialTrxnId'], |
9099cab3 CW |
507 | 'return' => ['card_type_id', 'pan_truncation'], |
508 | ] | |
a7f2d5fd | 509 | ); |
510 | $this->assertEquals(1, $financialTrxn['card_type_id']); | |
511 | $this->assertEquals(1111, $financialTrxn['pan_truncation']); | |
512 | ||
9099cab3 | 513 | $this->callAPISuccessGetCount('LineItem', [ |
08fd4b45 EM |
514 | 'entity_id' => $membership['id'], |
515 | 'entity_table' => 'civicrm_membership', | |
516 | 'contribution_id' => $contribution['id'], | |
9099cab3 | 517 | ], 1); |
1a1a2f4f | 518 | |
9099cab3 | 519 | $this->_checkFinancialRecords([ |
16f3bd02 | 520 | 'id' => $contribution['id'], |
f8df19bb | 521 | 'total_amount' => 1234.56, |
16f3bd02 | 522 | 'financial_account_id' => 2, |
9099cab3 | 523 | 'payment_instrument_id' => $this->callAPISuccessGetValue('PaymentProcessor', [ |
16f3bd02 | 524 | 'id' => $this->_paymentProcessorID, |
525 | 'return' => 'payment_instrument_id', | |
9099cab3 CW |
526 | ]), |
527 | ], 'online'); | |
528 | $this->mut->checkMailLog([ | |
f8df19bb | 529 | CRM_Utils_Money::format('1234.56'), |
bbaa79ff | 530 | 'Receipt text', |
9099cab3 | 531 | ]); |
bbaa79ff | 532 | $this->mut->stop(); |
6d5b9c63 | 533 | $this->assertEquals([ |
534 | [ | |
535 | 'text' => 'AnnualFixed membership for Mr. Anthony Anderson II has been added. The new membership End Date is December 31st, ' . date('Y') . '. A membership confirmation and receipt has been sent to anthony_anderson@civicrm.org.', | |
536 | 'title' => 'Complete', | |
537 | 'type' => 'success', | |
538 | 'options' => NULL, | |
539 | ], | |
540 | ], CRM_Core_Session::singleton()->getStatus()); | |
7865d848 EM |
541 | } |
542 | ||
268a84f2 | 543 | /** |
544 | * Test the submit function of the membership form on membership type change. | |
545 | * Check if the related contribuion is also updated if the minimum_fee didn't match | |
546 | */ | |
547 | public function testContributionUpdateOnMembershipTypeChange() { | |
548 | // Step 1: Create a Membership via backoffice whose with 50.00 payment | |
549 | $form = $this->getForm(); | |
550 | $form->preProcess(); | |
551 | $this->mut = new CiviMailUtils($this, TRUE); | |
552 | $this->createLoggedInUser(); | |
9099cab3 | 553 | $priceSet = $this->callAPISuccess('PriceSet', 'Get', ["extends" => "CiviMember"]); |
268a84f2 | 554 | $form->set('priceSetId', $priceSet['id']); |
555 | CRM_Price_BAO_PriceSet::buildPriceSet($form); | |
9099cab3 | 556 | $params = [ |
268a84f2 | 557 | 'cid' => $this->_individualId, |
8b408447 | 558 | 'join_date' => date('Y-m-d'), |
268a84f2 | 559 | 'start_date' => '', |
560 | 'end_date' => '', | |
561 | // This format reflects the 23 being the organisation & the 25 being the type. | |
9099cab3 | 562 | 'membership_type_id' => [23, $this->membershipTypeAnnualFixedID], |
268a84f2 | 563 | 'record_contribution' => 1, |
564 | 'total_amount' => 50, | |
553842be | 565 | 'receive_date' => date('Y-m-d', time()) . ' 20:36:00', |
268a84f2 | 566 | 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), |
567 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'), | |
39b959db SL |
568 | //Member dues, see data.xml |
569 | 'financial_type_id' => '2', | |
268a84f2 | 570 | 'payment_processor_id' => $this->_paymentProcessorID, |
9099cab3 | 571 | ]; |
268a84f2 | 572 | $form->_contactID = $this->_individualId; |
573 | $form->testSubmit($params); | |
9099cab3 | 574 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
268a84f2 | 575 | // check the membership status after partial payment, if its Pending |
576 | $this->assertEquals(array_search('New', CRM_Member_PseudoConstant::membershipStatus()), $membership['status_id']); | |
9099cab3 | 577 | $contribution = $this->callAPISuccessGetSingle('Contribution', [ |
268a84f2 | 578 | 'contact_id' => $this->_individualId, |
9099cab3 | 579 | ]); |
268a84f2 | 580 | $this->assertEquals('Completed', $contribution['contribution_status']); |
581 | $this->assertEquals(50.00, $contribution['total_amount']); | |
582 | $this->assertEquals(50.00, $contribution['net_amount']); | |
583 | ||
584 | // Step 2: Change the membership type whose minimum free is less than earlier membership | |
9099cab3 | 585 | $secondMembershipType = $this->callAPISuccess('membership_type', 'create', [ |
268a84f2 | 586 | 'domain_id' => 1, |
587 | 'name' => "Second Test Membership", | |
588 | 'member_of_contact_id' => 23, | |
589 | 'duration_unit' => "month", | |
590 | 'minimum_fee' => 25, | |
591 | 'duration_interval' => 1, | |
592 | 'period_type' => "fixed", | |
593 | 'fixed_period_start_day' => "101", | |
594 | 'fixed_period_rollover_day' => "1231", | |
595 | 'relationship_type_id' => 20, | |
596 | 'financial_type_id' => 2, | |
9099cab3 | 597 | ]); |
268a84f2 | 598 | Civi::settings()->set('update_contribution_on_membership_type_change', TRUE); |
599 | $form = $this->getForm(); | |
600 | $form->preProcess(); | |
601 | $form->_id = $membership['id']; | |
602 | $form->set('priceSetId', $priceSet['id']); | |
603 | CRM_Price_BAO_PriceSet::buildPriceSet($form); | |
604 | $form->_action = CRM_Core_Action::UPDATE; | |
9099cab3 | 605 | $params = [ |
268a84f2 | 606 | 'cid' => $this->_individualId, |
8b408447 | 607 | 'join_date' => date('Y-m-d'), |
268a84f2 | 608 | 'start_date' => '', |
609 | 'end_date' => '', | |
610 | // This format reflects the 23 being the organisation & the 25 being the type. | |
9099cab3 | 611 | 'membership_type_id' => [23, $secondMembershipType['id']], |
268a84f2 | 612 | 'record_contribution' => 1, |
613 | 'status_id' => 1, | |
614 | 'total_amount' => 25, | |
553842be | 615 | 'receive_date' => date('Y-m-d', time()) . ' 20:36:00', |
268a84f2 | 616 | 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), |
39b959db SL |
617 | //Member dues, see data.xml |
618 | 'financial_type_id' => '2', | |
268a84f2 | 619 | 'payment_processor_id' => $this->_paymentProcessorID, |
9099cab3 | 620 | ]; |
268a84f2 | 621 | $form->_contactID = $this->_individualId; |
622 | $form->testSubmit($params); | |
9099cab3 | 623 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
268a84f2 | 624 | // check the membership status after partial payment, if its Pending |
9099cab3 | 625 | $contribution = $this->callAPISuccessGetSingle('Contribution', [ |
268a84f2 | 626 | 'contact_id' => $this->_individualId, |
9099cab3 | 627 | ]); |
268a84f2 | 628 | $payment = CRM_Contribute_BAO_Contribution::getPaymentInfo($membership['id'], 'membership', FALSE, TRUE); |
629 | // Check the contribution status on membership type change whose minimum fee was less than earlier memebership | |
630 | $this->assertEquals('Pending refund', $contribution['contribution_status']); | |
631 | // Earlier paid amount | |
632 | $this->assertEquals(50, $payment['paid']); | |
633 | // balance remaning | |
634 | $this->assertEquals(-25, $payment['balance']); | |
635 | } | |
636 | ||
aec171f3 | 637 | /** |
638 | * Test the submit function of the membership form for partial payment. | |
83644f47 | 639 | * |
640 | * @param string $thousandSeparator | |
641 | * punctuation used to refer to thousands. | |
642 | * | |
643 | * @dataProvider getThousandSeparators | |
aec171f3 | 644 | */ |
83644f47 | 645 | public function testSubmitPartialPayment($thousandSeparator) { |
646 | $this->setCurrencySeparators($thousandSeparator); | |
aec171f3 | 647 | // Step 1: submit a partial payment for a membership via backoffice |
648 | $form = $this->getForm(); | |
649 | $form->preProcess(); | |
650 | $this->mut = new CiviMailUtils($this, TRUE); | |
651 | $this->createLoggedInUser(); | |
9099cab3 | 652 | $priceSet = $this->callAPISuccess('PriceSet', 'Get', ["extends" => "CiviMember"]); |
aec171f3 | 653 | $form->set('priceSetId', $priceSet['id']); |
654 | $partiallyPaidAmount = 25; | |
655 | CRM_Price_BAO_PriceSet::buildPriceSet($form); | |
9099cab3 | 656 | $params = [ |
aec171f3 | 657 | 'cid' => $this->_individualId, |
8b408447 | 658 | 'join_date' => date('Y-m-d'), |
aec171f3 | 659 | 'start_date' => '', |
660 | 'end_date' => '', | |
661 | // This format reflects the 23 being the organisation & the 25 being the type. | |
9099cab3 | 662 | 'membership_type_id' => [23, $this->membershipTypeAnnualFixedID], |
553842be | 663 | 'receive_date' => date('Y-m-d', time()) . ' 20:36:00', |
aec171f3 | 664 | 'record_contribution' => 1, |
83644f47 | 665 | 'total_amount' => $this->formatMoneyInput($partiallyPaidAmount), |
aec171f3 | 666 | 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), |
667 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Partially paid'), | |
39b959db SL |
668 | //Member dues, see data.xml |
669 | 'financial_type_id' => '2', | |
aec171f3 | 670 | 'payment_processor_id' => $this->_paymentProcessorID, |
9099cab3 | 671 | ]; |
aec171f3 | 672 | $form->_contactID = $this->_individualId; |
673 | $form->testSubmit($params); | |
9099cab3 | 674 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
aec171f3 | 675 | // check the membership status after partial payment, if its Pending |
676 | $this->assertEquals(array_search('Pending', CRM_Member_PseudoConstant::membershipStatus()), $membership['status_id']); | |
9099cab3 | 677 | $contribution = $this->callAPISuccessGetSingle('Contribution', [ |
aec171f3 | 678 | 'contact_id' => $this->_individualId, |
9099cab3 | 679 | ]); |
aec171f3 | 680 | $this->assertEquals('Partially paid', $contribution['contribution_status']); |
681 | // $this->assertEquals(50.00, $contribution['total_amount']); | |
682 | // $this->assertEquals(25.00, $contribution['net_amount']); | |
683 | ||
684 | // Step 2: submit the other half of the partial payment | |
685 | // via AdditionalPayment form to complete the related contribution | |
686 | $form = new CRM_Contribute_Form_AdditionalPayment(); | |
9099cab3 | 687 | $submitParams = [ |
aec171f3 | 688 | 'contribution_id' => $contribution['contribution_id'], |
689 | 'contact_id' => $this->_individualId, | |
83644f47 | 690 | 'total_amount' => $this->formatMoneyInput($partiallyPaidAmount), |
aec171f3 | 691 | 'currency' => 'USD', |
692 | 'financial_type_id' => 2, | |
553842be | 693 | 'receive_date' => '2015-04-21 23:27:00', |
aec171f3 | 694 | 'trxn_date' => '2017-04-11 13:05:11', |
695 | 'payment_processor_id' => 0, | |
696 | 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), | |
697 | 'check_number' => 'check-12345', | |
9099cab3 | 698 | ]; |
aec171f3 | 699 | $form->cid = $this->_individualId; |
700 | $form->testSubmit($submitParams); | |
9099cab3 | 701 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
aec171f3 | 702 | // check the membership status after additional payment, if its changed to 'New' |
703 | $this->assertEquals(array_search('New', CRM_Member_PseudoConstant::membershipStatus()), $membership['status_id']); | |
704 | ||
705 | // check the contribution status and net amount after additional payment | |
9099cab3 | 706 | $contribution = $this->callAPISuccessGetSingle('Contribution', [ |
aec171f3 | 707 | 'contact_id' => $this->_individualId, |
9099cab3 | 708 | ]); |
aec171f3 | 709 | $this->assertEquals('Completed', $contribution['contribution_status']); |
aec171f3 | 710 | // $this->assertEquals(50.00, $contribution['net_amount']); |
711 | } | |
712 | ||
a8215a8d EM |
713 | /** |
714 | * Test the submit function of the membership form. | |
715 | */ | |
716 | public function testSubmitRecur() { | |
c26225d2 | 717 | CRM_Core_Session::singleton()->getStatus(TRUE); |
9099cab3 | 718 | $pendingVal = $this->callAPISuccessGetValue('OptionValue', [ |
371e0262 JP |
719 | 'return' => "id", |
720 | 'option_group_id' => "contribution_status", | |
721 | 'label' => "Pending", | |
9099cab3 | 722 | ]); |
371e0262 | 723 | //Update label for Pending contribution status. |
9099cab3 | 724 | $this->callAPISuccess('OptionValue', 'create', [ |
371e0262 JP |
725 | 'id' => $pendingVal, |
726 | 'label' => "PendingEdited", | |
9099cab3 | 727 | ]); |
371e0262 | 728 | |
a8215a8d EM |
729 | $form = $this->getForm(); |
730 | ||
9099cab3 | 731 | $this->callAPISuccess('MembershipType', 'create', [ |
08fd4b45 | 732 | 'id' => $this->membershipTypeAnnualFixedID, |
a8215a8d EM |
733 | 'duration_unit' => 'month', |
734 | 'duration_interval' => 1, | |
735 | 'auto_renew' => TRUE, | |
9099cab3 | 736 | ]); |
a8215a8d EM |
737 | $form->preProcess(); |
738 | $this->createLoggedInUser(); | |
3cc61729 | 739 | $params = $this->getBaseSubmitParams(); |
740 | $form->_mode = 'test'; | |
09108d7d | 741 | $form->_contactID = $this->_individualId; |
742 | $form->testSubmit($params); | |
9099cab3 CW |
743 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
744 | $this->callAPISuccessGetCount('ContributionRecur', ['contact_id' => $this->_individualId], 1); | |
3cc61729 | 745 | |
9099cab3 | 746 | $contribution = $this->callAPISuccess('Contribution', 'get', [ |
3cc61729 | 747 | 'contact_id' => $this->_individualId, |
748 | 'is_test' => TRUE, | |
9099cab3 | 749 | ]); |
3cc61729 | 750 | |
371e0262 | 751 | //Check if Membership Payment is recorded. |
9099cab3 | 752 | $this->callAPISuccessGetCount('MembershipPayment', [ |
371e0262 JP |
753 | 'membership_id' => $membership['id'], |
754 | 'contribution_id' => $contribution['id'], | |
9099cab3 | 755 | ], 1); |
371e0262 | 756 | |
3cc61729 | 757 | // CRM-16992. |
9099cab3 | 758 | $this->callAPISuccessGetCount('LineItem', [ |
3cc61729 | 759 | 'entity_id' => $membership['id'], |
760 | 'entity_table' => 'civicrm_membership', | |
761 | 'contribution_id' => $contribution['id'], | |
9099cab3 | 762 | ], 1); |
c26225d2 MWMC |
763 | $this->assertEquals([ |
764 | [ | |
765 | 'text' => 'AnnualFixed membership for Mr. Anthony Anderson II has been added. The new membership End Date is ' . date('F jS, Y', strtotime('last day of this month')) . ' 12:00 AM.', | |
766 | 'title' => 'Complete', | |
767 | 'type' => 'success', | |
768 | 'options' => NULL, | |
769 | ], | |
770 | ], CRM_Core_Session::singleton()->getStatus()); | |
3cc61729 | 771 | } |
772 | ||
e2ce0d88 | 773 | /** |
774 | * CRM-20946: Test the financial entires especially the reversed amount, | |
775 | * after related Contribution is cancelled | |
776 | */ | |
777 | public function testFinancialEntiriesOnCancelledContribution() { | |
b7e2e1b0 DJ |
778 | // Create two memberships for individual $this->_individualId, via a price set in the back end. |
779 | $this->createTwoMembershipsViaPriceSetInBackEnd($this->_individualId); | |
e2ce0d88 | 780 | |
781 | // cancel the related contribution via API | |
9099cab3 | 782 | $contribution = $this->callAPISuccessGetSingle('Contribution', [ |
e2ce0d88 | 783 | 'contact_id' => $this->_individualId, |
784 | 'contribution_status_id' => 2, | |
9099cab3 CW |
785 | ]); |
786 | $this->callAPISuccess('Contribution', 'create', [ | |
e2ce0d88 | 787 | 'id' => $contribution['id'], |
788 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_DAO_Contribution', 'contribution_status_id', 'Cancelled'), | |
9099cab3 | 789 | ]); |
e2ce0d88 | 790 | |
791 | // fetch financial_trxn ID of the related contribution | |
792 | $sql = "SELECT financial_trxn_id | |
793 | FROM civicrm_entity_financial_trxn | |
794 | WHERE entity_id = %1 AND entity_table = 'civicrm_contribution' | |
795 | ORDER BY id DESC | |
796 | LIMIT 1 | |
797 | "; | |
9099cab3 | 798 | $financialTrxnID = CRM_Core_DAO::singleValueQuery($sql, [1 => [$contribution['id'], 'Int']]); |
e2ce0d88 | 799 | |
800 | // fetch entity_financial_trxn records and compare their cancelled records | |
9099cab3 | 801 | $result = $this->callAPISuccess('EntityFinancialTrxn', 'Get', [ |
e2ce0d88 | 802 | 'financial_trxn_id' => $financialTrxnID, |
803 | 'entity_table' => 'civicrm_financial_item', | |
9099cab3 | 804 | ]); |
e2ce0d88 | 805 | // compare the reversed amounts of respective memberships after cancelling contribution |
9099cab3 | 806 | $cancelledMembershipAmounts = [ |
e2ce0d88 | 807 | -20.00, |
808 | -10.00, | |
9099cab3 | 809 | ]; |
e2ce0d88 | 810 | $count = 0; |
811 | foreach ($result['values'] as $record) { | |
812 | $this->assertEquals($cancelledMembershipAmounts[$count], $record['amount']); | |
813 | $count++; | |
814 | } | |
815 | } | |
816 | ||
09108d7d | 817 | /** |
818 | * Test the submit function of the membership form. | |
819 | */ | |
820 | public function testSubmitPayLaterWithBilling() { | |
821 | $form = $this->getForm(NULL); | |
0dc4ef42 | 822 | $form->preProcess(); |
09108d7d | 823 | $this->createLoggedInUser(); |
9099cab3 | 824 | $params = [ |
09108d7d | 825 | 'cid' => $this->_individualId, |
8b408447 | 826 | 'join_date' => date('Y-m-d'), |
09108d7d | 827 | 'start_date' => '', |
828 | 'end_date' => '', | |
829 | // This format reflects the 23 being the organisation & the 25 being the type. | |
9099cab3 | 830 | 'membership_type_id' => [23, $this->membershipTypeAnnualFixedID], |
09108d7d | 831 | 'auto_renew' => '0', |
832 | 'max_related' => '', | |
833 | 'num_terms' => '2', | |
834 | 'source' => '', | |
835 | 'total_amount' => '50.00', | |
836 | //Member dues, see data.xml | |
837 | 'financial_type_id' => '2', | |
838 | 'soft_credit_type_id' => '', | |
839 | 'soft_credit_contact_id' => '', | |
840 | 'payment_instrument_id' => 4, | |
841 | 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>', | |
842 | 'receipt_text_signup' => 'Thank you text', | |
843 | 'payment_processor_id' => $this->_paymentProcessorID, | |
844 | 'record_contribution' => TRUE, | |
845 | 'trxn_id' => 777, | |
846 | 'contribution_status_id' => 2, | |
847 | 'billing_first_name' => 'Test', | |
848 | 'billing_middlename' => 'Last', | |
849 | 'billing_street_address-5' => '10 Test St', | |
850 | 'billing_city-5' => 'Test', | |
851 | 'billing_state_province_id-5' => '1003', | |
852 | 'billing_postal_code-5' => '90210', | |
853 | 'billing_country_id-5' => '1228', | |
9099cab3 | 854 | ]; |
09108d7d | 855 | $form->_contactID = $this->_individualId; |
856 | ||
857 | $form->testSubmit($params); | |
9099cab3 CW |
858 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
859 | $contribution = $this->callAPISuccessGetSingle('Contribution', [ | |
09108d7d | 860 | 'contact_id' => $this->_individualId, |
861 | 'contribution_status_id' => 2, | |
9099cab3 | 862 | ]); |
09108d7d | 863 | $this->assertEquals($contribution['trxn_id'], 777); |
864 | ||
9099cab3 | 865 | $this->callAPISuccessGetCount('LineItem', [ |
09108d7d | 866 | 'entity_id' => $membership['id'], |
867 | 'entity_table' => 'civicrm_membership', | |
868 | 'contribution_id' => $contribution['id'], | |
9099cab3 CW |
869 | ], 1); |
870 | $this->callAPISuccessGetSingle('address', [ | |
09108d7d | 871 | 'contact_id' => $this->_individualId, |
872 | 'street_address' => '10 Test St', | |
873 | 'postal_code' => 90210, | |
9099cab3 | 874 | ]); |
09108d7d | 875 | } |
876 | ||
494fdf05 JP |
877 | /** |
878 | * Test if membership is updated to New after contribution | |
879 | * is updated from Partially paid to Completed. | |
880 | */ | |
881 | public function testSubmitUpdateMembershipFromPartiallyPaid() { | |
882 | $memStatus = CRM_Member_BAO_Membership::buildOptions('status_id', 'validate'); | |
883 | ||
884 | //Perform a pay later membership contribution. | |
885 | $this->testSubmitPayLaterWithBilling(); | |
9099cab3 | 886 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
494fdf05 | 887 | $this->assertEquals($membership['status_id'], array_search('Pending', $memStatus)); |
9099cab3 | 888 | $contribution = $this->callAPISuccessGetSingle('MembershipPayment', [ |
494fdf05 | 889 | 'membership_id' => $membership['id'], |
9099cab3 | 890 | ]); |
494fdf05 JP |
891 | |
892 | //Update contribution to Partially paid. | |
9099cab3 | 893 | $prevContribution = $this->callAPISuccess('Contribution', 'create', [ |
494fdf05 | 894 | 'id' => $contribution['contribution_id'], |
1e9b7f9f | 895 | 'contribution_status_id' => 'Partially paid', |
9099cab3 | 896 | ]); |
494fdf05 JP |
897 | $prevContribution = $prevContribution['values'][1]; |
898 | ||
899 | //Complete the contribution from offline form. | |
900 | $form = new CRM_Contribute_Form_Contribution(); | |
9099cab3 | 901 | $submitParams = [ |
494fdf05 | 902 | 'id' => $contribution['contribution_id'], |
1e9b7f9f | 903 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'), |
494fdf05 | 904 | 'price_set_id' => 0, |
9099cab3 CW |
905 | ]; |
906 | $fields = ['total_amount', 'net_amount', 'financial_type_id', 'receive_date', 'contact_id', 'payment_instrument_id']; | |
494fdf05 JP |
907 | foreach ($fields as $val) { |
908 | $submitParams[$val] = $prevContribution[$val]; | |
909 | } | |
910 | $form->testSubmit($submitParams, CRM_Core_Action::UPDATE); | |
911 | ||
912 | //Check if Membership is updated to New. | |
9099cab3 | 913 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
494fdf05 JP |
914 | $this->assertEquals($membership['status_id'], array_search('New', $memStatus)); |
915 | } | |
916 | ||
bf6ba9fc | 917 | /** |
918 | * Test the submit function of the membership form. | |
919 | */ | |
920 | public function testSubmitRecurCompleteInstant() { | |
921 | $form = $this->getForm(); | |
e9dfe40a | 922 | $mut = new CiviMailUtils($this, TRUE); |
bf6ba9fc | 923 | $processor = Civi\Payment\System::singleton()->getById($this->_paymentProcessorID); |
9099cab3 | 924 | $processor->setDoDirectPaymentResult([ |
77623a96 | 925 | 'payment_status_id' => 1, |
926 | 'trxn_id' => 'kettles boil water', | |
927 | 'fee_amount' => .14, | |
9099cab3 | 928 | ]); |
204efedd | 929 | $processorDetail = $processor->getPaymentProcessor(); |
9099cab3 | 930 | $this->callAPISuccess('MembershipType', 'create', [ |
bf6ba9fc | 931 | 'id' => $this->membershipTypeAnnualFixedID, |
932 | 'duration_unit' => 'month', | |
933 | 'duration_interval' => 1, | |
934 | 'auto_renew' => TRUE, | |
9099cab3 | 935 | ]); |
bf6ba9fc | 936 | $form->preProcess(); |
937 | $this->createLoggedInUser(); | |
938 | $params = $this->getBaseSubmitParams(); | |
939 | $form->_mode = 'test'; | |
09108d7d | 940 | $form->_contactID = $this->_individualId; |
941 | $form->testSubmit($params); | |
9099cab3 CW |
942 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
943 | $this->callAPISuccessGetCount('ContributionRecur', ['contact_id' => $this->_individualId], 1); | |
bf6ba9fc | 944 | |
9099cab3 | 945 | $contribution = $this->callAPISuccess('Contribution', 'getsingle', [ |
bf6ba9fc | 946 | 'contact_id' => $this->_individualId, |
947 | 'is_test' => TRUE, | |
9099cab3 | 948 | ]); |
bf6ba9fc | 949 | |
77623a96 | 950 | $this->assertEquals(.14, $contribution['fee_amount']); |
951 | $this->assertEquals('kettles boil water', $contribution['trxn_id']); | |
204efedd | 952 | $this->assertEquals($processorDetail['payment_instrument_id'], $contribution['payment_instrument_id']); |
77623a96 | 953 | |
9099cab3 | 954 | $this->callAPISuccessGetCount('LineItem', [ |
bf6ba9fc | 955 | 'entity_id' => $membership['id'], |
956 | 'entity_table' => 'civicrm_membership', | |
957 | 'contribution_id' => $contribution['id'], | |
9099cab3 CW |
958 | ], 1); |
959 | $mut->checkMailLog([ | |
39b959db | 960 | '=========================================================== |
e9dfe40a | 961 | Billing Name and Address |
962 | =========================================================== | |
963 | Test | |
964 | 10 Test St | |
965 | Test, AR 90210 | |
966 | US', | |
39b959db | 967 | '=========================================================== |
e9dfe40a | 968 | Membership Information |
969 | =========================================================== | |
970 | Membership Type: AnnualFixed | |
971 | Membership Start Date: ', | |
39b959db | 972 | '=========================================================== |
e9dfe40a | 973 | Credit Card Information |
974 | =========================================================== | |
975 | Visa | |
976 | ************1111 | |
977 | Expires: ', | |
9099cab3 | 978 | ]); |
e9dfe40a | 979 | $mut->stop(); |
bf6ba9fc | 980 | |
981 | } | |
982 | ||
1da0f2ec JP |
983 | /** |
984 | * Test membership form with Failed Contribution. | |
985 | */ | |
986 | public function testFormWithFailedContribution() { | |
987 | $form = $this->getForm(); | |
0dc4ef42 | 988 | $form->preProcess(); |
1da0f2ec JP |
989 | $this->createLoggedInUser(); |
990 | $params = $this->getBaseSubmitParams(); | |
991 | unset($params['price_set_id']); | |
992 | unset($params['credit_card_number']); | |
993 | unset($params['cvv2']); | |
994 | unset($params['credit_card_exp_date']); | |
995 | unset($params['credit_card_type']); | |
996 | unset($params['send_receipt']); | |
997 | unset($params['is_recur']); | |
998 | ||
999 | $params['record_contribution'] = TRUE; | |
1000 | $params['contribution_status_id'] = array_search('Failed', CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name')); | |
1001 | $form->_mode = NULL; | |
1002 | $form->_contactID = $this->_individualId; | |
1003 | ||
1004 | $form->testSubmit($params); | |
9099cab3 | 1005 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
1da0f2ec | 1006 | $form->testSubmit($params); |
9099cab3 | 1007 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
1da0f2ec JP |
1008 | $this->assertEquals($membership['status_id'], array_search('Pending', CRM_Member_PseudoConstant::membershipStatus())); |
1009 | } | |
1010 | ||
b7e2e1b0 DJ |
1011 | /** |
1012 | * CRM-20955, CRM-20966: | |
1013 | * Test creating two memberships with inheritance via price set in the back end, | |
1014 | * checking that the correct primary & secondary memberships, contributions, line items | |
1015 | * & membership_payment records are created. | |
1016 | * Uses some data from tests/phpunit/CRM/Member/Form/dataset/data.xml . | |
1017 | */ | |
1018 | public function testTwoInheritedMembershipsViaPriceSetInBackend() { | |
1019 | // Create an organization and give it a "Member of" relationship to $this->_individualId. | |
74b3a175 | 1020 | $orgID = $this->organizationCreate(); |
9099cab3 | 1021 | $relationship = $this->callAPISuccess('relationship', 'create', [ |
b7e2e1b0 | 1022 | 'contact_id_a' => $this->_individualId, |
74b3a175 | 1023 | 'contact_id_b' => $orgID, |
b7e2e1b0 DJ |
1024 | 'relationship_type_id' => 20, |
1025 | 'is_active' => 1, | |
9099cab3 | 1026 | ]); |
b7e2e1b0 DJ |
1027 | |
1028 | // Create two memberships for the organization, via a price set in the back end. | |
74b3a175 | 1029 | $this->createTwoMembershipsViaPriceSetInBackEnd($orgID); |
b7e2e1b0 DJ |
1030 | |
1031 | // Check the primary memberships on the organization. | |
9099cab3 | 1032 | $orgMembershipResult = $this->callAPISuccess('membership', 'get', [ |
74b3a175 | 1033 | 'contact_id' => $orgID, |
9099cab3 | 1034 | ]); |
b7e2e1b0 | 1035 | $this->assertEquals(2, $orgMembershipResult['count'], "2 primary memberships should have been created on the organization."); |
9099cab3 | 1036 | $primaryMembershipIds = []; |
b7e2e1b0 DJ |
1037 | foreach ($orgMembershipResult['values'] as $membership) { |
1038 | $primaryMembershipIds[] = $membership['id']; | |
1039 | $this->assertTrue(empty($membership['owner_membership_id']), "Membership on the organization has owner_membership_id so is inherited."); | |
1040 | } | |
1041 | ||
1042 | // CRM-20955: check that correct inherited memberships were created for the individual, | |
1043 | // for both of the primary memberships. | |
9099cab3 | 1044 | $individualMembershipResult = $this->callAPISuccess('membership', 'get', [ |
b7e2e1b0 | 1045 | 'contact_id' => $this->_individualId, |
9099cab3 | 1046 | ]); |
b7e2e1b0 DJ |
1047 | $this->assertEquals(2, $individualMembershipResult['count'], "2 inherited memberships should have been created on the individual."); |
1048 | foreach ($individualMembershipResult['values'] as $membership) { | |
1049 | $this->assertNotEmpty($membership['owner_membership_id'], "Membership on the individual lacks owner_membership_id so is not inherited."); | |
1050 | $this->assertNotContains($membership['id'], $primaryMembershipIds, "Inherited membership id should not be the id of a primary membership."); | |
1051 | $this->assertContains($membership['owner_membership_id'], $primaryMembershipIds, "Inherited membership owner_membership_id should be the id of a primary membership."); | |
1052 | } | |
1053 | ||
1054 | // CRM-20966: check that the correct membership contribution, line items | |
1055 | // & membership_payment records were created for the organization. | |
9099cab3 | 1056 | $contributionResult = $this->callAPISuccess('contribution', 'get', [ |
74b3a175 | 1057 | 'contact_id' => $orgID, |
b7e2e1b0 | 1058 | 'sequential' => 1, |
9099cab3 CW |
1059 | 'api.line_item.get' => [], |
1060 | 'api.membership_payment.get' => [], | |
1061 | ]); | |
b7e2e1b0 DJ |
1062 | $this->assertEquals(1, $contributionResult['count'], "One contribution should have been created for the organization's memberships."); |
1063 | ||
74b3a175 | 1064 | $this->assertEquals(2, $contributionResult['values'][0]['api.line_item.get']['count'], "2 line items should have been created for the organization's memberships."); |
b7e2e1b0 | 1065 | foreach ($contributionResult['values'][0]['api.line_item.get']['values'] as $lineItem) { |
74b3a175 DJ |
1066 | $this->assertEquals('civicrm_membership', $lineItem['entity_table'], "Membership line item's entity_table should be 'civicrm_membership'."); |
1067 | $this->assertContains($lineItem['entity_id'], $primaryMembershipIds, "Membership line item's entity_id should be the id of a primary membership."); | |
b7e2e1b0 DJ |
1068 | } |
1069 | ||
74b3a175 | 1070 | $this->assertEquals(2, $contributionResult['values'][0]['api.membership_payment.get']['count'], "2 membership payment records should have been created for the organization's memberships."); |
b7e2e1b0 | 1071 | foreach ($contributionResult['values'][0]['api.membership_payment.get']['values'] as $membershipPayment) { |
74b3a175 DJ |
1072 | $this->assertEquals($contributionResult['values'][0]['id'], $membershipPayment['contribution_id'], "membership payment's contribution ID should be the ID of the organization's membership contribution."); |
1073 | $this->assertContains($membershipPayment['membership_id'], $primaryMembershipIds, "membership payment's membership ID should be the ID of a primary membership."); | |
b7e2e1b0 DJ |
1074 | } |
1075 | ||
1076 | // CRM-20966: check that deleting relationship used for inheritance does not delete contribution. | |
9099cab3 | 1077 | $this->callAPISuccess('relationship', 'delete', [ |
b7e2e1b0 | 1078 | 'id' => $relationship['id'], |
9099cab3 | 1079 | ]); |
b7e2e1b0 | 1080 | |
9099cab3 | 1081 | $contributionResultAfterRelationshipDelete = $this->callAPISuccess('contribution', 'get', [ |
b7e2e1b0 | 1082 | 'id' => $contributionResult['values'][0]['id'], |
74b3a175 | 1083 | 'contact_id' => $orgID, |
9099cab3 | 1084 | ]); |
b7e2e1b0 DJ |
1085 | $this->assertEquals(1, $contributionResultAfterRelationshipDelete['count'], "Contribution has been wrongly deleted."); |
1086 | } | |
1087 | ||
3cc61729 | 1088 | /** |
1089 | * Get a membership form object. | |
1090 | * | |
1091 | * We need to instantiate the form to run preprocess, which means we have to trick it about the request method. | |
1092 | * | |
1093 | * @return \CRM_Member_Form_Membership | |
1094 | */ | |
1095 | protected function getForm() { | |
b0104807 | 1096 | if (isset($_REQUEST['cid'])) { |
1097 | unset($_REQUEST['cid']); | |
1098 | } | |
3cc61729 | 1099 | $form = new CRM_Member_Form_Membership(); |
1100 | $_SERVER['REQUEST_METHOD'] = 'GET'; | |
1101 | $form->controller = new CRM_Core_Controller(); | |
3cc61729 | 1102 | return $form; |
1103 | } | |
1104 | ||
1105 | /** | |
1106 | * @return array | |
1107 | */ | |
1108 | protected function getBaseSubmitParams() { | |
9099cab3 | 1109 | $params = [ |
a8215a8d EM |
1110 | 'cid' => $this->_individualId, |
1111 | 'price_set_id' => 0, | |
8b408447 | 1112 | 'join_date' => date('Y-m-d'), |
a8215a8d EM |
1113 | 'start_date' => '', |
1114 | 'end_date' => '', | |
1115 | 'campaign_id' => '', | |
08fd4b45 | 1116 | // This format reflects the 23 being the organisation & the 25 being the type. |
9099cab3 | 1117 | 'membership_type_id' => [23, $this->membershipTypeAnnualFixedID], |
a8215a8d EM |
1118 | 'auto_renew' => '1', |
1119 | 'is_recur' => 1, | |
1120 | 'max_related' => 0, | |
1121 | 'num_terms' => '1', | |
1122 | 'source' => '', | |
1123 | 'total_amount' => '77.00', | |
39b959db SL |
1124 | //Member dues, see data.xml |
1125 | 'financial_type_id' => '2', | |
a8215a8d EM |
1126 | 'soft_credit_type_id' => 11, |
1127 | 'soft_credit_contact_id' => '', | |
1128 | 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>', | |
1129 | 'receipt_text' => 'Thank you text', | |
1130 | 'payment_processor_id' => $this->_paymentProcessorID, | |
1131 | 'credit_card_number' => '4111111111111111', | |
1132 | 'cvv2' => '123', | |
9099cab3 | 1133 | 'credit_card_exp_date' => [ |
a8215a8d | 1134 | 'M' => '9', |
39b959db SL |
1135 | // TODO: Future proof |
1136 | 'Y' => '2019', | |
9099cab3 | 1137 | ], |
a8215a8d EM |
1138 | 'credit_card_type' => 'Visa', |
1139 | 'billing_first_name' => 'Test', | |
1140 | 'billing_middlename' => 'Last', | |
1141 | 'billing_street_address-5' => '10 Test St', | |
1142 | 'billing_city-5' => 'Test', | |
1143 | 'billing_state_province_id-5' => '1003', | |
1144 | 'billing_postal_code-5' => '90210', | |
1145 | 'billing_country_id-5' => '1228', | |
e9dfe40a | 1146 | 'send_receipt' => 1, |
9099cab3 | 1147 | ]; |
3cc61729 | 1148 | return $params; |
a8215a8d | 1149 | } |
a271822c | 1150 | |
b7e2e1b0 DJ |
1151 | /** |
1152 | * Scenario builder: | |
1153 | * create two memberships for the same individual, via a price set in the back end. | |
1154 | * | |
1155 | * @param int $contactId Id of contact on which the memberships will be created. | |
1156 | */ | |
1157 | protected function createTwoMembershipsViaPriceSetInBackEnd($contactId) { | |
1158 | $form = $this->getForm(NULL); | |
1159 | $form->preProcess(); | |
1160 | $this->createLoggedInUser(); | |
1161 | ||
1162 | // create a price-set of price-field of type checkbox and each price-option corresponds to a membership type | |
9099cab3 | 1163 | $priceSet = $this->callAPISuccess('price_set', 'create', [ |
b7e2e1b0 DJ |
1164 | 'is_quick_config' => 0, |
1165 | 'extends' => 'CiviMember', | |
1166 | 'financial_type_id' => 1, | |
1167 | 'title' => 'my Page', | |
9099cab3 | 1168 | ]); |
b7e2e1b0 DJ |
1169 | $priceSetID = $priceSet['id']; |
1170 | // create respective checkbox price-field | |
9099cab3 | 1171 | $priceField = $this->callAPISuccess('price_field', 'create', [ |
b7e2e1b0 DJ |
1172 | 'price_set_id' => $priceSetID, |
1173 | 'label' => 'Memberships', | |
1174 | 'html_type' => 'Checkbox', | |
9099cab3 | 1175 | ]); |
b7e2e1b0 DJ |
1176 | $priceFieldID = $priceField['id']; |
1177 | // create two price options, each represent a membership type of amount 20 and 10 respectively | |
9099cab3 | 1178 | $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', [ |
39b959db SL |
1179 | 'price_set_id' => $priceSetID, |
1180 | 'price_field_id' => $priceField['id'], | |
1181 | 'label' => 'Long Haired Goat', | |
1182 | 'amount' => 20, | |
1183 | 'financial_type_id' => 'Donation', | |
1184 | 'membership_type_id' => 15, | |
1185 | 'membership_num_terms' => 1, | |
9099cab3 CW |
1186 | ]); |
1187 | $pfvIDs = [$priceFieldValue['id'] => 1]; | |
1188 | $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', [ | |
39b959db SL |
1189 | 'price_set_id' => $priceSetID, |
1190 | 'price_field_id' => $priceField['id'], | |
1191 | 'label' => 'Shoe-eating Goat', | |
1192 | 'amount' => 10, | |
1193 | 'financial_type_id' => 'Donation', | |
1194 | 'membership_type_id' => 35, | |
1195 | 'membership_num_terms' => 2, | |
9099cab3 | 1196 | ]); |
b7e2e1b0 DJ |
1197 | $pfvIDs[$priceFieldValue['id']] = 1; |
1198 | ||
1199 | // register for both of these memberships via backoffice membership form submission | |
9099cab3 | 1200 | $params = [ |
b7e2e1b0 | 1201 | 'cid' => $contactId, |
8b408447 | 1202 | 'join_date' => date('Y-m-d'), |
b7e2e1b0 DJ |
1203 | 'start_date' => '', |
1204 | 'end_date' => '', | |
1205 | // This format reflects the 23 being the organisation & the 25 being the type. | |
1206 | "price_$priceFieldID" => $pfvIDs, | |
1207 | "price_set_id" => $priceSetID, | |
9099cab3 | 1208 | 'membership_type_id' => [1 => 0], |
b7e2e1b0 DJ |
1209 | 'auto_renew' => '0', |
1210 | 'max_related' => '', | |
1211 | 'num_terms' => '2', | |
1212 | 'source' => '', | |
1213 | 'total_amount' => '30.00', | |
1214 | //Member dues, see data.xml | |
1215 | 'financial_type_id' => '2', | |
1216 | 'soft_credit_type_id' => '', | |
1217 | 'soft_credit_contact_id' => '', | |
1218 | 'payment_instrument_id' => 4, | |
1219 | 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>', | |
1220 | 'receipt_text_signup' => 'Thank you text', | |
1221 | 'payment_processor_id' => $this->_paymentProcessorID, | |
1222 | 'record_contribution' => TRUE, | |
1223 | 'trxn_id' => 777, | |
1224 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_DAO_Contribution', 'contribution_status_id', 'Pending'), | |
1225 | 'billing_first_name' => 'Test', | |
1226 | 'billing_middlename' => 'Last', | |
1227 | 'billing_street_address-5' => '10 Test St', | |
1228 | 'billing_city-5' => 'Test', | |
1229 | 'billing_state_province_id-5' => '1003', | |
1230 | 'billing_postal_code-5' => '90210', | |
1231 | 'billing_country_id-5' => '1228', | |
9099cab3 | 1232 | ]; |
b7e2e1b0 DJ |
1233 | $form->testSubmit($params); |
1234 | } | |
1235 | ||
de5b5c6c JP |
1236 | /** |
1237 | * Test membership status overrides when contribution is cancelled. | |
1238 | */ | |
1239 | public function testContributionFormStatusUpdate() { | |
1240 | $form = new CRM_Contribute_Form_Contribution(); | |
1241 | ||
1242 | //Create a membership with status = 'New'. | |
1243 | $this->_individualId = $this->createLoggedInUser(); | |
9099cab3 | 1244 | $memParams = [ |
de5b5c6c JP |
1245 | 'contact_id' => $this->_individualId, |
1246 | 'membership_type_id' => $this->membershipTypeAnnualFixedID, | |
1247 | 'status_id' => array_search('New', CRM_Member_PseudoConstant::membershipStatus()), | |
9099cab3 CW |
1248 | ]; |
1249 | $cancelledStatusId = $this->callAPISuccessGetValue('OptionValue', [ | |
de5b5c6c JP |
1250 | 'return' => "value", |
1251 | 'option_group_id' => "contribution_status", | |
1252 | 'name' => "Cancelled", | |
9099cab3 CW |
1253 | ]); |
1254 | $params = [ | |
de5b5c6c JP |
1255 | 'total_amount' => 50, |
1256 | 'financial_type_id' => 2, | |
1257 | 'contact_id' => $this->_individualId, | |
1258 | 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), | |
1259 | 'contribution_status_id' => $cancelledStatusId, | |
9099cab3 | 1260 | ]; |
de5b5c6c JP |
1261 | $membershipId = $this->contactMembershipCreate($memParams); |
1262 | ||
9099cab3 | 1263 | $contriParams = [ |
de5b5c6c JP |
1264 | 'membership_id' => $membershipId, |
1265 | 'total_amount' => 50, | |
1266 | 'financial_type_id' => 2, | |
1267 | 'contact_id' => $this->_individualId, | |
9099cab3 | 1268 | ]; |
de5b5c6c JP |
1269 | $contribution = CRM_Member_BAO_Membership::recordMembershipContribution($contriParams); |
1270 | ||
1271 | //Update Contribution to Cancelled. | |
1272 | $form->_id = $params['id'] = $contribution->id; | |
1273 | $form->_mode = NULL; | |
1274 | $form->_contactID = $this->_individualId; | |
1275 | $form->testSubmit($params, CRM_Core_Action::UPDATE); | |
9099cab3 | 1276 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
de5b5c6c JP |
1277 | |
1278 | //Assert membership status overrides when the contribution cancelled. | |
1279 | $this->assertEquals($membership['is_override'], TRUE); | |
9099cab3 | 1280 | $this->assertEquals($membership['status_id'], $this->callAPISuccessGetValue('MembershipStatus', [ |
de5b5c6c JP |
1281 | 'return' => "id", |
1282 | 'name' => "Cancelled", | |
9099cab3 | 1283 | ])); |
de5b5c6c JP |
1284 | } |
1285 | ||
f436577a | 1286 | /** |
ddfe1cb1 K |
1287 | * CRM-21656: Test the submit function of the membership form if Sales Tax is enabled. |
1288 | * This test simulates what happens when one hits Edit on a Contribution that has both LineItems and Sales Tax components | |
1289 | * Without making any Edits -> check that the LineItem data remain the same | |
1290 | * In addition (a data-integrity check) -> check that the LineItem data add up to the data at the Contribution level | |
f436577a | 1291 | */ |
ddfe1cb1 | 1292 | public function testLineItemAmountOnSalesTax() { |
f436577a | 1293 | $this->enableTaxAndInvoicing(); |
1294 | $this->relationForFinancialTypeWithFinancialAccount(2); | |
1295 | $form = $this->getForm(); | |
1296 | $form->preProcess(); | |
1297 | $this->mut = new CiviMailUtils($this, TRUE); | |
1298 | $this->createLoggedInUser(); | |
9099cab3 | 1299 | $priceSet = $this->callAPISuccess('PriceSet', 'Get', ["extends" => "CiviMember"]); |
f436577a | 1300 | $form->set('priceSetId', $priceSet['id']); |
dcdfd53d | 1301 | // we are simulating the creation of a Price Set in Administer -> CiviContribute -> Manage Price Sets so set is_quick_config = 0 |
9099cab3 | 1302 | $this->callAPISuccess('PriceSet', 'Create', ["id" => $priceSet['id'], 'is_quick_config' => 0]); |
f436577a | 1303 | // clean the price options static variable to repopulate the options, in order to fetch tax information |
1304 | \Civi::$statics['CRM_Price_BAO_PriceField']['priceOptions'] = NULL; | |
1305 | CRM_Price_BAO_PriceSet::buildPriceSet($form); | |
1306 | // rebuild the price set form variable to include the tax information against each price options | |
1307 | $form->_priceSet = current(CRM_Price_BAO_PriceSet::getSetDetail($priceSet['id'])); | |
9099cab3 | 1308 | $params = [ |
f436577a | 1309 | 'cid' => $this->_individualId, |
8b408447 | 1310 | 'join_date' => date('Y-m-d'), |
f436577a | 1311 | 'start_date' => '', |
1312 | 'end_date' => '', | |
1313 | // This format reflects the 23 being the organisation & the 25 being the type. | |
9099cab3 | 1314 | 'membership_type_id' => [23, $this->membershipTypeAnnualFixedID], |
f436577a | 1315 | 'record_contribution' => 1, |
1316 | 'total_amount' => 55, | |
553842be | 1317 | 'receive_date' => date('Y-m-d', time()) . ' 20:36:00', |
f436577a | 1318 | 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), |
1319 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'), | |
39b959db SL |
1320 | //Member dues, see data.xml |
1321 | 'financial_type_id' => 2, | |
f436577a | 1322 | 'payment_processor_id' => $this->_paymentProcessorID, |
9099cab3 | 1323 | ]; |
f436577a | 1324 | $form->_contactID = $this->_individualId; |
1325 | $form->testSubmit($params); | |
1326 | ||
9099cab3 CW |
1327 | $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]); |
1328 | $lineItem = $this->callAPISuccessGetSingle('LineItem', ['entity_id' => $membership['id'], 'entity_table' => 'civicrm_membership']); | |
f436577a | 1329 | $this->assertEquals(1, $lineItem['qty']); |
1330 | $this->assertEquals(50.00, $lineItem['unit_price']); | |
1331 | $this->assertEquals(50.00, $lineItem['line_total']); | |
1332 | $this->assertEquals(5.00, $lineItem['tax_amount']); | |
1333 | ||
c6000ff3 | 1334 | // Simply save the 'Edit Contribution' form |
1335 | $form = new CRM_Contribute_Form_Contribution(); | |
1336 | $form->_context = 'membership'; | |
9099cab3 CW |
1337 | $form->_values = $this->callAPISuccessGetSingle('Contribution', ['id' => $lineItem['contribution_id'], 'return' => ['total_amount', 'net_amount', 'fee_amount', 'tax_amount']]); |
1338 | $form->testSubmit([ | |
c6000ff3 | 1339 | 'contact_id' => $this->_individualId, |
1340 | 'id' => $lineItem['contribution_id'], | |
1341 | 'financial_type_id' => 2, | |
4a413eb6 | 1342 | 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'), |
9099cab3 | 1343 | ], |
c6000ff3 | 1344 | CRM_Core_Action::UPDATE); |
1345 | ||
ddfe1cb1 | 1346 | // ensure that the LineItem data remain the same |
9099cab3 | 1347 | $lineItem = $this->callAPISuccessGetSingle('LineItem', ['entity_id' => $membership['id'], 'entity_table' => 'civicrm_membership']); |
c6000ff3 | 1348 | $this->assertEquals(1, $lineItem['qty']); |
dcdfd53d K |
1349 | $this->assertEquals(50.00, $lineItem['unit_price']); |
1350 | $this->assertEquals(50.00, $lineItem['line_total']); | |
1351 | $this->assertEquals(5.00, $lineItem['tax_amount']); | |
c6000ff3 | 1352 | |
ddfe1cb1 | 1353 | // ensure that the LineItem data add up to the data at the Contribution level |
9a1b6474 | 1354 | $contribution = $this->callAPISuccessGetSingle('Contribution', |
9099cab3 | 1355 | [ |
02b29d41 | 1356 | 'contribution_id' => 1, |
9099cab3 CW |
1357 | 'return' => ['tax_amount', 'total_amount'], |
1358 | ] | |
9a1b6474 | 1359 | ); |
dcdfd53d | 1360 | $this->assertEquals($contribution['total_amount'], $lineItem['line_total'] + $lineItem['tax_amount']); |
9a1b6474 K |
1361 | $this->assertEquals($contribution['tax_amount'], $lineItem['tax_amount']); |
1362 | ||
9099cab3 | 1363 | $financialItems = $this->callAPISuccess('FinancialItem', 'get', []); |
b4940518 K |
1364 | $financialItems_sum = 0; |
1365 | foreach ($financialItems['values'] as $financialItem) { | |
1366 | $financialItems_sum += $financialItem['amount']; | |
1367 | } | |
1368 | $this->assertEquals($contribution['total_amount'], $financialItems_sum); | |
1369 | ||
f436577a | 1370 | // reset the price options static variable so not leave any dummy data, that might hamper other unit tests |
1371 | \Civi::$statics['CRM_Price_BAO_PriceField']['priceOptions'] = NULL; | |
1372 | $this->disableTaxAndInvoicing(); | |
1373 | } | |
1374 | ||
6a488035 | 1375 | } |