From 6d5ed9ac325f031f884eb6e21b05d07d44d66c9d Mon Sep 17 00:00:00 2001 From: olayiwola-compucorp Date: Tue, 26 Mar 2024 11:06:01 +0100 Subject: [PATCH] Ensure payment amount are allocated to lineitems without roundoff error --- CRM/Financial/BAO/Payment.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/CRM/Financial/BAO/Payment.php b/CRM/Financial/BAO/Payment.php index 3d39dda7556d..dae03a868ca5 100644 --- a/CRM/Financial/BAO/Payment.php +++ b/CRM/Financial/BAO/Payment.php @@ -547,6 +547,7 @@ protected static function getPayableLineItems($params, $contribution): 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; } @@ -567,19 +568,32 @@ protected static function getPayableLineItems($params, $contribution): 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'] = $lineItem['tax_amount'] * ($params['total_amount'] / $contribution['total_amount']); + $lineItems[$lineItemID]['tax_allocation'] = round($lineItem['tax_amount'] * ($params['total_amount'] / $contribution['total_amount']), 2); } } } + if (empty($lineItemOverrides)) { + $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; }