Skip to content

Commit

Permalink
Fixes getTemplateContribution to use a more reliable way to load line…
Browse files Browse the repository at this point in the history
… items

My efforts to add testing a 'deprecate weird stuff' have identified an odd and fragile
flow for the line items in getTemplateContribution. It calls
getLineItemsByContributionID which, as it turns out, substitues the
actual entity table with 'civicrm_contribution'.

Then this line of weird handling swoops in and saves the day.

https://github.com/civicrm/civicrm-core/pull/20775/files#diff-a16d4d7449cf5f3a0616d1d282a32f27ab6d3f7d2726d076c02ad1d4d655af41R393

This switches us to something cleaner than just loads the line items (with v4 LineItem.get) and
no weird handling
  • Loading branch information
eileenmcnaughton committed Jul 12, 2021
1 parent 09e790b commit 4df23f2
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 103 deletions.
1 change: 0 additions & 1 deletion CRM/Contribute/BAO/Contribution.php
Original file line number Diff line number Diff line change
Expand Up @@ -2497,7 +2497,6 @@ public static function contributionCount($contactId, $includeSoftCredit = TRUE)
* The count is out on how correct related entities wind up in this case.
*/
protected static function repeatTransaction(array $input, array $contributionParams) {

$templateContribution = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution(
(int) $contributionParams['contribution_recur_id'],
array_filter([
Expand Down
62 changes: 11 additions & 51 deletions CRM/Contribute/BAO/ContributionRecur.php
Original file line number Diff line number Diff line change
Expand Up @@ -453,16 +453,25 @@ public static function getTemplateContribution(int $id, $overrides = []): array
}
if ($templateContributions->count()) {
$templateContribution = $templateContributions->first();
$lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($templateContribution['id']);
$order = new CRM_Financial_BAO_Order();
$order->setTemplateContributionID($templateContribution['id']);
$order->setOverrideFinancialTypeID($overrides['financial_type_id'] ?? NULL);
$order->setOverridableFinancialTypeID($templateContribution['financial_type_id']);
$order->setOverrideTotalAmount($overrides['total_amount'] ?? NULL);
$order->setIsPermitOverrideFinancialTypeForMultipleLines(FALSE);
$lineItems = $order->getLineItems();
// We only permit the financial type to be overridden for single line items.
// Otherwise we need to figure out a whole lot of extra complexity.
// It's not UI-possible to alter financial_type_id for recurring contributions
// with more than one line item.
// The handling of the line items is managed in BAO_Order so this
// is whether we should override on the contribution. Arguably the 2 should
// be decoupled.
if (count($lineItems) > 1 && isset($overrides['financial_type_id'])) {
unset($overrides['financial_type_id']);
}
$result = array_merge($templateContribution, $overrides);
$result['line_item'] = self::reformatLineItemsForRepeatContribution($result['total_amount'], $result['financial_type_id'], $lineItems, (array) $templateContribution);
$result['line_item'][$order->getPriceSetID()] = $lineItems;
// If the template contribution was made on-behalf then add the
// relevant values to ensure the activity reflects that.
$relatedContact = CRM_Contribute_BAO_Contribution::getOnbehalfIds($result['id']);
Expand Down Expand Up @@ -993,53 +1002,4 @@ public static function buildOptions($fieldName, $context = NULL, $props = []) {
return CRM_Core_PseudoConstant::get(__CLASS__, $fieldName, $params, $context);
}

/**
* Reformat line items for getTemplateContribution / repeat contribution.
*
* This is an extraction and may be subject to further cleanup.
*
* @param float $total_amount
* @param int $financial_type_id
* @param array $lineItems
* @param array $originalContribution
*
* @return array
*/
protected static function reformatLineItemsForRepeatContribution($total_amount, $financial_type_id, array $lineItems, array $originalContribution): array {
$lineSets = [];
if (count($lineItems) == 1) {
foreach ($lineItems as $index => $lineItem) {
if ($lineItem['financial_type_id'] != $originalContribution['financial_type_id']) {
// CRM-20685, Repeattransaction produces incorrect Financial Type ID (in specific circumstance) - if number of lineItems = 1, So this conditional will set the financial_type_id as the original if line_item and contribution comes with different data.
$financial_type_id = $lineItem['financial_type_id'];
}
if ($financial_type_id) {
// CRM-17718 allow for possibility of changed financial type ID having been set prior to calling this.
$lineItem['financial_type_id'] = $financial_type_id;
}
$taxAmountMatches = FALSE;
if ((!empty($lineItem['tax_amount']) && ($lineItem['line_total'] + $lineItem['tax_amount']) == $total_amount)) {
$taxAmountMatches = TRUE;
}
if ($lineItem['line_total'] != $total_amount && !$taxAmountMatches) {
// We are dealing with a changed amount! Per CRM-16397 we can work out what to do with these
// if there is only one line item, and the UI should prevent this situation for those with more than one.
$lineItem['line_total'] = $total_amount;
$lineItem['unit_price'] = round($total_amount / $lineItem['qty'], 2);
}
$priceField = new CRM_Price_DAO_PriceField();
$priceField->id = $lineItem['price_field_id'];
$priceField->find(TRUE);
$lineSets[$priceField->price_set_id][$lineItem['price_field_id']] = $lineItem;
}
}
// CRM-19309 if more than one then just pass them through:
elseif (count($lineItems) > 1) {
foreach ($lineItems as $index => $lineItem) {
$lineSets[$index][$lineItem['price_field_id']] = $lineItem;
}
}
return $lineSets;
}

}
Loading

0 comments on commit 4df23f2

Please sign in to comment.