diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index f768c0a53466..9adcded1a491 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -4168,6 +4168,39 @@ public static function getPaymentInfo($id, $component, $getTrxnInfo = FALSE, $us return $info; } + /** + * Get the outstanding balance on a contribution. + * + * @param int $contributionId + * @param float $contributionTotal + * Optional amount to override the saved amount paid (e.g if calculating what it WILL be). + * + * @return float + */ + public static function getContributionBalance($contributionId, $contributionTotal = NULL) { + + if ($contributionTotal === NULL) { + $contributionTotal = CRM_Price_BAO_LineItem::getLineTotal($contributionId); + } + $statusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'); + $refundStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Refunded'); + + $sqlFtTotalAmt = " +SELECT SUM(ft.total_amount) +FROM civicrm_financial_trxn ft + INNER JOIN civicrm_entity_financial_trxn eft ON (ft.id = eft.financial_trxn_id AND eft.entity_table = 'civicrm_contribution' AND eft.entity_id = {$contributionId}) +WHERE ft.is_payment = 1 + AND ft.status_id IN ({$statusId}, {$refundStatusId}) +"; + + $ftTotalAmt = CRM_Core_DAO::singleValueQuery($sqlFtTotalAmt); + if (!$ftTotalAmt) { + $ftTotalAmt = 0; + } + $currency = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'currency'); + return CRM_Utils_Money::subtractCurrencies($contributionTotal, $ftTotalAmt, $currency); + } + /** * Get the tax amount (misnamed function). * diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php index ed56fd99e680..a3cdf1e0d994 100644 --- a/CRM/Contribute/Form/Contribution/Main.php +++ b/CRM/Contribute/Form/Contribution/Main.php @@ -1313,13 +1313,13 @@ public function assignFormVariablesByContributionID() { CRM_Core_Error::statusBounce(ts("Returning since there is no contact attached to this contribution id.")); } - $payment = CRM_Contribute_BAO_Contribution::getPaymentInfo($this->_ccid, 'contribution'); + $paymentBalance = CRM_Contribute_BAO_Contribution::getContributionBalance($this->_ccid); //bounce if the contribution is not pending. - if (empty($payment['balance'])) { + if ((int) $paymentBalance <= 0) { CRM_Core_Error::statusBounce(ts("Returning since contribution has already been handled.")); } - if (!empty($payment['total'])) { - $this->_pendingAmount = $payment['total']; + if (!empty($paymentBalance)) { + $this->_pendingAmount = $paymentBalance; $this->assign('pendingAmount', $this->_pendingAmount); } diff --git a/CRM/Core/BAO/FinancialTrxn.php b/CRM/Core/BAO/FinancialTrxn.php index 78c51313ac8e..9f4e5f1aead7 100644 --- a/CRM/Core/BAO/FinancialTrxn.php +++ b/CRM/Core/BAO/FinancialTrxn.php @@ -466,26 +466,10 @@ public static function getPartialPaymentWithType($entityId, $entityName = 'parti $financialTypeId = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'financial_type_id'); if ($contributionId && $financialTypeId) { - $statusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'); - $refundStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Refunded'); - if (empty($lineItemTotal)) { - $lineItemTotal = CRM_Price_BAO_LineItem::getLineTotal($contributionId); - } - $sqlFtTotalAmt = " -SELECT SUM(ft.total_amount) -FROM civicrm_financial_trxn ft - INNER JOIN civicrm_entity_financial_trxn eft ON (ft.id = eft.financial_trxn_id AND eft.entity_table = 'civicrm_contribution' AND eft.entity_id = {$contributionId}) -WHERE ft.is_payment = 1 - AND ft.status_id IN ({$statusId}, {$refundStatusId}) -"; - - $ftTotalAmt = CRM_Core_DAO::singleValueQuery($sqlFtTotalAmt); - if (!$ftTotalAmt) { - $ftTotalAmt = 0; - } - $currency = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'currency'); - $value = $paymentVal = CRM_Utils_Money::subtractCurrencies($lineItemTotal, $ftTotalAmt, $currency); + $value = CRM_Contribute_BAO_Contribution::getContributionBalance($contributionId, $lineItemTotal); + + $paymentVal = $value; if ($returnType) { $value = array(); if ($paymentVal < 0) { @@ -494,9 +478,6 @@ public static function getPartialPaymentWithType($entityId, $entityName = 'parti elseif ($paymentVal > 0) { $value['amount_owed'] = $paymentVal; } - elseif ($lineItemTotal == $ftTotalAmt) { - $value['full_paid'] = $ftTotalAmt; - } } } return $value; diff --git a/tests/phpunit/CRM/Event/BAO/AdditionalPaymentTest.php b/tests/phpunit/CRM/Event/BAO/AdditionalPaymentTest.php index 85d8043d7486..82ac169c4855 100644 --- a/tests/phpunit/CRM/Event/BAO/AdditionalPaymentTest.php +++ b/tests/phpunit/CRM/Event/BAO/AdditionalPaymentTest.php @@ -207,8 +207,7 @@ public function testAddPartialPayment() { $amtPaid = 60; $balance = $feeAmt - $amtPaid; $result = $this->addParticipantWithPayment($feeAmt, $amtPaid); - extract($result); - $paymentInfo = CRM_Contribute_BAO_Contribution::getPaymentInfo($participant['id'], 'event'); + $paymentInfo = CRM_Contribute_BAO_Contribution::getPaymentInfo($result['participant']['id'], 'event'); // amount checking $this->assertEquals(round($paymentInfo['total']), $feeAmt, 'Total amount recorded is not proper'); @@ -216,7 +215,7 @@ public function testAddPartialPayment() { $this->assertEquals(round($paymentInfo['balance']), $balance, 'Balance amount is not proper'); // status checking - $this->assertEquals($participant['participant_status_id'], 14, 'Status record is not proper for participant'); + $this->assertEquals($result['participant']['participant_status_id'], 14, 'Status record is not proper for participant'); $this->assertEquals($result['contribution']['contribution_status_id'], 8, 'Status record is not proper for contribution'); }