3 use Civi\Api4\Participant
;
6 * Test CRM_Event_Form_Registration functions.
11 class CRM_Event_Form_ParticipantTest
extends CiviUnitTestCase
{
13 use CRMTraits_Financial_OrderTrait
;
15 * Options on the from Email address array.
19 protected $fromEmailAddressOptions = [];
21 public function setUp(): void
{
22 $this->useTransaction(TRUE);
27 * Initial test of submit function.
31 public function testSubmit(): void
{
32 $form = $this->getForm();
34 'register_date' => date('Ymd'),
37 'event_id' => $form->_eventId
,
39 $this->callAPISuccessGetSingle('Participant', []);
43 * Test financial items pending transaction is later altered.
47 public function testSubmitUnpaidPriceChangeWhileStillPending() {
48 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
49 $form->_quickConfig
= TRUE;
54 'price_field_id' => $this->getPriceFieldID(),
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,
60 'unit_price' => '800.000000000',
61 'line_total' => 800.0,
62 'participant_count' => 0,
64 'membership_type_id' => NULL,
65 'membership_num_terms' => NULL,
67 'html_type' => 'Radio',
68 'financial_type_id' => '4',
70 'non_deductible_amount' => '0.00',
74 $form->setAction(CRM_Core_Action
::ADD
);
75 $form->_priceSetId
= $this->getPriceSetID();
77 'register_date' => date('Ymd'),
80 'event_id' => $form->_eventId
,
81 'priceSetId' => $this->getPriceSetID(),
82 $this->getPriceFieldKey() => $this->_ids
['price_field_value'][0],
84 'amount_level' => 'Too much',
87 'payment_processor_id' => 0,
88 'record_contribution' => TRUE,
89 'financial_type_id' => 1,
90 'contribution_status_id' => 2,
91 'payment_instrument_id' => 1,
92 'receive_date' => date('Y-m-d'),
94 $participant = $this->callAPISuccessGetSingle('Participant', []);
95 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
96 $this->assertEquals(2, $contribution['contribution_status_id']);
97 $this->callAPISuccessGetSingle('FinancialItem', []);
99 $priceSetParams[$this->getPriceFieldKey()] = $this->getPriceFieldValueID();
100 $lineItem = CRM_Price_BAO_LineItem
::getLineItems($participant['id'], 'participant');
101 $this->assertEquals(55, $lineItem[1]['subTotal']);
102 $financialItems = $this->callAPISuccess('FinancialItem', 'get', []);
104 foreach ($financialItems['values'] as $financialItem) {
105 $sum +
= $financialItem['amount'];
107 $this->assertEquals(55, $sum);
109 CRM_Price_BAO_LineItem
::changeFeeSelections($priceSetParams, $participant['id'], 'participant', $contribution['id'], $this->eventFeeBlock
, $lineItem);
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);
114 $lineItem = CRM_Price_BAO_LineItem
::getLineItems($participant['id'], 'participant');
115 // Participants is updated to 0 but line remains.
116 $this->assertEquals(0, $lineItem[1]['subTotal']);
117 $this->assertEquals(1550.55, $lineItem[2]['subTotal']);
118 $financialItems = $this->callAPISuccess('FinancialItem', 'get', []);
121 foreach ($financialItems['values'] as $financialItem) {
122 $sum +
= $financialItem['amount'];
124 $this->assertEquals(1550.55, $sum);
128 * (dev/core#310) : Test to ensure payments are correctly allocated, when a event fee is changed for a mult-line item event registration
130 * @throws \CRM_Core_Exception
131 * @throws \CiviCRM_API3_Exception
133 public function testPaymentAllocationOnMultiLineItemEvent() {
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();
142 $priceSetBlock = CRM_Price_BAO_PriceSet
::getSetDetail($this->getPriceSetID(), TRUE, FALSE)[$this->getPriceSetID()]['fields'];
145 'priceSetId' => $this->getPriceSetID(),
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,
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);
155 $financialItems = $this->callAPISuccess('FinancialItem', 'get', [])['values'];
157 foreach ($financialItems as $financialItem) {
158 $sum +
= $financialItem['amount'];
160 $this->assertEquals(105, $sum);
161 $this->assertCount(3, $financialItems);
163 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
164 $this->assertEquals('Partially paid', $contribution['contribution_status']);
166 $this->callAPISuccess('Payment', 'create', [
167 'contribution_id' => $contribution['id'],
168 'participant_id' => $participant['id'],
169 'total_amount' => 40.00,
171 'payment_instrument_id' => 'Check',
172 'check_number' => '#123',
175 $result = $this->callAPISuccess('EntityFinancialTrxn', 'get', ['entity_table' => 'civicrm_financial_item', 'sequential' => 1, 'return' => ['entity_table', 'amount']])['values'];
176 $this->assertEquals(40, $result[2]['amount']);
177 $this->assertCount(4, $result);
181 * Initial test of submit function.
183 * @param string $thousandSeparator
185 * @dataProvider getThousandSeparators
189 public function testSubmitWithPayment($thousandSeparator) {
190 $this->setCurrencySeparators($thousandSeparator);
191 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
192 $form->_mode
= 'Live';
193 $form->_quickConfig
= TRUE;
194 $paymentProcessorID = $this->processorCreate(['is_test' => 0]);
195 $form->submit($this->getSubmitParamsForCreditCardPayment($paymentProcessorID));
196 $participant = $this->callAPISuccessGetSingle('Participant', []);
197 $this->assertEquals('2018-09-04 00:00:00', $participant['participant_register_date']);
198 $this->assertEquals('Offline Registration for Event: Annual CiviCRM meet by: ', $participant['participant_source']);
199 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
200 $this->assertEquals(1550.55, $contribution['total_amount']);
201 $this->assertEquals('Debit Card', $contribution['payment_instrument']);
202 $lineItem = $this->callAPISuccessGetSingle('LineItem', []);
204 'contribution_id' => $contribution['id'],
205 'entity_table' => 'civicrm_participant',
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],
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'),
217 foreach ($expected as $key => $value) {
218 $this->assertEquals($value, $lineItem[$key], $key);
223 * Initial test of submit function.
225 * @param string $thousandSeparator
226 * @param array $fromEmails From Emails array to overwrite the default.
228 * @dataProvider getThousandSeparators
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']);
240 $form->_fromEmails
= [
241 'from_email_id' => ['abc@gmail.com' => 1],
244 $form->submit($this->getSubmitParamsForCreditCardPayment($paymentProcessorID));
246 catch (CRM_Core_Exception_PrematureExitException
$e) {
249 $this->fail('should have hit premature exit');
253 * Test offline participant mail.
255 * @param string $thousandSeparator
257 * @dataProvider getThousandSeparators
260 public function testParticipantOfflineReceipt(string $thousandSeparator): void
{
261 $this->setCurrencySeparators($thousandSeparator);
262 $this->swapMessageTemplateForTestTemplate('event_offline_receipt', 'text');
263 $mut = new CiviMailUtils($this, TRUE);
264 // Create an email associated with the logged in contact
265 $loggedInContactID = $this->createLoggedInUser();
266 $email = $this->callAPISuccess('Email', 'create', [
267 'contact_id' => $loggedInContactID,
269 'email' => 'testLoggedInReceiptEmail@civicrm.org',
270 'location_type_id' => 1,
273 //Get workflow id of event_offline receipt.
274 $workflowId = $this->callAPISuccess('OptionValue', 'get', [
276 'option_group_id' => 'msg_tpl_workflow_event',
277 'name' => 'event_offline_receipt',
280 //Modify html to contain event_type_id token.
281 $result = $this->callAPISuccess('MessageTemplate', 'get', [
283 'return' => ['id', 'msg_html'],
284 'workflow_id' => $workflowId['id'],
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);
290 $this->callAPISuccess('MessageTemplate', 'create', [
291 'id' => $result['id'],
292 'msg_html' => $newMsg,
295 // Use the email created as the from email ensuring we are passing a numeric from to test dev/core#1069
296 $this->setCurrencySeparators($thousandSeparator);
297 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1, 'pay_later_receipt' => 'pay us']);
298 $form->_mode
= 'Live';
299 $form->_quickConfig
= TRUE;
300 $form->_fromEmails
= [
301 'from_email_id' => [$email['id'] => 1],
303 $paymentProcessorID = $this->processorCreate(['is_test' => 0]);
304 $submitParams = $this->getSubmitParamsForCreditCardPayment($paymentProcessorID);
305 $submitParams['from_email_address'] = $email['id'];
306 $form->submit($submitParams);
307 $participantID = Participant
::get()->addWhere('event_id', '=', $this->getEventID())->execute()->first()['id'];
308 //Check if type is correctly populated in mails.
309 //Also check the string email is present not numeric from.
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,
317 '<p>Test event type - 1</p>',
318 'event.title:::Annual CiviCRM meet',
319 'participant.status_id:name:::Registered',
320 'testloggedinreceiptemail@civicrm.org',
321 'event.pay_later_receipt:::pay us',
322 $this->formatMoneyInput(1550.55),
325 $this->callAPISuccess('Email', 'delete', ['id' => $email['id']]);
329 * Get prepared form object.
331 * @param array $eventParams
333 * @return CRM_Event_Form_Participant
335 * @throws \CRM_Core_Exception
337 protected function getForm($eventParams = []) {
338 if (!empty($eventParams['is_monetary'])) {
339 $event = $this->eventCreatePaid($eventParams, [['name' => 'big', 'amount' => 1550.55]]);
342 $event = $this->eventCreate($eventParams);
345 $this->ids
['contact']['event'] = (int) $this->individualCreate();
346 /** @var CRM_Event_Form_Participant $form */
347 $form = $this->getFormObject('CRM_Event_Form_Participant');
348 $form->_single
= TRUE;
349 $form->_contactID
= $form->_contactId
= $this->ids
['contact']['event'];
350 $form->setCustomDataTypes();
351 $form->_eventId
= $event['id'];
352 if (!empty($eventParams['is_monetary'])) {
354 $form->_isPaidEvent
= TRUE;
355 CRM_Event_Form_EventFees
::preProcess($form);
356 $form->assignProcessors();
357 $form->buildEventFeeForm($form);
360 $form->_fromEmails
= [
361 'from_email_id' => ['abc@gmail.com' => 1],
364 $this->fromEmailAddressOptions
= $form->_fromEmails
['from_email_id'];
369 * Get a valid value for from_email_address.
373 public function getFromEmailAddress() {
374 return key($this->fromEmailAddressOptions
);
378 * Create a Price set with two price field of type Text.
380 * Financial Type: 'Event Fee' and 'Event Fee 2' respectively.
382 * @throws \CRM_Core_Exception
383 * @throws \CiviCRM_API3_Exception
385 protected function createParticipantRecordsFromTwoFieldPriceSet() {
386 // Create financial type - Event Fee 2
387 $form = $this->getForm(['is_monetary' => 1, 'financial_type_id' => 1]);
389 $textFieldsToCreate = [['amount' => 10, 'label' => 'First Text field'], ['amount' => 55, 'label' => 'Second Text field']];
390 foreach ($textFieldsToCreate as $fieldToCreate) {
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'],
400 'html_type' => 'Text',
401 'financial_type_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Campaign Contribution'),
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'];
407 $this->_ids
['price_field_value'][strtolower(CRM_Utils_String
::titleToVar($fieldToCreate['label']))] = (int) $this->callAPISuccess('PriceFieldValue', 'getsingle', ['price_field_id' => $textPriceFieldID])['id'];
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,
419 'unit_price' => 55.00,
421 'participant_count' => 0,
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',
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,
438 'unit_price' => 10.00,
440 'participant_count' => 0,
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',
452 $form->setAction(CRM_Core_Action
::ADD
);
453 $form->_priceSetId
= $this->_ids
['price_set'];
456 'register_date' => date('Ymd'),
457 'receive_date' => '2018-09-01',
460 'event_id' => $this->getEventID(),
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',
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'),
476 * Get params for submit function.
478 * @param int $paymentProcessorID
482 private function getSubmitParamsForCreditCardPayment(int $paymentProcessorID): array {
484 'register_date' => '2018-09-04',
487 'event_id' => $this->getEventID(),
488 'credit_card_number' => 4444333322221111,
490 'credit_card_exp_date' => [
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,
504 'priceSetId' => $this->getPriceSetID(),
505 $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
506 'amount_level' => 'Too much',
507 'fee_amount' => $this->formatMoneyInput(1550.55),
508 'total_amount' => $this->formatMoneyInput(1550.55),
509 'from_email_address' => $this->getFromEmailAddress(),
511 'receipt_text' => '',
513 return $submitParams;
518 * @throws \CRM_Core_Exception
519 * @throws \CiviCRM_API3_Exception
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;
528 'register_date' => date('Ymd'),
531 $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
532 'priceSetId' => $this->getPriceSetID(),
533 'event_id' => $this->getEventID(),
534 'record_contribution' => TRUE,
535 'amount_level' => 'blah',
536 'financial_type_id' => 1,
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']}"));
544 * Test submitting a partially paid event registration.
546 * In this case the participant status is selected as 'partially paid' and
547 * a contribution is created for the full amount with a payment equal to the
550 * @dataProvider getBooleanDataProvider
552 * @param bool $isQuickConfig
554 * @throws \CRM_Core_Exception
555 * @throws \CiviCRM_API3_Exception
557 public function testSubmitPartialPayment($isQuickConfig) {
558 $mut = new CiviMailUtils($this, TRUE);
559 $form = $this->getForm(['is_monetary' => 1]);
560 $this->callAPISuccess('PriceSet', 'create', ['is_quick_config' => $isQuickConfig, 'id' => $this->getPriceSetID()]);
561 $paymentInstrumentID = CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
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',
571 'payment_instrument_id' => $paymentInstrumentID,
573 'contribution_status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'),
574 'total_amount' => '20',
575 'send_receipt' => '1',
576 'from_email_address' => $this->getFromEmailAddress(),
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],
581 'contact_id' => $this->getContactID(),
582 'event_id' => $this->getEventID(),
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',
591 $form->submit($submitParams);
592 $this->assertPartialPaymentResult($isQuickConfig, $mut);
596 * Test submitting a partially paid event registration, recording a pending contribution.
600 * @dataProvider getBooleanDataProvider
602 * @param bool $isQuickConfig
604 * @throws \CRM_Core_Exception
605 * @throws \CiviCRM_API3_Exception
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,
620 $this->assertPartialPaymentResult($isQuickConfig, $mut);
624 * Test submitting a partially paid event registration, recording a pending contribution.
628 * @dataProvider getBooleanDataProvider
630 * @param bool $isQuickConfig
632 * @throws \CRM_Core_Exception
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,
649 $this->assertPartialPaymentResult($isQuickConfig, $mut, FALSE);
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)
658 protected function assertPartialPaymentResult($isQuickConfig, CiviMailUtils
$mut, $isAmountPaidOnForm = TRUE) {
659 $paymentInstrumentID = CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
660 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
662 'contact_id' => $this->getContactID(),
663 'total_amount' => '1550.55',
664 'fee_amount' => '0.00',
665 'net_amount' => '1550.55',
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',
674 $this->assertAttributesEquals($expected, $contribution);
676 $participant = $this->callAPISuccessGetSingle('Participant', []);
677 $this->assertAttributesEquals([
678 'contact_id' => $this->getContactID(),
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',
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(),
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',
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',
715 'payment_instrument_id' => $paymentInstrumentID,
716 'check_number' => '879',
719 $financialItem = $this->callAPISuccessGetSingle('FinancialItem', []);
720 $this->assertAttributesEquals([
721 'description' => 'big',
722 'contact_id' => $this->getContactID(),
725 'status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Financial_BAO_FinancialItem', 'status_id', 'Partially paid'),
726 'entity_table' => 'civicrm_line_item',
727 'entity_id' => $lineItem['id'],
728 'financial_account_id' => 4,
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',
739 $isQuickConfig ?
$this->formatMoneyInput(1550.55) . ' big - 1' : 'Price Field - big',
740 $isAmountPaidOnForm ?
'Total Paid: $20.00' : ' ',
741 'Balance: $1,530.55',
742 'Financial Type: Event Fee',
749 * Get the id of the configured price set.
753 protected function getPriceSetID() {
754 return (int) $this->_ids
['price_set'];
758 * Get the price field id that has been created for the test.
762 protected function getPriceFieldID() {
763 return (int) $this->_ids
['price_field'][0];
767 * Get the array key for the configured price field.
771 protected function getPriceFieldKey(): string {
772 return 'price_' . $this->getPriceFieldID();
776 * Get the price field value id that has been created for the test.
780 protected function getPriceFieldValueID(): int {
781 return (int) $this->_ids
['price_field_value'][1];
785 * Get the parameters for recording a contribution.
787 * @param string $participantStatus
788 * @param string $contributionStatus
792 protected function getRecordContributionParams($participantStatus, $contributionStatus): array {
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'),
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],
812 'contact_id' => $this->getContactID(),
813 'event_id' => $this->getEventID(),
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',
822 return $submitParams;
826 * Check if participant is transferred correctly.
828 * @throws \CRM_Core_Exception
829 * @throws \CiviCRM_API3_Exception
831 public function testTransferParticipantRegistration(): void
{
832 //Register a contact to a sample event.
833 $this->createEventOrder();
834 $contribution = $this->callAPISuccessGetSingle('Contribution', ['return' => 'id']);
835 //Check line item count of the contribution id before transfer.
836 $lineItems = CRM_Price_BAO_LineItem
::getLineItemsByContributionID($contribution['id']);
837 $this->assertCount(2, $lineItems);
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();
842 $mut = new CiviMailUtils($this);
843 $this->swapMessageTemplateForInput('event_online_receipt', '{domain.name} {contact.first_name}');
844 $form->transferParticipantRegistration($toContactId, $participantId);
845 $mut->checkAllMailLog(['Default Domain Name Anthony']);
846 $mut->clearMessages();
847 $this->revertTemplateToReservedTemplate('event_online_receipt', 'html');
849 //Assert participant is transferred to $toContactId.
850 $participant = $this->callAPISuccess('Participant', 'getsingle', [
851 'return' => ['transferred_to_contact_id'],
852 'id' => $participantId,
854 $this->assertEquals($participant['transferred_to_contact_id'], $toContactId);
856 //Assert $toContactId has a new registration.
857 $toParticipant = $this->callAPISuccess('Participant', 'getsingle', [
858 'contact_id' => $toContactId,
860 $this->assertEquals($toParticipant['participant_registered_by_id'], $participantId);
862 //Check line item count of the contribution id remains the same.
863 $lineItems = CRM_Price_BAO_LineItem
::getLineItemsByContributionID($contribution['id']);
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);
873 * Get the id of the created event.
877 protected function getEventID(): int {
878 return $this->ids
['Event']['event'];
882 * Get created contact ID.
886 protected function getContactID(): int {
887 return $this->ids
['contact']['event'];