3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
29 * Test APIv3 civicrm_contribute_* functions
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contribution
35 class CRM_Contribute_Form_AdditionalPaymentTest
extends CiviUnitTestCase
{
42 protected $_individualId;
45 * Parameters to create contribution.
56 protected $_contributionId;
59 * Parameters to create payment processor.
63 protected $_processorParams = array();
66 * Payment instrument mapping.
70 protected $paymentInstruments = array();
73 * Dummy payment processor.
75 * @var CRM_Core_Payment_Dummy
77 protected $paymentProcessor;
80 * Payment processor ID.
84 protected $paymentProcessorID;
89 public function setUp() {
91 $this->createLoggedInUser();
93 $this->_individualId
= $this->individualCreate();
94 $this->_params
= array(
95 'total_amount' => 100,
97 'contact_id' => $this->_individualId
,
98 'financial_type_id' => 1,
100 $this->_processorParams
= array(
103 'payment_processor_type_id' => 10,
104 'financial_account_id' => 12,
107 'url_site' => 'http://dummy.com',
108 'url_recur' => 'http://dummy.com',
112 $instruments = $this->callAPISuccess('contribution', 'getoptions', array('field' => 'payment_instrument_id'));
113 $this->paymentInstruments
= $instruments['values'];
115 $this->paymentProcessor
= $this->dummyProcessorCreate();
116 $processor = $this->paymentProcessor
->getPaymentProcessor();
117 $this->paymentProcessorID
= $processor['id'];
121 * Clean up after each test.
123 public function tearDown() {
124 $this->quickCleanUpFinancialEntities();
125 CRM_Core_DAO
::executeQuery('DELETE FROM civicrm_mailing_spool ORDER BY id DESC');
130 * Test the submit function that completes the partially paid Contribution using Credit Card.
132 public function testAddPaymentUsingCreditCardForPartialyPaidContribution() {
133 $mut = new CiviMailUtils($this, TRUE);
134 $this->createContribution('Partially paid');
136 // pay additional amount by using Credit Card
137 $this->submitPayment(70, 'live', TRUE);
138 $this->checkResults(array(30, 70), 2);
139 $mut->assertSubjects(['Payment Receipt -']);
143 'Total Fees: $ 100.00',
144 'This Payment Amount: $ 70.00',
145 'Balance Owed: $ 0.00 ',
146 'Billing Name and Address',
147 'Vancouver, AE 1321312',
154 $mut->clearMessages();
158 * Test the submit function that completes the partially paid Contribution.
160 public function testAddPaymentForPartialyPaidContribution() {
161 $this->createContribution('Partially paid');
163 // pay additional amount
164 $this->submitPayment(70);
165 $this->checkResults(array(30, 70), 2);
169 * Test the submit function that completes the partially paid Contribution with multiple payments.
171 public function testMultiplePaymentForPartialyPaidContribution() {
172 $this->createContribution('Partially paid');
174 // pay additional amount
175 $this->submitPayment(50);
176 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
177 $this->assertEquals('Partially paid', $contribution['contribution_status']);
179 // pay additional amount
180 $this->submitPayment(20);
181 $this->checkResults(array(30, 50, 20), 3);
185 * Test the submit function that completes the partially paid Contribution with multiple payments.
187 public function testMultiplePaymentForPartiallyPaidContributionWithOneCreditCardPayment() {
188 $mut = new CiviMailUtils($this, TRUE);
189 $this->createContribution('Partially paid');
190 // In general when there is tpl leakage we try to fix. At the moment, however,
191 // the tpl leakage on credit card related things is kind of 'by-design' - or
192 // at least we haven't found a way to replace the way in with Payment.send_confirmation
193 // picks them up from the form process so we will just clear templates here to stop leakage
194 // from previous tests causing a fail.
195 // The reason this is hard to fix is that we save a billing address per contribution not
196 // per payment so it's a problem with the data model
197 CRM_Core_Smarty
::singleton()->clearTemplateVars();
199 // pay additional amount
200 $this->submitPayment(50, NULL, TRUE);
201 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
202 $this->assertEquals('Partially paid', $contribution['contribution_status']);
204 // pay additional amount by using credit card
205 $this->submitPayment(20, 'live');
206 $this->checkResults(array(30, 50, 20), 3);
207 $mut->assertSubjects(array('Payment Receipt -'));
210 'A payment has been received',
211 'Total Fees: $ 100.00',
212 'This Payment Amount: $ 50.00',
213 'Balance Owed: $ 20.00 ',
215 'Check Number: check-12345',
218 'Billing Name and Address',
222 $mut->clearMessages();
226 * Test the submit function that completes the pending pay later Contribution using Credit Card.
228 public function testAddPaymentUsingCreditCardForPendingPayLaterContribution() {
229 $this->createContribution('Pending');
231 // pay additional amount by using Credit Card
232 $this->submitPayment(100, 'live');
233 $this->checkResults(array(100), 1);
237 * Test the submit function that completes the pending pay later Contribution.
239 public function testAddPaymentForPendingPayLaterContribution() {
240 $this->createContribution('Pending');
242 // pay additional amount
243 $this->submitPayment(70);
244 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
245 $this->assertEquals('Partially paid', $contribution['contribution_status']);
247 // pay additional amount
248 $this->submitPayment(30);
249 $this->checkResults(array(30, 70), 2);
253 * Test the Membership status after completing the pending pay later Contribution.
255 public function testMembershipStatusAfterCompletingPayLaterContribution() {
256 $this->createContribution('Pending');
257 $membership = $this->createPendingMembershipAndRecordContribution($this->_contributionId
);
258 // pay additional amount
259 $this->submitPayment(100);
260 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
261 $contributionMembership = $this->callAPISuccessGetSingle('Membership', array('id' => $membership["id"]));
262 $membershipStatus = $this->callAPISuccessGetSingle('MembershipStatus', array('id' => $contributionMembership["status_id"]));
263 $this->assertEquals('New', $membershipStatus['name']);
266 private function createPendingMembershipAndRecordContribution($contributionId) {
267 $this->_individualId
= $this->individualCreate();
268 $membershipTypeAnnualFixed = $this->callAPISuccess('membership_type', 'create', array(
270 'name' => "AnnualFixed",
271 'member_of_contact_id' => 1,
272 'duration_unit' => "year",
273 'duration_interval' => 1,
274 'period_type' => "fixed",
275 'fixed_period_start_day' => "101",
276 'fixed_period_rollover_day' => "1231",
277 'relationship_type_id' => 20,
278 'financial_type_id' => 2,
280 $membershipStatuses = CRM_Member_PseudoConstant
::membershipStatus();
281 $pendingStatusId = array_search('Pending', $membershipStatuses);
282 $membership = $this->callAPISuccess('Membership', 'create', array(
283 'contact_id' => $this->_individualId
,
284 'membership_type_id' => $membershipTypeAnnualFixed['id'],
286 // Updating Membership status to Pending
287 $membership = $this->callAPISuccess('Membership', 'create', array(
288 'id' => $membership["id"],
289 'status_id' => $pendingStatusId,
291 $membershipPayment = $this->callAPISuccess('MembershipPayment', 'create', array(
292 'membership_id' => $membership["id"],
293 'contribution_id' => $contributionId,
299 * Test the submit function that completes the pending pay later Contribution with multiple payments.
301 public function testMultiplePaymentForPendingPayLaterContribution() {
302 $this->createContribution('Pending');
304 // pay additional amount
305 $this->submitPayment(40);
306 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
307 $this->assertEquals('Partially paid', $contribution['contribution_status']);
309 $this->submitPayment(20);
310 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
311 $this->assertEquals('Partially paid', $contribution['contribution_status']);
313 $this->submitPayment(30);
314 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
315 $this->assertEquals('Partially paid', $contribution['contribution_status']);
317 $this->submitPayment(10);
318 $this->checkResults(array(40, 20, 30, 10), 4);
322 * Test the submit function that completes the pending pay later Contribution with multiple payments.
324 public function testMultiplePaymentForPendingPayLaterContributionWithOneCreditCardPayment() {
325 $this->createContribution('Pending');
327 // pay additional amount
328 $this->submitPayment(50);
329 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
330 $this->assertEquals('Partially paid', $contribution['contribution_status']);
332 $this->submitPayment(20, 'live');
333 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
334 $this->assertEquals('Partially paid', $contribution['contribution_status']);
336 $this->submitPayment(20);
337 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
338 $this->assertEquals('Partially paid', $contribution['contribution_status']);
340 $this->submitPayment(10, 'live');
341 $this->checkResults(array(50, 20, 20, 10), 4);
345 * Function to create pending pay later or partially paid conntribution.
347 * @param string $typeofContribution
350 public function createContribution($typeofContribution = 'Pending') {
351 if ($typeofContribution == 'Partially paid') {
352 $contributionParams = array_merge($this->_params
, array(
353 'partial_payment_total' => 100.00,
354 'partial_amount_to_pay' => 30,
355 'contribution_status_id' => 1,
358 elseif ($typeofContribution == 'Pending') {
359 $contributionParams = array_merge($this->_params
, array(
360 'contribution_status_id' => 2,
364 $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams);
365 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $contribution['id']));
366 $this->assertNotEmpty($contribution);
367 $this->assertEquals($typeofContribution, $contribution['contribution_status']);
368 $this->_contributionId
= $contribution['id'];
372 * Function to submit payments for contribution.
374 * @param float $amount
376 * @param string $mode
378 * @param bool $isEmailReceipt
380 public function submitPayment($amount, $mode = NULL, $isEmailReceipt = FALSE) {
381 $form = new CRM_Contribute_Form_AdditionalPayment();
383 $submitParams = array(
384 'contribution_id' => $this->_contributionId
,
385 'contact_id' => $this->_individualId
,
386 'total_amount' => $amount,
388 'financial_type_id' => 1,
389 'receive_date' => '04/21/2015',
390 'receive_date_time' => '11:27PM',
391 'trxn_date' => '2017-04-11 13:05:11',
392 'payment_processor_id' => 0,
393 'is_email_receipt' => $isEmailReceipt,
394 'from_email_address' => 'site@something.com',
397 $submitParams +
= array(
398 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
399 'payment_processor_id' => $this->paymentProcessorID
,
400 'credit_card_exp_date' => array('M' => 5, 'Y' => 2025),
401 'credit_card_number' => '411111111111111',
403 'credit_card_type' => 'Visa',
404 'billing_city-5' => 'Vancouver',
405 'billing_state_province_id-5' => 1059,
406 'billing_postal_code-5' => 1321312,
407 'billing_country_id-5' => 1228,
411 $submitParams +
= array(
412 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
413 'check_number' => 'check-12345',
416 $form->cid
= $this->_individualId
;
417 $form->testSubmit($submitParams, $mode);
421 * Function to check result.
423 * @param array $amounts
424 * Array of payment amount for contribution
426 * Number payment for contribution
429 public function checkResults($amounts, $count) {
430 $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId
));
431 $this->assertNotEmpty($contribution);
432 $this->assertEquals('Completed', $contribution['contribution_status']);
434 $this->callAPISuccessGetCount('EntityFinancialTrxn', array(
435 'entity_table' => "civicrm_contribution",
436 'entity_id' => $this->_contributionId
,
437 'financial_trxn_id.is_payment' => 1,
438 'financial_trxn_id.total_amount' => array('IN' => $amounts),