From 61bfc59503bd8a42c19e04afc50971e136391f63 Mon Sep 17 00:00:00 2001 From: Pradeep Nayak Date: Wed, 12 Apr 2017 23:32:42 +1200 Subject: [PATCH] CRM-20392 add unit test and fix for incorrect total used in line item creation code. Eileen's note - this is code done by Pradeep that I am reviewing - I am committing and merging the portion I have reviewed so far. This fixes a bug replicable in the test Pradeep wrote, and some minor obvious cleanups such as removing unused parameters. I've commented out some tests to complete this portion & there is still code of Pradeeps not yet reviewed. --- CRM/Contribute/BAO/Contribution.php | 3 +- CRM/Contribute/Form/AdditionalPayment.php | 62 ++- CRM/Price/BAO/LineItem.php | 2 +- .../Contribute/Form/AdditionalPaymentTest.php | 352 ++++++++++++++++++ 4 files changed, 409 insertions(+), 10 deletions(-) create mode 100644 tests/phpunit/CRM/Contribute/Form/AdditionalPaymentTest.php diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index 6e715176d1..16169a4fa8 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -3943,8 +3943,9 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']}) $activityType = ($paymentType == 'refund') ? 'Refund' : 'Payment'; self::addActivityForPayment($entityObj, $financialTrxn, $activityType, $component, $contributionId); + return $financialTrxn; } - return $financialTrxn; + } /** diff --git a/CRM/Contribute/Form/AdditionalPayment.php b/CRM/Contribute/Form/AdditionalPayment.php index 8540925c5e..799948d995 100644 --- a/CRM/Contribute/Form/AdditionalPayment.php +++ b/CRM/Contribute/Form/AdditionalPayment.php @@ -99,7 +99,6 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract return; } $this->_fromEmails = CRM_Core_BAO_Email::getFromEmail(); - $this->_formType = CRM_Utils_Array::value('formType', $_GET); $enitityType = NULL; $enitityType = 'contribution'; @@ -436,10 +435,10 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract $params["address_name-{$this->_bltID}"] = trim($params["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; - $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', - $this->_contactId, - 'contact_type' - ); + $ctype = civicrm_api3('Contact', 'getvalue', array( + 'return' => "contact_type", + 'id' => $this->_contactId, + )); $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { @@ -569,9 +568,11 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract } /** + * Function to send email receipt. + * * @param array $params * - * @return mixed + * @return bool */ public function emailReceipt(&$params) { // email receipt sending @@ -647,11 +648,56 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract $sendTemplateParams['from'] = $receiptFrom; $sendTemplateParams['toName'] = $this->_contributorDisplayName; $sendTemplateParams['toEmail'] = $this->_contributorEmail; - $sendTemplateParams['cc'] = CRM_Utils_Array::value('cc', $this->_fromEmails); - $sendTemplateParams['bcc'] = CRM_Utils_Array::value('bcc', $this->_fromEmails); } list($mailSent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); return $mailSent; } + /** + * Wrapper for unit testing the post process submit function. + * + * + * @param array $params + * @param string|null $creditCardMode + * @param string $enitityType + * + * @throws \CiviCRM_API3_Exception + */ + public function testSubmit($params, $creditCardMode = NULL, $enitityType = 'contribute') { + $this->_bltID = 5; + if (!empty($params['contribution_id'])) { + $this->_contributionId = $params['contribution_id']; + + $paymentInfo = CRM_Core_BAO_FinancialTrxn::getPartialPaymentWithType($this->_contributionId, $enitityType); + $paymentDetails = CRM_Contribute_BAO_Contribution::getPaymentInfo($this->_contributionId, $enitityType, FALSE, TRUE); + + $this->_amtPaid = $paymentDetails['paid']; + $this->_amtTotal = $paymentDetails['total']; + + if (!empty($paymentInfo['refund_due'])) { + $this->_refund = $paymentInfo['refund_due']; + $this->_paymentType = 'refund'; + } + elseif (!empty($paymentInfo['amount_owed'])) { + $this->_owed = $paymentInfo['amount_owed']; + $this->_paymentType = 'owed'; + } + } + + if (!empty($params['contact_id'])) { + $this->_contactId = $params['contact_id']; + } + + if ($creditCardMode) { + $this->_mode = $creditCardMode; + } + + // Required because processCreditCard calls set method on this. + $_SERVER['REQUEST_METHOD'] = 'GET'; + $this->controller = new CRM_Core_Controller(); + + $this->_fields = array(); + $this->submit($params); + } + } diff --git a/CRM/Price/BAO/LineItem.php b/CRM/Price/BAO/LineItem.php index 56694bd71c..e1b629c4a7 100644 --- a/CRM/Price/BAO/LineItem.php +++ b/CRM/Price/BAO/LineItem.php @@ -555,7 +555,7 @@ WHERE li.contribution_id = %1"; if (!$entityId) { $priceSetDetails = CRM_Price_BAO_PriceSet::getDefaultPriceSet($entityTable); - $totalAmount = CRM_Utils_Array::value('total_amount', $params); + $totalAmount = CRM_Utils_Array::value('partial_payment_total', $params, CRM_Utils_Array::value('total_amount', $params)); $financialType = CRM_Utils_Array::value('financial_type_id', $params); foreach ($priceSetDetails as $values) { if ($entityTable == 'membership') { diff --git a/tests/phpunit/CRM/Contribute/Form/AdditionalPaymentTest.php b/tests/phpunit/CRM/Contribute/Form/AdditionalPaymentTest.php new file mode 100644 index 0000000000..50ec1fdf86 --- /dev/null +++ b/tests/phpunit/CRM/Contribute/Form/AdditionalPaymentTest.php @@ -0,0 +1,352 @@ +createLoggedInUser(); + + $this->_individualId = $this->individualCreate(); + $this->_params = array( + 'total_amount' => 100, + 'currency' => 'USD', + 'contact_id' => $this->_individualId, + 'financial_type_id' => 1, + ); + $this->_processorParams = array( + 'domain_id' => 1, + 'name' => 'Dummy', + 'payment_processor_type_id' => 10, + 'financial_account_id' => 12, + 'is_active' => 1, + 'user_name' => '', + 'url_site' => 'http://dummy.com', + 'url_recur' => 'http://dummy.com', + 'billing_mode' => 1, + ); + + $instruments = $this->callAPISuccess('contribution', 'getoptions', array('field' => 'payment_instrument_id')); + $this->paymentInstruments = $instruments['values']; + + $this->paymentProcessor = $this->dummyProcessorCreate(); + $processor = $this->paymentProcessor->getPaymentProcessor(); + $this->paymentProcessorID = $processor['id']; + } + + /** + * Clean up after each test. + */ + public function tearDown() { + $this->quickCleanUpFinancialEntities(); + parent::tearDown(); + } + + /** + * Test the submit function that completes the partially paid Contribution using Credit Card. + + public function testAddPaymentUsingCreditCardForPartialyPaidContribution() { + $this->createContribution('Partially paid'); + + // pay additional amount by using Credit Card + $this->submitPayment(70, 'live'); + $this->checkResults(array(30, 70), 2); + } + */ + + /** + * Test the submit function that completes the partially paid Contribution. + */ + public function testAddPaymentForPartialyPaidContribution() { + $this->createContribution('Partially paid'); + + // pay additional amount + $this->submitPayment(70); + $this->checkResults(array(30, 70), 2); + } + + /** + * Test the submit function that completes the partially paid Contribution with multiple payments. + */ + public function testMultiplePaymentForPartialyPaidContribution() { + $this->createContribution('Partially paid'); + + // pay additional amount + $this->submitPayment(50); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + // pay additional amount + $this->submitPayment(20); + $this->checkResults(array(30, 50, 20), 3); + } + /** + * Test the submit function that completes the partially paid Contribution with multiple payments. + * + public function testMultiplePaymentForPartialyPaidContributionWithOneCreditCardPayment() { + $this->createContribution('Partially paid'); + + // pay additional amount + $this->submitPayment(50); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + // pay additional amount by using credit card + $this->submitPayment(20, 'live'); + $this->checkResults(array(30, 50, 20), 3); + } + + + /** + * Test the submit function that completes the pending pay later Contribution using Credit Card. + * + public function testAddPaymentUsingCreditCardForPendingPayLaterContribution() { + $this->createContribution('Pending'); + + // pay additional amount by using Credit Card + $this->submitPayment(100, 'live'); + $this->checkResults(array(100), 1); + } + */ + + /** + * Test the submit function that completes the pending pay later Contribution. + */ + public function testAddPaymentForPendingPayLaterContribution() { + $this->createContribution('Pending'); + + // pay additional amount + $this->submitPayment(70); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + // pay additional amount + $this->submitPayment(30); + $this->checkResults(array(30, 70), 2); + } + + /** + * Test the submit function that completes the pending pay later Contribution with multiple payments. + */ + public function testMultiplePaymentForPendingPayLaterContribution() { + $this->createContribution('Pending'); + + // pay additional amount + $this->submitPayment(40); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + $this->submitPayment(20); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + $this->submitPayment(30); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + $this->submitPayment(10); + $this->checkResults(array(40, 20, 30, 10), 4); + } + + /** + * Test the submit function that completes the pending pay later Contribution with multiple payments. + * + public function testMultiplePaymentForPendingPayLaterContributionWithOneCreditCardPayment() { + $this->createContribution('Pending'); + + // pay additional amount + $this->submitPayment(50); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + $this->submitPayment(20, 'live'); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + $this->submitPayment(20); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertEquals('Partially paid', $contribution['contribution_status']); + + $this->submitPayment(10, 'live'); + $this->checkResults(array(50, 20, 20, 10), 4); + } + */ + + /** + * Function to create pending pay later or partially paid conntribution. + * + * @param string $typeofContribution + * + */ + public function createContribution($typeofContribution = 'Pending') { + if ($typeofContribution == 'Partially paid') { + $contributionParams = array_merge($this->_params, array( + 'partial_payment_total' => 100.00, + 'partial_amount_pay' => 30, + 'contribution_status_id' => 1, + )); + } + elseif ($typeofContribution == 'Pending') { + $contributionParams = array_merge($this->_params, array( + 'contribution_status_id' => 2, + 'is_pay_later' => 1, + )); + } + $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams); + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $contribution['id'])); + $this->assertNotEmpty($contribution); + $this->assertEquals($typeofContribution, $contribution['contribution_status']); + $this->_contributionId = $contribution['id']; + } + + /** + * Function to submit payments for contribution. + * + * @param float $amount + * Payment Amount + * @param string $mode + * Mode of Payment + * + */ + public function submitPayment($amount, $mode = NULL) { + $form = new CRM_Contribute_Form_AdditionalPayment(); + + $submitParams = array( + 'contribution_id' => $this->_contributionId, + 'contact_id' => $this->_individualId, + 'total_amount' => $amount, + 'currency' => 'USD', + 'financial_type_id' => 1, + 'receive_date' => '04/21/2015', + 'receive_date_time' => '11:27PM', + 'trxn_date' => '2017-04-11 13:05:11', + ); + if ($mode) { + $submitParams += array( + 'payment_instrument_id' => array_search('Credit card', $this->paymentInstruments), + 'payment_processor_id' => $this->paymentProcessorID, + 'credit_card_exp_date' => array('M' => 5, 'Y' => 2025), + 'credit_card_number' => '411111111111111', + 'cvv2' => 234, + 'credit_card_type' => 'Visa', + 'billing_city-5' => 'Vancouver', + 'billing_state_province_id-5' => 1059, + 'billing_postal_code-5' => 1321312, + 'billing_country_id-5' => 1228, + ); + } + else { + $submitParams += array( + 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), + 'check_number' => 'check-12345', + ); + } + $form->testSubmit($submitParams, $mode); + } + + /** + * Function to check result. + * + * @param array $amounts + * Array of payment amount for contribution + * @param int $count + * Number payment for contribution + * + */ + public function checkResults($amounts, $count) { + $contribution = $this->callAPISuccessGetSingle('Contribution', array('id' => $this->_contributionId)); + $this->assertNotEmpty($contribution); + $this->assertEquals('Completed', $contribution['contribution_status']); + + $this->callAPISuccessGetCount('EntityFinancialTrxn', array( + 'entity_table' => "civicrm_contribution", + 'entity_id' => $this->_contributionId, + 'financial_trxn_id.is_payment' => 1, + 'financial_trxn_id.total_amount' => array('IN' => $amounts), + ), $count); + } + +} -- 2.25.1