Swap out some additional assigns for tokens, improve tests
[civicrm-core.git] / tests / phpunit / CRM / Event / Form / ParticipantTest.php
CommitLineData
5fda4b16 1<?php
2
c16c5e08
EM
3use Civi\Api4\Participant;
4
5fda4b16 5/**
6 * Test CRM_Event_Form_Registration functions.
7 *
8 * @package CiviCRM
9 * @group headless
10 */
11class CRM_Event_Form_ParticipantTest extends CiviUnitTestCase {
12
da610957 13 use CRMTraits_Financial_OrderTrait;
89b6b472 14 /**
15 * Options on the from Email address array.
16 *
17 * @var array
18 */
19 protected $fromEmailAddressOptions = [];
20
faba1457 21 public function setUp(): void {
5fda4b16 22 $this->useTransaction(TRUE);
23 parent::setUp();
24 }
25
26 /**
27 * Initial test of submit function.
28 *
29 * @throws \Exception
30 */
c16c5e08 31 public function testSubmit(): void {
f660d2ad 32 $form = $this->getForm();
f78dbf0b 33 $form->submit([
6ba1830e 34 'register_date' => date('Ymd'),
5fda4b16 35 'status_id' => 1,
36 'role_id' => 1,
7c902b13 37 'event_id' => $form->_eventId,
f78dbf0b 38 ]);
beac0c97 39 $this->callAPISuccessGetSingle('Participant', []);
5fda4b16 40 }
41
f660d2ad 42 /**
43 * Test financial items pending transaction is later altered.
44 *
45 * @throws \Exception
46 */
6ba1830e 47 public function testSubmitUnpaidPriceChangeWhileStillPending() {
f78dbf0b 48 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
f660d2ad 49 $form->_quickConfig = TRUE;
50
f78dbf0b 51 $form->_lineItem = [
52 0 => [
53 13 => [
beac0c97 54 'price_field_id' => $this->getPriceFieldID(),
f660d2ad 55 'price_field_value_id' => $this->_ids['price_field_value'][0],
56 'label' => 'Tiny-tots (ages 5-8)',
57 'field_title' => 'Tournament Fees',
58 'description' => NULL,
59 'qty' => 1,
60 'unit_price' => '800.000000000',
61 'line_total' => 800.0,
62 'participant_count' => 0,
63 'max_value' => NULL,
64 'membership_type_id' => NULL,
65 'membership_num_terms' => NULL,
66 'auto_renew' => NULL,
67 'html_type' => 'Radio',
68 'financial_type_id' => '4',
69 'tax_amount' => NULL,
70 'non_deductible_amount' => '0.00',
f78dbf0b 71 ],
72 ],
73 ];
f660d2ad 74 $form->setAction(CRM_Core_Action::ADD);
beac0c97 75 $form->_priceSetId = $this->getPriceSetID();
f78dbf0b 76 $form->submit([
6ba1830e 77 'register_date' => date('Ymd'),
f660d2ad 78 'status_id' => 5,
79 'role_id' => 1,
80 'event_id' => $form->_eventId,
beac0c97 81 'priceSetId' => $this->getPriceSetID(),
82 $this->getPriceFieldKey() => $this->_ids['price_field_value'][0],
f660d2ad 83 'is_pay_later' => 1,
84 'amount_level' => 'Too much',
85 'fee_amount' => 55,
86 'total_amount' => 55,
87 'payment_processor_id' => 0,
88 'record_contribution' => TRUE,
89 'financial_type_id' => 1,
90 'contribution_status_id' => 2,
91 'payment_instrument_id' => 1,
fde1821d 92 'receive_date' => date('Y-m-d'),
f78dbf0b 93 ]);
beac0c97 94 $participant = $this->callAPISuccessGetSingle('Participant', []);
f78dbf0b 95 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
f660d2ad 96 $this->assertEquals(2, $contribution['contribution_status_id']);
beac0c97 97 $this->callAPISuccessGetSingle('FinancialItem', []);
f660d2ad 98
beac0c97 99 $priceSetParams[$this->getPriceFieldKey()] = $this->getPriceFieldValueID();
100 $lineItem = CRM_Price_BAO_LineItem::getLineItems($participant['id'], 'participant');
f660d2ad 101 $this->assertEquals(55, $lineItem[1]['subTotal']);
f78dbf0b 102 $financialItems = $this->callAPISuccess('FinancialItem', 'get', []);
f660d2ad 103 $sum = 0;
104 foreach ($financialItems['values'] as $financialItem) {
105 $sum += $financialItem['amount'];
106 }
107 $this->assertEquals(55, $sum);
108
beac0c97 109 CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $participant['id'], 'participant', $contribution['id'], $this->eventFeeBlock, $lineItem);
fab405c8 110 // Check that no payment records have been created.
111 // In https://lab.civicrm.org/dev/financial/issues/94 we had an issue where payments were created when none happend.
112 $payments = $this->callAPISuccess('Payment', 'get', [])['values'];
113 $this->assertCount(0, $payments);
beac0c97 114 $lineItem = CRM_Price_BAO_LineItem::getLineItems($participant['id'], 'participant');
f660d2ad 115 // Participants is updated to 0 but line remains.
116 $this->assertEquals(0, $lineItem[1]['subTotal']);
2d6f64f4 117 $this->assertEquals(1550.55, $lineItem[2]['subTotal']);
f78dbf0b 118 $financialItems = $this->callAPISuccess('FinancialItem', 'get', []);
f660d2ad 119
120 $sum = 0;
121 foreach ($financialItems['values'] as $financialItem) {
122 $sum += $financialItem['amount'];
123 }
2d6f64f4 124 $this->assertEquals(1550.55, $sum);
f660d2ad 125 }
126
74531938 127 /**
128 * (dev/core#310) : Test to ensure payments are correctly allocated, when a event fee is changed for a mult-line item event registration
129 *
130 * @throws \CRM_Core_Exception
131 * @throws \CiviCRM_API3_Exception
132 */
133 public function testPaymentAllocationOnMultiLineItemEvent() {
134 // USE-CASE :
135 // 1. Create a Price set with two price fields
136 // 2. Register for a Event using both the price field A($55 - qty 1) and B($10 - qty 1)
137 // 3. Now after registration, edit the participant, change the fee of price B from $10 to $50 (i.e. change qty from 1 to 5)
138 // 4. After submission check that related contribution's status is changed to 'Partially Paid'
139 // 5. Record the additional amount which $40 ($50-$10)
140 // Expected : Check the amount of new Financial Item created is $40
141 $this->createParticipantRecordsFromTwoFieldPriceSet();
beac0c97 142 $priceSetBlock = CRM_Price_BAO_PriceSet::getSetDetail($this->getPriceSetID(), TRUE, FALSE)[$this->getPriceSetID()]['fields'];
74531938 143
144 $priceSetParams = [
beac0c97 145 'priceSetId' => $this->getPriceSetID(),
74531938 146 // The 1 & 5 refer to qty as they are text fields.
147 'price_' . $this->_ids['price_field']['first_text_field'] => 5,
148 'price_' . $this->_ids['price_field']['second_text_field'] => 1,
149 ];
150 $participant = $this->callAPISuccess('Participant', 'get', []);
151 $lineItem = CRM_Price_BAO_LineItem::getLineItems($participant['id'], 'participant');
152 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
153 CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $participant['id'], 'participant', $contribution['id'], $priceSetBlock, $lineItem);
154
155 $financialItems = $this->callAPISuccess('FinancialItem', 'get', [])['values'];
156 $sum = 0;
157 foreach ($financialItems as $financialItem) {
158 $sum += $financialItem['amount'];
159 }
160 $this->assertEquals(105, $sum);
beac0c97 161 $this->assertCount(3, $financialItems);
74531938 162
163 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
164 $this->assertEquals('Partially paid', $contribution['contribution_status']);
165
166 $this->callAPISuccess('Payment', 'create', [
167 'contribution_id' => $contribution['id'],
168 'participant_id' => $participant['id'],
169 'total_amount' => 40.00,
170 'currency' => 'USD',
171 'payment_instrument_id' => 'Check',
172 'check_number' => '#123',
173 ]);
174
175 $result = $this->callAPISuccess('EntityFinancialTrxn', 'get', ['entity_table' => 'civicrm_financial_item', 'sequential' => 1, 'return' => ['entity_table', 'amount']])['values'];
f5a468db 176 $this->assertEquals(40, $result[2]['amount']);
beac0c97 177 $this->assertCount(4, $result);
74531938 178 }
179
5fda4b16 180 /**
181 * Initial test of submit function.
182 *
189f0360 183 * @param string $thousandSeparator
184 *
185 * @dataProvider getThousandSeparators
186 *
5fda4b16 187 * @throws \Exception
188 */
65f1a9a1 189 public function testSubmitWithPayment($thousandSeparator) {
189f0360 190 $this->setCurrencySeparators($thousandSeparator);
f78dbf0b 191 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
5fda4b16 192 $form->_mode = 'Live';
5fda4b16 193 $form->_quickConfig = TRUE;
f78dbf0b 194 $paymentProcessorID = $this->processorCreate(['is_test' => 0]);
beac0c97 195 $form->submit($this->getSubmitParamsForCreditCardPayment($paymentProcessorID));
ef45ad8c 196 $participant = $this->callAPISuccessGetSingle('Participant', []);
51c6ef2b 197 $this->assertEquals('2018-09-04 00:00:00', $participant['participant_register_date']);
ef45ad8c 198 $this->assertEquals('Offline Registration for Event: Annual CiviCRM meet by: ', $participant['participant_source']);
f78dbf0b 199 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
189f0360 200 $this->assertEquals(1550.55, $contribution['total_amount']);
5fda4b16 201 $this->assertEquals('Debit Card', $contribution['payment_instrument']);
dcf7cb45 202 $lineItem = $this->callAPISuccessGetSingle('LineItem', []);
203 $expected = [
204 'contribution_id' => $contribution['id'],
205 'entity_table' => 'civicrm_participant',
206 'qty' => 1,
207 'label' => 'big',
208 'unit_price' => 1550.55,
209 'line_total' => 1550.55,
210 'participant_count' => 0,
211 'price_field_id' => $this->_ids['price_field'][0],
212 'price_field_value_id' => $this->_ids['price_field_value'][1],
213 'tax_amount' => 0,
214 // Interestingly the financial_type_id set in this test is ignored but currently locking in what is happening with this test so setting to 'actual'
215 'financial_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Event Fee'),
216 ];
217 foreach ($expected as $key => $value) {
218 $this->assertEquals($value, $lineItem[$key], $key);
219 }
5fda4b16 220 }
221
65f1a9a1 222 /**
223 * Initial test of submit function.
224 *
225 * @param string $thousandSeparator
226 * @param array $fromEmails From Emails array to overwrite the default.
227 *
228 * @dataProvider getThousandSeparators
229 *
230 * @throws \Exception
231 */
232 public function testSubmitWithFailedPayment($thousandSeparator, $fromEmails = []) {
233 $this->setCurrencySeparators($thousandSeparator);
234 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
235 $form->_mode = 'Live';
236 $form->_quickConfig = TRUE;
237 $paymentProcessorID = $this->processorCreate(['is_test' => 0]);
238 Civi\Payment\System::singleton()->getById($paymentProcessorID)->setDoDirectPaymentResult(['payment_status_id' => 'failed']);
239
240 $form->_fromEmails = [
241 'from_email_id' => ['abc@gmail.com' => 1],
242 ];
243 try {
beac0c97 244 $form->submit($this->getSubmitParamsForCreditCardPayment($paymentProcessorID));
65f1a9a1 245 }
246 catch (CRM_Core_Exception_PrematureExitException $e) {
247 return;
248 }
249 $this->fail('should have hit premature exit');
250 }
251
8742774e
JP
252 /**
253 * Test offline participant mail.
f8df19bb 254 *
255 * @param string $thousandSeparator
256 *
257 * @dataProvider getThousandSeparators
65f1a9a1 258 * @throws \Exception
8742774e 259 */
c16c5e08 260 public function testParticipantOfflineReceipt(string $thousandSeparator): void {
f8df19bb 261 $this->setCurrencySeparators($thousandSeparator);
c16c5e08 262 $this->swapMessageTemplateForTestTemplate('event_offline_receipt', 'text');
8742774e 263 $mut = new CiviMailUtils($this, TRUE);
18422b25
SL
264 // Create an email associated with the logged in contact
265 $loggedInContactID = $this->createLoggedInUser();
266 $email = $this->callAPISuccess('Email', 'create', [
267 'contact_id' => $loggedInContactID,
268 'is_primary' => 1,
269 'email' => 'testLoggedInReceiptEmail@civicrm.org',
270 'location_type_id' => 1,
271 ]);
8742774e
JP
272
273 //Get workflow id of event_offline receipt.
f78dbf0b 274 $workflowId = $this->callAPISuccess('OptionValue', 'get', [
b28a34c3 275 'return' => ['id'],
276 'option_group_id' => 'msg_tpl_workflow_event',
277 'name' => 'event_offline_receipt',
f78dbf0b 278 ]);
8742774e
JP
279
280 //Modify html to contain event_type_id token.
f78dbf0b 281 $result = $this->callAPISuccess('MessageTemplate', 'get', [
8742774e 282 'sequential' => 1,
b28a34c3 283 'return' => ['id', 'msg_html'],
8742774e
JP
284 'workflow_id' => $workflowId['id'],
285 'is_default' => 1,
f78dbf0b 286 ]);
8742774e
JP
287 $oldMsg = $result['values'][0]['msg_html'];
288 $pos = strpos($oldMsg, 'Please print this confirmation');
289 $newMsg = substr_replace($oldMsg, '<p>Test event type - {$event.event_type_id}</p>', $pos, 0);
f78dbf0b 290 $this->callAPISuccess('MessageTemplate', 'create', [
8742774e
JP
291 'id' => $result['id'],
292 'msg_html' => $newMsg,
f78dbf0b 293 ]);
8742774e 294
18422b25 295 // Use the email created as the from email ensuring we are passing a numeric from to test dev/core#1069
65f1a9a1 296 $this->setCurrencySeparators($thousandSeparator);
c16c5e08 297 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1, 'pay_later_receipt' => 'pay us']);
65f1a9a1 298 $form->_mode = 'Live';
299 $form->_quickConfig = TRUE;
300 $form->_fromEmails = [
301 'from_email_id' => [$email['id'] => 1],
302 ];
303 $paymentProcessorID = $this->processorCreate(['is_test' => 0]);
beac0c97 304 $submitParams = $this->getSubmitParamsForCreditCardPayment($paymentProcessorID);
65f1a9a1 305 $submitParams['from_email_address'] = $email['id'];
306 $form->submit($submitParams);
c16c5e08 307 $participantID = Participant::get()->addWhere('event_id', '=', $this->getEventID())->execute()->first()['id'];
8742774e 308 //Check if type is correctly populated in mails.
18422b25 309 //Also check the string email is present not numeric from.
65f1a9a1 310 $mut->checkMailLog([
c16c5e08
EM
311 'contactID:::' . $this->getContactID(),
312 'contact.id:::' . $this->getContactID(),
313 'eventID:::' . $this->getEventID(),
314 'event.id:::' . $this->getEventID(),
315 'participantID:::' . $participantID,
316 'participant.id:::' . $participantID,
39b959db 317 '<p>Test event type - 1</p>',
c16c5e08
EM
318 'event.title:::Annual CiviCRM meet',
319 'participant.status_id:name:::Registered',
18422b25 320 'testloggedinreceiptemail@civicrm.org',
c16c5e08 321 'event.pay_later_receipt:::pay us',
39b959db
SL
322 $this->formatMoneyInput(1550.55),
323 ]);
c16c5e08 324
18422b25 325 $this->callAPISuccess('Email', 'delete', ['id' => $email['id']]);
8742774e
JP
326 }
327
7c902b13 328 /**
f660d2ad 329 * Get prepared form object.
7c902b13 330 *
331 * @param array $eventParams
332 *
333 * @return CRM_Event_Form_Participant
65f1a9a1 334 *
74531938 335 * @throws \CRM_Core_Exception
7c902b13 336 */
74531938 337 protected function getForm($eventParams = []) {
f660d2ad 338 if (!empty($eventParams['is_monetary'])) {
2d6f64f4 339 $event = $this->eventCreatePaid($eventParams, [['name' => 'big', 'amount' => 1550.55]]);
f660d2ad 340 }
341 else {
342 $event = $this->eventCreate($eventParams);
343 }
344
4132c927 345 $this->ids['contact']['event'] = (int) $this->individualCreate();
f78dbf0b 346 /** @var CRM_Event_Form_Participant $form */
7c902b13 347 $form = $this->getFormObject('CRM_Event_Form_Participant');
348 $form->_single = TRUE;
4132c927 349 $form->_contactID = $form->_contactId = $this->ids['contact']['event'];
7c902b13 350 $form->setCustomDataTypes();
351 $form->_eventId = $event['id'];
352 if (!empty($eventParams['is_monetary'])) {
7c902b13 353 $form->_bltID = 5;
7c902b13 354 $form->_isPaidEvent = TRUE;
b28a34c3 355 CRM_Event_Form_EventFees::preProcess($form);
26e40b3e 356 $form->assignProcessors();
2ee9bfad 357 $form->buildEventFeeForm($form);
7c902b13 358 }
89b6b472 359 else {
360 $form->_fromEmails = [
361 'from_email_id' => ['abc@gmail.com' => 1],
362 ];
363 }
364 $this->fromEmailAddressOptions = $form->_fromEmails['from_email_id'];
7c902b13 365 return $form;
366 }
367
89b6b472 368 /**
369 * Get a valid value for from_email_address.
370 *
371 * @return int|string
372 */
373 public function getFromEmailAddress() {
374 return key($this->fromEmailAddressOptions);
375 }
376
74531938 377 /**
378 * Create a Price set with two price field of type Text.
379 *
380 * Financial Type: 'Event Fee' and 'Event Fee 2' respectively.
381 *
382 * @throws \CRM_Core_Exception
383 * @throws \CiviCRM_API3_Exception
384 */
385 protected function createParticipantRecordsFromTwoFieldPriceSet() {
386 // Create financial type - Event Fee 2
387 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
388
389 $textFieldsToCreate = [['amount' => 10, 'label' => 'First Text field'], ['amount' => 55, 'label' => 'Second Text field']];
390 foreach ($textFieldsToCreate as $fieldToCreate) {
391 $fieldParams = [
392 'option_label' => ['1' => 'Price Field'],
393 'option_value' => ['1' => $fieldToCreate['amount']],
394 'option_name' => ['1' => $fieldToCreate['amount']],
395 'option_amount' => ['1' => $fieldToCreate['amount']],
396 'option_weight' => ['1' => $fieldToCreate['amount']],
397 'is_display_amounts' => 1,
398 'price_set_id' => $this->_ids['price_set'],
399 'is_enter_qty' => 1,
400 'html_type' => 'Text',
401 'financial_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Campaign Contribution'),
402 ];
403 $fieldParams['label'] = $fieldToCreate['label'];
404 $fieldParams['name'] = CRM_Utils_String::titleToVar($fieldToCreate['label']);
405 $fieldParams['price'] = $fieldToCreate['amount'];
406 $this->_ids['price_field'][strtolower(CRM_Utils_String::titleToVar($fieldToCreate['label']))] = $textPriceFieldID = $this->callAPISuccess('PriceField', 'create', $fieldParams)['id'];
f78dbf0b 407 $this->_ids['price_field_value'][strtolower(CRM_Utils_String::titleToVar($fieldToCreate['label']))] = (int) $this->callAPISuccess('PriceFieldValue', 'getsingle', ['price_field_id' => $textPriceFieldID])['id'];
74531938 408 }
409
410 $form->_lineItem = [
411 0 => [
412 13 => [
413 'price_field_id' => $this->_ids['price_field']['second_text_field'],
414 'price_field_value_id' => $this->_ids['price_field_value']['second_text_field'],
415 'label' => 'Event Fee 1',
416 'field_title' => 'Event Fee 1',
417 'description' => NULL,
418 'qty' => 1,
419 'unit_price' => 55.00,
420 'line_total' => 55.,
421 'participant_count' => 0,
422 'max_value' => NULL,
423 'membership_type_id' => NULL,
424 'membership_num_terms' => NULL,
425 'auto_renew' => NULL,
426 'html_type' => 'Text',
427 'financial_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Campaign Contribution'),
428 'tax_amount' => NULL,
429 'non_deductible_amount' => '0.00',
430 ],
431 14 => [
432 'price_field_id' => $this->_ids['price_field']['first_text_field'],
433 'price_field_value_id' => $this->_ids['price_field_value']['first_text_field'],
434 'label' => 'Event Fee 2',
435 'field_title' => 'Event Fee 2',
436 'description' => NULL,
437 'qty' => 1,
438 'unit_price' => 10.00,
439 'line_total' => 10,
440 'participant_count' => 0,
441 'max_value' => NULL,
442 'membership_type_id' => NULL,
443 'membership_num_terms' => NULL,
444 'auto_renew' => NULL,
445 'html_type' => 'Text',
446 'financial_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Campaign Contribution'),
447 'tax_amount' => NULL,
448 'non_deductible_amount' => '0.00',
449 ],
450 ],
451 ];
452 $form->setAction(CRM_Core_Action::ADD);
453 $form->_priceSetId = $this->_ids['price_set'];
454
455 $form->submit([
456 'register_date' => date('Ymd'),
457 'receive_date' => '2018-09-01',
458 'status_id' => 5,
459 'role_id' => 1,
beac0c97 460 'event_id' => $this->getEventID(),
74531938 461 'priceSetId' => $this->_ids['price_set'],
462 'price_' . $this->_ids['price_field']['first_text_field'] => [$this->_ids['price_field_value']['first_text_field'] => 1],
463 'price_' . $this->_ids['price_field']['second_text_field'] => [$this->_ids['price_field_value']['second_text_field'] => 1],
464 'amount_level' => 'Too much',
465 'fee_amount' => 65,
466 'total_amount' => 65,
467 'payment_processor_id' => 0,
468 'record_contribution' => TRUE,
469 'financial_type_id' => 1,
470 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'),
471 'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
472 ]);
473 }
474
65f1a9a1 475 /**
476 * Get params for submit function.
477 *
65f1a9a1 478 * @param int $paymentProcessorID
479 *
480 * @return array
481 */
beac0c97 482 private function getSubmitParamsForCreditCardPayment(int $paymentProcessorID): array {
65f1a9a1 483 $submitParams = [
51c6ef2b 484 'register_date' => '2018-09-04',
65f1a9a1 485 'status_id' => 1,
486 'role_id' => 1,
beac0c97 487 'event_id' => $this->getEventID(),
65f1a9a1 488 'credit_card_number' => 4444333322221111,
489 'cvv2' => 123,
490 'credit_card_exp_date' => [
491 'M' => 9,
492 'Y' => 2025,
493 ],
494 'credit_card_type' => 'Visa',
495 'billing_first_name' => 'Junko',
496 'billing_middle_name' => '',
497 'billing_last_name' => 'Adams',
498 'billing_street_address-5' => '790L Lincoln St S',
499 'billing_city-5' => 'Maryknoll',
500 'billing_state_province_id-5' => 1031,
501 'billing_postal_code-5' => 10545,
502 'billing_country_id-5' => 1228,
503 'payment_processor_id' => $paymentProcessorID,
beac0c97 504 'priceSetId' => $this->getPriceSetID(),
505 $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
65f1a9a1 506 'amount_level' => 'Too much',
507 'fee_amount' => $this->formatMoneyInput(1550.55),
508 'total_amount' => $this->formatMoneyInput(1550.55),
89b6b472 509 'from_email_address' => $this->getFromEmailAddress(),
65f1a9a1 510 'send_receipt' => 1,
511 'receipt_text' => '',
512 ];
513 return $submitParams;
514 }
515
f84f92f2 516 /**
517 *
518 * @throws \CRM_Core_Exception
519 * @throws \CiviCRM_API3_Exception
520 */
521 public function testSubmitWithDeferredRecognition() {
522 Civi::settings()->set('deferred_revenue_enabled', TRUE);
523 $futureDate = date('Y') + 1 . '-09-20';
524 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1, 'start_date' => $futureDate]);
525 $form->_quickConfig = TRUE;
526
527 $form->submit([
528 'register_date' => date('Ymd'),
529 'status_id' => 1,
530 'role_id' => 1,
4cd86dba
EM
531 $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
532 'priceSetId' => $this->getPriceSetID(),
beac0c97 533 'event_id' => $this->getEventID(),
f84f92f2 534 'record_contribution' => TRUE,
f84f92f2 535 'amount_level' => 'blah',
536 'financial_type_id' => 1,
537 ]);
538 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
539 // Api doesn't retrieve it & we don't much want to change that as we want to feature freeze BAO_Query.
540 $this->assertEquals($futureDate . ' 00:00:00', CRM_Core_DAO::singleValueQuery("SELECT revenue_recognition_date FROM civicrm_contribution WHERE id = {$contribution['id']}"));
541 }
542
b28a34c3 543 /**
544 * Test submitting a partially paid event registration.
545 *
546 * In this case the participant status is selected as 'partially paid' and
d6d93aa4
EM
547 * a contribution is created for the full amount with a payment equal to the
548 * entered amount.
b28a34c3 549 *
550 * @dataProvider getBooleanDataProvider
551 *
552 * @param bool $isQuickConfig
553 *
554 * @throws \CRM_Core_Exception
d6d93aa4 555 * @throws \CiviCRM_API3_Exception
b28a34c3 556 */
557 public function testSubmitPartialPayment($isQuickConfig) {
89b6b472 558 $mut = new CiviMailUtils($this, TRUE);
b28a34c3 559 $form = $this->getForm(['is_monetary' => 1]);
560 $this->callAPISuccess('PriceSet', 'create', ['is_quick_config' => $isQuickConfig, 'id' => $this->getPriceSetID()]);
89b6b472 561 $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
b28a34c3 562 $submitParams = [
563 'hidden_feeblock' => '1',
564 'hidden_eventFullMsg' => '',
565 'priceSetId' => $this->getPriceSetID(),
566 $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
567 'check_number' => '879',
568 'record_contribution' => '1',
569 'financial_type_id' => '4',
570 'receive_date' => '2020-01-31 00:51:00',
89b6b472 571 'payment_instrument_id' => $paymentInstrumentID,
b28a34c3 572 'trxn_id' => '',
573 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'),
574 'total_amount' => '20',
575 'send_receipt' => '1',
89b6b472 576 'from_email_address' => $this->getFromEmailAddress(),
b28a34c3 577 'receipt_text' => 'Contact the Development Department if you need to make any changes to your registration.',
578 'hidden_custom' => '1',
579 'hidden_custom_group_count' => ['' => 1],
580 'custom_4_-1' => '',
4132c927 581 'contact_id' => $this->getContactID(),
beac0c97 582 'event_id' => $this->getEventID(),
b28a34c3 583 'campaign_id' => '',
584 'register_date' => '2020-01-31 00:50:00',
585 'role_id' => [0 => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Attendee')],
586 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'status_id', 'Partially paid'),
587 'source' => 'I wrote this',
588 'note' => 'I wrote a note',
589 'MAX_FILE_SIZE' => '33554432',
590 ];
591 $form->submit($submitParams);
4132c927 592 $this->assertPartialPaymentResult($isQuickConfig, $mut);
593 }
594
595 /**
596 * Test submitting a partially paid event registration, recording a pending contribution.
597 *
598 * This tests
599 *
600 * @dataProvider getBooleanDataProvider
601 *
602 * @param bool $isQuickConfig
603 *
604 * @throws \CRM_Core_Exception
605 * @throws \CiviCRM_API3_Exception
606 */
607 public function testSubmitPendingPartiallyPaidAddPayment($isQuickConfig) {
608 $mut = new CiviMailUtils($this, TRUE);
609 $form = $this->getForm(['is_monetary' => 1]);
610 $this->callAPISuccess('PriceSet', 'create', ['is_quick_config' => $isQuickConfig, 'id' => $this->getPriceSetID()]);
611 $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
612 $submitParams = $this->getRecordContributionParams('Partially paid', $form);
613 $form->submit($submitParams);
614 $this->callAPISuccess('Payment', 'create', [
615 'contribution_id' => $this->callAPISuccessGetValue('Contribution', ['return' => 'id']),
616 'total_amount' => 20,
617 'check_number' => 879,
618 'payment_instrument_id' => $paymentInstrumentID,
619 ]);
620 $this->assertPartialPaymentResult($isQuickConfig, $mut);
621 }
622
623 /**
624 * Test submitting a partially paid event registration, recording a pending contribution.
625 *
626 * This tests
627 *
628 * @dataProvider getBooleanDataProvider
629 *
630 * @param bool $isQuickConfig
631 *
632 * @throws \CRM_Core_Exception
633 */
634 public function testSubmitPendingAddPayment($isQuickConfig) {
635 $mut = new CiviMailUtils($this, TRUE);
636 $form = $this->getForm(['is_monetary' => 1]);
637 $this->callAPISuccess('PriceSet', 'create', ['is_quick_config' => $isQuickConfig, 'id' => $this->getPriceSetID()]);
638 $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
639 $submitParams = $this->getRecordContributionParams('Pending from pay later', 'Pending');
640 // Create the pending contribution for the full amount to be paid.
641 $submitParams['total_amount'] = 1550.55;
642 $form->submit($submitParams);
643 $this->callAPISuccess('Payment', 'create', [
644 'contribution_id' => $this->callAPISuccessGetValue('Contribution', ['return' => 'id']),
645 'total_amount' => 20,
646 'check_number' => 879,
647 'payment_instrument_id' => $paymentInstrumentID,
648 ]);
649 $this->assertPartialPaymentResult($isQuickConfig, $mut, FALSE);
650 }
651
652 /**
653 * @param bool $isQuickConfig
654 * @param \CiviMailUtils $mut
655 * @param bool $isAmountPaidOnForm
656 * Was the amount paid entered on the form (if so this should be on the receipt)
657 */
658 protected function assertPartialPaymentResult($isQuickConfig, CiviMailUtils $mut, $isAmountPaidOnForm = TRUE) {
659 $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
89b6b472 660 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
661 $expected = [
4132c927 662 'contact_id' => $this->getContactID(),
89b6b472 663 'total_amount' => '1550.55',
664 'fee_amount' => '0.00',
d3e6e9a4 665 'net_amount' => '1550.55',
89b6b472 666 'contribution_source' => 'I wrote this',
667 'amount_level' => '',
668 'is_template' => '0',
669 'financial_type' => 'Event Fee',
670 'payment_instrument' => 'Check',
671 'contribution_status' => 'Partially paid',
672 'check_number' => '879',
673 ];
674 $this->assertAttributesEquals($expected, $contribution);
675
676 $participant = $this->callAPISuccessGetSingle('Participant', []);
677 $this->assertAttributesEquals([
4132c927 678 'contact_id' => $this->getContactID(),
89b6b472 679 'event_title' => 'Annual CiviCRM meet',
680 'participant_fee_level' => [0 => 'big - 1'],
681 'participant_fee_amount' => '1550.55',
682 'participant_fee_currency' => 'USD',
683 'event_type' => 'Conference',
684 'participant_status' => 'Partially paid',
685 'participant_role' => 'Attendee',
686 'participant_source' => 'I wrote this',
687 'participant_note' => 'I wrote a note',
688 'participant_is_pay_later' => '0',
689 ], $participant);
690 $lineItem = $this->callAPISuccessGetSingle('LineItem', []);
691 $this->assertAttributesEquals([
692 'entity_table' => 'civicrm_participant',
693 'entity_id' => $participant['id'],
694 'contribution_id' => $contribution['id'],
695 'price_field_id' => $this->getPriceFieldID(),
696 'label' => 'big',
697 'qty' => '1.00',
698 'unit_price' => '1550.55',
699 'line_total' => '1550.55',
700 'participant_count' => '0',
701 'price_field_value_id' => $this->getPriceFieldValueID(),
702 'financial_type_id' => '4',
703 'tax_amount' => '0.00',
704 ], $lineItem);
705
89b6b472 706 $payment = $this->callAPISuccessGetSingle('FinancialTrxn', ['is_payment' => 1]);
707 $this->assertAttributesEquals([
708 'to_financial_account_id' => 6,
709 'from_financial_account_id' => 7,
710 'total_amount' => 20,
711 'fee_amount' => '0.00',
712 'net_amount' => 20,
713 'currency' => 'USD',
714 'status_id' => '1',
715 'payment_instrument_id' => $paymentInstrumentID,
716 'check_number' => '879',
717 ], $payment);
718
719 $financialItem = $this->callAPISuccessGetSingle('FinancialItem', []);
720 $this->assertAttributesEquals([
721 'description' => 'big',
4132c927 722 'contact_id' => $this->getContactID(),
89b6b472 723 'amount' => 1550.55,
724 'currency' => 'USD',
de7391fc 725 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_FinancialItem', 'status_id', 'Partially paid'),
89b6b472 726 'entity_table' => 'civicrm_line_item',
727 'entity_id' => $lineItem['id'],
728 'financial_account_id' => 4,
729 ], $financialItem);
730
731 $mut->checkMailLog([
732 'From: "FIXME" <info@EXAMPLE.ORG>',
733 'To: Anthony Anderson <anthony_anderson@civicrm.org>',
734 'Subject: Event Confirmation - Annual CiviCRM meet - Mr. Anthony Anderson II',
735 'Dear Anthony,Contact the Development Department if you need to make any changes to your registration.',
736 'Event Information and Location',
737 'Annual CiviCRM meet',
738 'Registered Email',
739 $isQuickConfig ? $this->formatMoneyInput(1550.55) . ' big - 1' : 'Price Field - big',
d6d93aa4
EM
740 $isAmountPaidOnForm ? 'Total Paid: $20.00' : ' ',
741 'Balance: $1,530.55',
89b6b472 742 'Financial Type: Event Fee',
743 'Paid By: Check',
744 'Check Number: 879',
745 ]);
b28a34c3 746 }
747
748 /**
749 * Get the id of the configured price set.
750 *
751 * @return int
752 */
753 protected function getPriceSetID() {
754 return (int) $this->_ids['price_set'];
755 }
756
757 /**
758 * Get the price field id that has been created for the test.
759 *
760 * @return int
761 */
762 protected function getPriceFieldID() {
763 return (int) $this->_ids['price_field'][0];
764 }
765
766 /**
767 * Get the array key for the configured price field.
768 *
769 * @return string
770 */
771 protected function getPriceFieldKey(): string {
772 return 'price_' . $this->getPriceFieldID();
773 }
774
775 /**
776 * Get the price field value id that has been created for the test.
777 *
778 * @return int
779 */
780 protected function getPriceFieldValueID(): int {
781 return (int) $this->_ids['price_field_value'][1];
782 }
783
4132c927 784 /**
785 * Get the parameters for recording a contribution.
786 *
787 * @param string $participantStatus
788 * @param string $contributionStatus
789 *
790 * @return array
791 */
792 protected function getRecordContributionParams($participantStatus, $contributionStatus): array {
793 $submitParams = [
794 'hidden_feeblock' => '1',
795 'hidden_eventFullMsg' => '',
796 'priceSetId' => $this->getPriceSetID(),
797 $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
798 'check_number' => '879',
799 'record_contribution' => '1',
800 'financial_type_id' => '4',
801 'receive_date' => '2020-01-31 00:51:00',
802 'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
803 'trxn_id' => '',
804 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contributionStatus),
805 'total_amount' => '20',
806 'send_receipt' => '1',
807 'from_email_address' => $this->getFromEmailAddress(),
808 'receipt_text' => 'Contact the Development Department if you need to make any changes to your registration.',
809 'hidden_custom' => '1',
810 'hidden_custom_group_count' => ['' => 1],
811 'custom_4_-1' => '',
812 'contact_id' => $this->getContactID(),
813 'event_id' => $this->getEventID(),
814 'campaign_id' => '',
815 'register_date' => '2020-01-31 00:50:00',
816 'role_id' => [0 => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Attendee')],
817 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'status_id', $participantStatus),
818 'source' => 'I wrote this',
819 'note' => 'I wrote a note',
820 'MAX_FILE_SIZE' => '33554432',
821 ];
822 return $submitParams;
823 }
824
4720af1a 825 /**
826 * Check if participant is transferred correctly.
827 *
828 * @throws \CRM_Core_Exception
829 * @throws \CiviCRM_API3_Exception
830 */
da610957 831 public function testTransferParticipantRegistration(): void {
4720af1a 832 //Register a contact to a sample event.
da610957
EM
833 $this->createEventOrder();
834 $contribution = $this->callAPISuccessGetSingle('Contribution', ['return' => 'id']);
4720af1a 835 //Check line item count of the contribution id before transfer.
836 $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($contribution['id']);
da610957 837 $this->assertCount(2, $lineItems);
4720af1a 838 $participantId = CRM_Core_DAO::getFieldValue('CRM_Event_BAO_ParticipantPayment', $contribution['id'], 'participant_id', 'contribution_id');
839 /* @var CRM_Event_Form_SelfSvcTransfer $form */
840 $form = $this->getFormObject('CRM_Event_Form_SelfSvcTransfer');
841 $toContactId = $this->individualCreate();
96ea99c8
EM
842 $mut = new CiviMailUtils($this);
843 $this->swapMessageTemplateForInput('event_online_receipt', '{domain.name} {contact.first_name}');
99afef64 844 $form->transferParticipantRegistration($toContactId, $participantId);
96ea99c8
EM
845 $mut->checkAllMailLog(['Default Domain Name Anthony']);
846 $mut->clearMessages();
847 $this->revertTemplateToReservedTemplate('event_online_receipt', 'html');
4720af1a 848
849 //Assert participant is transferred to $toContactId.
850 $participant = $this->callAPISuccess('Participant', 'getsingle', [
da610957 851 'return' => ['transferred_to_contact_id'],
4720af1a 852 'id' => $participantId,
853 ]);
854 $this->assertEquals($participant['transferred_to_contact_id'], $toContactId);
855
856 //Assert $toContactId has a new registration.
857 $toParticipant = $this->callAPISuccess('Participant', 'getsingle', [
858 'contact_id' => $toContactId,
859 ]);
860 $this->assertEquals($toParticipant['participant_registered_by_id'], $participantId);
861
862 //Check line item count of the contribution id remains the same.
863 $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($contribution['id']);
da610957
EM
864 $this->assertCount(2, $lineItems);
865 // There should be 2 participant payments on the contribution & 0 others existing.
866 $this->callAPISuccessGetCount('ParticipantPayment', ['contribution_id' => $contribution['id']], 2);
867 $this->callAPISuccessGetCount('ParticipantPayment', [], 2);
868 $this->callAPISuccessGetCount('ParticipantPayment', ['participant_id' => $toParticipant['id']], 1);
869 $this->callAPISuccessGetCount('ParticipantPayment', ['participant_id' => $participantId], 0);
4720af1a 870 }
871
beac0c97 872 /**
873 * Get the id of the created event.
874 *
875 * @return int
876 */
877 protected function getEventID(): int {
57a7aa8a 878 return $this->ids['Event']['event'];
beac0c97 879 }
880
4132c927 881 /**
882 * Get created contact ID.
883 *
884 * @return int
885 */
886 protected function getContactID(): int {
887 return $this->ids['contact']['event'];
888 }
889
5fda4b16 890}