From b24c057ae422004c823a6785dc58fbf3465dc9ea Mon Sep 17 00:00:00 2001 From: olayiwola-compucorp Date: Mon, 20 May 2024 19:49:05 +0100 Subject: [PATCH] PROD-180: Resolve Issue with Payment Allocation to Contribution Line Item Applying PR https://github.com/civicrm/civicrm-core/pull/29823 Partially Included in 5.74 --- CRM/Financial/BAO/Payment.php | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/CRM/Financial/BAO/Payment.php b/CRM/Financial/BAO/Payment.php index 5b4a2b55b511..269cbc8b40f2 100644 --- a/CRM/Financial/BAO/Payment.php +++ b/CRM/Financial/BAO/Payment.php @@ -45,7 +45,7 @@ public static function create(array $params): CRM_Financial_DAO_FinancialTrxn { $contribution = civicrm_api3('Contribution', 'getsingle', ['id' => $params['contribution_id']]); $contributionStatus = CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contribution['contribution_status_id']); $isPaymentCompletesContribution = self::isPaymentCompletesContribution($params['contribution_id'], $params['total_amount'], $contributionStatus); - $lineItems = self::getPayableLineItems($params); + $lineItems = self::getPayableLineItems($params, $contribution); $whiteList = ['check_number', 'payment_processor_id', 'fee_amount', 'total_amount', 'contribution_id', 'net_amount', 'card_type_id', 'pan_truncation', 'trxn_result_code', 'payment_instrument_id', 'trxn_id', 'trxn_date', 'order_reference']; $paymentTrxnParams = array_intersect_key($params, array_fill_keys($whiteList, 1)); @@ -168,18 +168,13 @@ public static function create(array $params): CRM_Financial_DAO_FinancialTrxn { if ($item['price_field_value_id'] === (int) $value['price_field_value_id'] && in_array($item['financial_item.financial_account_id'], $salesTaxFinancialAccount, TRUE) ) { - // @todo - this is expected to be broken - it should be fixed to - // a) have the getPayableLineItems add the amount to allocate for tax - // b) call EntityFinancialTrxn directly - per above. - // - see https://github.com/civicrm/civicrm-core/pull/14763 - $entityParams = [ - 'contribution_total_amount' => $contribution['total_amount'], - 'trxn_total_amount' => $params['total_amount'], - 'trxn_id' => $trxn->id, - 'line_item_amount' => $item['tax_amount'], + $eftParams = [ + 'entity_table' => 'civicrm_financial_item', + 'financial_trxn_id' => $trxn->id, + 'entity_id' => $item['financial_item.id'], + 'amount' => $value['tax_allocation'], ]; - $eftParams['entity_id'] = $item['financial_item.id']; - CRM_Contribute_BAO_Contribution::createProportionalEntry($entityParams, $eftParams); + civicrm_api3('EntityFinancialTrxn', 'create', $eftParams); } } } @@ -534,11 +529,12 @@ private static function updateContributionStatus(int $contributionID, string $st * - if overrides have been passed in we use those amounts instead. * * @param $params + * @param $contribution * * @return array * @throws \CiviCRM_API3_Exception */ - protected static function getPayableLineItems($params): array { + protected static function getPayableLineItems($params, $contribution): array { $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($params['contribution_id']); $lineItemOverrides = []; if (!empty($params['line_item'])) { @@ -549,6 +545,7 @@ protected static function getPayableLineItems($params): array { } } $outstandingBalance = CRM_Contribute_BAO_Contribution::getContributionBalance($params['contribution_id']); + $isPaymentCompletesContribution = self::isPaymentCompletesContribution($params['contribution_id'], $params['total_amount'], ''); if ($outstandingBalance !== 0.0) { $ratio = $params['total_amount'] / $outstandingBalance; } @@ -569,13 +566,32 @@ protected static function getPayableLineItems($params): array { } else { if (empty($lineItems[$lineItemID]['balance']) && !empty($ratio) && $params['total_amount'] < 0) { - $lineItems[$lineItemID]['allocation'] = $lineItem['subTotal'] * $ratio; + $lineItems[$lineItemID]['allocation'] = round($lineItem['subTotal'] * $ratio, 2); + } + elseif ($isPaymentCompletesContribution) { + $lineItems[$lineItemID]['allocation'] = $lineItems[$lineItemID]['balance']; } else { - $lineItems[$lineItemID]['allocation'] = $lineItems[$lineItemID]['balance'] * $ratio; + $lineItems[$lineItemID]['allocation'] = round($lineItems[$lineItemID]['balance'] * $ratio, 2); + } + + if (!empty($lineItem['tax_amount'])) { + $lineItems[$lineItemID]['tax_allocation'] = round($lineItem['tax_amount'] * ($params['total_amount'] / $contribution['total_amount']), 2); } + } } + + if (empty($lineItemOverrides) && !empty($ratio)) { + $totalTaxAllocation = array_sum(array_column($lineItems, 'tax_allocation')); + $totalAllocation = array_sum(array_column($lineItems, 'allocation')); + $total = $totalTaxAllocation + $totalAllocation; + $leftPayment = $params['total_amount'] - $total; + + // assign any leftover amount, to the last lineitem + $lineItems[$lineItemID]['allocation'] += $leftPayment; + } + return $lineItems; }