diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index 9440b936b0bb..c7a653d6a0dc 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -4477,6 +4477,92 @@ public static function isSingleLineItem($id) { return ($lineItemCount == 1); } + /** + * Function to process additional payment for partial and refund contributions. + * + * This function is called via API payment.create function. All forms that add payments + * should use this. + * + * @param array $params + * - contribution_id + * - total_amount + * - line_item + * @return \CRM_Financial_DAO_FinancialTrxn + * + * @throws \API_Exception + * @throws \CRM_Core_Exception + */ + public static function addPayment($params) { + $contribution = civicrm_api3('Contribution', 'getsingle', ['id' => $params['contribution_id']]); + $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus($contribution['contribution_status_id'], 'name'); + if ($contributionStatus != 'Partially paid' + && !($contributionStatus == 'Pending' && $contribution['is_pay_later'] == TRUE) + ) { + throw new API_Exception('Please select a contribution which has a partial or pending payment'); + } + else { + // Check if pending contribution + $fullyPaidPayLater = FALSE; + if ($contributionStatus == 'Pending') { + $cmp = bccomp($contribution['total_amount'], $params['total_amount'], 5); + // Total payment amount is the whole amount paid against pending contribution + if ($cmp == 0 || $cmp == -1) { + civicrm_api3('Contribution', 'completetransaction', ['id' => $contribution['id']]); + // Get the trxn + $trxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC'); + $ftParams = ['id' => $trxnId['financialTrxnId']]; + $trxn = CRM_Core_BAO_FinancialTrxn::retrieve($ftParams, CRM_Core_DAO::$_nullArray); + $fullyPaidPayLater = TRUE; + } + else { + civicrm_api3('Contribution', 'create', + [ + 'id' => $contribution['id'], + 'contribution_status_id' => 'Partially paid', + ] + ); + } + } + if (!$fullyPaidPayLater) { + $trxn = CRM_Core_BAO_FinancialTrxn::getPartialPaymentTrxn($contribution, $params); + if (CRM_Utils_Array::value('line_item', $params) && !empty($trxn)) { + foreach ($params['line_item'] as $values) { + foreach ($values as $id => $amount) { + $p = ['id' => $id]; + $check = CRM_Price_BAO_LineItem::retrieve($p, $defaults); + if (empty($check)) { + throw new API_Exception('Please specify a valid Line Item.'); + } + // get financial item + $sql = "SELECT fi.id + FROM civicrm_financial_item fi + INNER JOIN civicrm_line_item li ON li.id = fi.entity_id and fi.entity_table = 'civicrm_line_item' + WHERE li.contribution_id = %1 AND li.id = %2"; + $sqlParams = [ + 1 => [$params['contribution_id'], 'Integer'], + 2 => [$id, 'Integer'], + ]; + $fid = CRM_Core_DAO::singleValueQuery($sql, $sqlParams); + // Record Entity Financial Trxn + $eftParams = [ + 'entity_table' => 'civicrm_financial_item', + 'financial_trxn_id' => $trxn->id, + 'amount' => $amount, + 'entity_id' => $fid, + ]; + civicrm_api3('EntityFinancialTrxn', 'create', $eftParams); + } + } + } + elseif (!empty($trxn)) { + CRM_Contribute_BAO_Contribution::assignProportionalLineItems($params, $trxn->id, $contribution['total_amount']); + } + } + } + return $trxn; + + } + /** * Complete an order. * diff --git a/api/v3/Payment.php b/api/v3/Payment.php index 1c144b43bc07..b80e899aa6ca 100644 --- a/api/v3/Payment.php +++ b/api/v3/Payment.php @@ -132,74 +132,8 @@ function civicrm_api3_payment_create(&$params) { civicrm_api3('Payment', 'cancel', $params); $params['total_amount'] = $amount; } - // Get contribution - $contribution = civicrm_api3('Contribution', 'getsingle', array('id' => $params['contribution_id'])); - $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus($contribution['contribution_status_id'], 'name'); - if ($contributionStatus != 'Partially paid' - && !($contributionStatus == 'Pending' && $contribution['is_pay_later'] == TRUE) - ) { - throw new API_Exception('Please select a contribution which has a partial or pending payment'); - } - else { - // Check if pending contribution - $fullyPaidPayLater = FALSE; - if ($contributionStatus == 'Pending') { - $cmp = bccomp($contribution['total_amount'], $params['total_amount'], 5); - // Total payment amount is the whole amount paid against pending contribution - if ($cmp == 0 || $cmp == -1) { - civicrm_api3('Contribution', 'completetransaction', array('id' => $contribution['id'])); - // Get the trxn - $trxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC'); - $ftParams = array('id' => $trxnId['financialTrxnId']); - $trxn = CRM_Core_BAO_FinancialTrxn::retrieve($ftParams, CRM_Core_DAO::$_nullArray); - $fullyPaidPayLater = TRUE; - } - else { - civicrm_api3('Contribution', 'create', - array( - 'id' => $contribution['id'], - 'contribution_status_id' => 'Partially paid', - ) - ); - } - } - if (!$fullyPaidPayLater) { - $trxn = CRM_Core_BAO_FinancialTrxn::getPartialPaymentTrxn($contribution, $params); - if (CRM_Utils_Array::value('line_item', $params) && !empty($trxn)) { - foreach ($params['line_item'] as $values) { - foreach ($values as $id => $amount) { - $p = array('id' => $id); - $check = CRM_Price_BAO_LineItem::retrieve($p, $defaults); - if (empty($check)) { - throw new API_Exception('Please specify a valid Line Item.'); - } - // get financial item - $sql = "SELECT fi.id - FROM civicrm_financial_item fi - INNER JOIN civicrm_line_item li ON li.id = fi.entity_id and fi.entity_table = 'civicrm_line_item' - WHERE li.contribution_id = %1 AND li.id = %2"; - $sqlParams = array( - 1 => array($params['contribution_id'], 'Integer'), - 2 => array($id, 'Integer'), - ); - $fid = CRM_Core_DAO::singleValueQuery($sql, $sqlParams); - // Record Entity Financial Trxn - $eftParams = array( - 'entity_table' => 'civicrm_financial_item', - 'financial_trxn_id' => $trxn->id, - 'amount' => $amount, - 'entity_id' => $fid, - ); - civicrm_api3('EntityFinancialTrxn', 'create', $eftParams); - } - } - } - elseif (!empty($trxn)) { - // Assign the lineitems proportionally - CRM_Contribute_BAO_Contribution::assignProportionalLineItems($params, $trxn->id, $contribution['total_amount']); - } - } - } + $trxn = CRM_Contribute_BAO_Contribution::addPayment($params); + $values = array(); _civicrm_api3_object_to_array_unique_fields($trxn, $values[$trxn->id]); return civicrm_api3_create_success($values, $params, 'Payment', 'create', $trxn); diff --git a/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php b/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php new file mode 100644 index 000000000000..522a553d415a --- /dev/null +++ b/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php @@ -0,0 +1,91 @@ +id; + $supporterProfile = CRM_Core_DAO::createTestObject('CRM_Core_DAO_UFGroup'); + $supporterProfileId = $supporterProfile->id; + + $params = array( + 'entity_table' => 'civicrm_contribution_page', + 'entity_id' => $contribPageId, + 'supporter_profile_id' => $supporterProfileId, + 'target_entity_id' => 1, + 'is_approval_needed' => 1, + 'is_tellfriend_enabled' => 1, + 'tellfriend_limit' => 1, + 'link_text' => 'Create your own PCP', + 'is_active' => 1, + ); + + return $params; + } + + /** + * Build and return pcp params. + * + * Create the necessary initial objects for a pcp page, then return the + * params needed to create the pcp page. + */ + public function pcpParams() { + $contact = CRM_Core_DAO::createTestObject('CRM_Contact_DAO_Contact'); + $contactId = $contact->id; + $contribPage = CRM_Core_DAO::createTestObject('CRM_Contribute_DAO_ContributionPage'); + $contribPageId = $contribPage->id; + + $params = array( + 'contact_id' => $contactId, + 'status_id' => '1', + 'title' => 'My PCP', + 'intro_text' => 'Hey you, contribute now!', + 'page_text' => 'You better give more.', + 'donate_link_text' => 'Donate Now', + 'page_id' => $contribPageId, + 'is_thermometer' => 1, + 'is_honor_roll' => 1, + 'goal_amount' => 10000.00, + 'is_active' => 1, + ); + + return $params; + } + +}