diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php index 4f34f2243db6..f9e24c14d942 100644 --- a/CRM/Price/BAO/PriceSet.php +++ b/CRM/Price/BAO/PriceSet.php @@ -676,79 +676,7 @@ public static function processAmount($fields, &$params, &$lineItem, $priceSetID continue; } - switch ($field['html_type']) { - case 'Text': - $firstOption = reset($field['options']); - $params["price_{$id}"] = [$firstOption['id'] => $params["price_{$id}"]]; - CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, CRM_Utils_Array::value('partial_payment_total', $params)); - $optionValueId = key($field['options']); - - if (CRM_Utils_Array::value('name', $field['options'][$optionValueId]) === 'contribution_amount') { - $taxRates = CRM_Core_PseudoConstant::getTaxRates(); - if (array_key_exists($params['financial_type_id'], $taxRates)) { - $field['options'][key($field['options'])]['tax_rate'] = $taxRates[$params['financial_type_id']]; - $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($field['options'][$optionValueId]['amount'], $field['options'][$optionValueId]['tax_rate']); - $field['options'][$optionValueId]['tax_amount'] = round($taxAmount['tax_amount'], 2); - } - } - if (!empty($field['options'][$optionValueId]['tax_rate'])) { - $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); - } - $totalPrice += $lineItem[$firstOption['id']]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[key($field['options'])]); - break; - - case 'Radio': - //special case if user select -none- - if ($params["price_{$id}"] <= 0) { - break; - } - $params["price_{$id}"] = [$params["price_{$id}"] => 1]; - $optionValueId = CRM_Utils_Array::key(1, $params["price_{$id}"]); - - // CRM-18701 Sometimes the amount in the price set is overridden by the amount on the form. - // This is notably the case with memberships and we need to put this amount - // on the line item rather than the calculated amount. - // This seems to only affect radio link items as that is the use case for the 'quick config' - // set up (which allows a free form field). - // @todo $priceSetID is a pseudoparam for permit override - we should stop passing it where we - // don't specifically need it & find a better way where we do. - $amount_override = NULL; - - if ($priceSetID && count(self::filterPriceFieldsFromParams($priceSetID, $params)) === 1) { - $amount_override = CRM_Utils_Array::value('partial_payment_total', $params, CRM_Utils_Array::value('total_amount', $params)); - } - CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, $amount_override); - if (!empty($field['options'][$optionValueId]['tax_rate'])) { - $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); - if ($amount_override) { - $lineItem[$optionValueId]['line_total'] = $lineItem[$optionValueId]['unit_price'] = CRM_Utils_Rule::cleanMoney($lineItem[$optionValueId]['line_total'] - $lineItem[$optionValueId]['tax_amount']); - } - } - $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]); - break; - - case 'Select': - $params["price_{$id}"] = [$params["price_{$id}"] => 1]; - $optionValueId = CRM_Utils_Array::key(1, $params["price_{$id}"]); - - CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, CRM_Utils_Array::value('partial_payment_total', $params)); - if (!empty($field['options'][$optionValueId]['tax_rate'])) { - $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); - } - $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]); - break; - - case 'CheckBox': - - CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, CRM_Utils_Array::value('partial_payment_total', $params)); - foreach ($params["price_{$id}"] as $optionId => $option) { - if (!empty($field['options'][$optionId]['tax_rate'])) { - $lineItem = self::setLineItem($field, $lineItem, $optionId, $totalTax); - } - $totalPrice += $lineItem[$optionId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionId]); - } - break; - } + list($params, $lineItem, $totalTax, $totalPrice) = self::getLine($params, $lineItem, $priceSetID, $field, $id, $totalPrice); } $amount_level = []; @@ -1751,4 +1679,96 @@ protected static function reformatUsedByFormsWithEntityData($forms) { return $usedBy; } + /** + * Get the relevant line item. + * + * Note this is part of code being cleaned up / refactored & may change. + * + * @param array $params + * @param array $lineItem + * @param int $priceSetID + * @param array $field + * @param int $id + * @param float $totalPrice + * + * @return array + */ + protected static function getLine(&$params, &$lineItem, $priceSetID, $field, $id, $totalPrice): array { + $totalTax = 0; + switch ($field['html_type']) { + case 'Text': + $firstOption = reset($field['options']); + $params["price_{$id}"] = [$firstOption['id'] => $params["price_{$id}"]]; + CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, CRM_Utils_Array::value('partial_payment_total', $params)); + $optionValueId = key($field['options']); + + if (CRM_Utils_Array::value('name', $field['options'][$optionValueId]) === 'contribution_amount') { + $taxRates = CRM_Core_PseudoConstant::getTaxRates(); + if (array_key_exists($params['financial_type_id'], $taxRates)) { + $field['options'][key($field['options'])]['tax_rate'] = $taxRates[$params['financial_type_id']]; + $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($field['options'][$optionValueId]['amount'], $field['options'][$optionValueId]['tax_rate']); + $field['options'][$optionValueId]['tax_amount'] = round($taxAmount['tax_amount'], 2); + } + } + if (!empty($field['options'][$optionValueId]['tax_rate'])) { + $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); + } + $totalPrice += $lineItem[$firstOption['id']]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[key($field['options'])]); + break; + + case 'Radio': + //special case if user select -none- + if ($params["price_{$id}"] <= 0) { + break; + } + $params["price_{$id}"] = [$params["price_{$id}"] => 1]; + $optionValueId = CRM_Utils_Array::key(1, $params["price_{$id}"]); + + // CRM-18701 Sometimes the amount in the price set is overridden by the amount on the form. + // This is notably the case with memberships and we need to put this amount + // on the line item rather than the calculated amount. + // This seems to only affect radio link items as that is the use case for the 'quick config' + // set up (which allows a free form field). + // @todo $priceSetID is a pseudoparam for permit override - we should stop passing it where we + // don't specifically need it & find a better way where we do. + $amount_override = NULL; + + if ($priceSetID && count(self::filterPriceFieldsFromParams($priceSetID, $params)) === 1) { + $amount_override = CRM_Utils_Array::value('partial_payment_total', $params, CRM_Utils_Array::value('total_amount', $params)); + } + CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, $amount_override); + if (!empty($field['options'][$optionValueId]['tax_rate'])) { + $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); + if ($amount_override) { + $lineItem[$optionValueId]['line_total'] = $lineItem[$optionValueId]['unit_price'] = CRM_Utils_Rule::cleanMoney($lineItem[$optionValueId]['line_total'] - $lineItem[$optionValueId]['tax_amount']); + } + } + $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]); + break; + + case 'Select': + $params["price_{$id}"] = [$params["price_{$id}"] => 1]; + $optionValueId = CRM_Utils_Array::key(1, $params["price_{$id}"]); + + CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, CRM_Utils_Array::value('partial_payment_total', $params)); + if (!empty($field['options'][$optionValueId]['tax_rate'])) { + $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); + } + $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]); + break; + + case 'CheckBox': + + CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, CRM_Utils_Array::value('partial_payment_total', $params)); + foreach ($params["price_{$id}"] as $optionId => $option) { + if (!empty($field['options'][$optionId]['tax_rate'])) { + $lineItem = self::setLineItem($field, $lineItem, $optionId, $totalTax); + } + $totalPrice += $lineItem[$optionId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionId]); + } + break; + } + return [$params, $lineItem, $totalTax, $totalPrice]; + } + } diff --git a/tests/phpunit/CRM/Event/Form/ParticipantTest.php b/tests/phpunit/CRM/Event/Form/ParticipantTest.php index d142ddab3121..efa3efd53a5d 100644 --- a/tests/phpunit/CRM/Event/Form/ParticipantTest.php +++ b/tests/phpunit/CRM/Event/Form/ParticipantTest.php @@ -203,6 +203,24 @@ public function testSubmitWithPayment($thousandSeparator) { $contribution = $this->callAPISuccessGetSingle('Contribution', []); $this->assertEquals(1550.55, $contribution['total_amount']); $this->assertEquals('Debit Card', $contribution['payment_instrument']); + $lineItem = $this->callAPISuccessGetSingle('LineItem', []); + $expected = [ + 'contribution_id' => $contribution['id'], + 'entity_table' => 'civicrm_participant', + 'qty' => 1, + 'label' => 'bug', + 'unit_price' => 1550.55, + 'line_total' => 1550.55, + 'participant_count' => 0, + 'price_field_id' => $this->_ids['price_field'][0], + 'price_value_id' => $this->_ids['price_field_value'][1], + 'tax_amount' => 0, + // Interestingly the financial_type_id set in this test is ignored but currently locking in what is happening with this test so setting to 'actual' + 'financial_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Event fee') + ]; + foreach ($expected as $key => $value) { + $this->assertEquals($value, $lineItem[$key]); + } } /**