After looking at this I think the 'right' answer is to always go to the same function to find out what the amount_level
should be - rather than calculate it on the forms and / or tack it onto the function that derives the line_items
I made this change on the form that was experiencing an issue & added a test.
Elsewhere I just added comments
$lineItem = array();
CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $value, $lineItem[$priceSetId]);
- //unset amount level since we always use quick config price set
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
unset($value['amount_level']);
//CRM-11529 for back office transactions
//when financial_type_id is passed in form, update the
//line items with the financial type selected in form
+ // @todo - create a price set or price field per financial type & simply choose the appropriate
+ // price field rather than working around the fact that each price_field is supposed to have a financial
+ // type & we are allowing that to be overridden.
if (!empty($value['financial_type_id']) && !empty($lineItem[$priceSetId])) {
foreach ($lineItem[$priceSetId] as &$values) {
$values['financial_type_id'] = $value['financial_type_id'];
}
$this->_params['ip_address'] = CRM_Utils_System::ipAddress();
$this->_params['amount'] = $this->_params['total_amount'];
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
$this->_params['amount_level'] = 0;
$this->_params['currencyID'] = CRM_Utils_Array::value('currency',
$this->_params,
}
$this->_params['amount'] = $this->_params['total_amount'];
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
$this->_params['amount_level'] = 0;
$this->_params['description'] = ts("Contribution submitted by a staff person using contributor's credit card");
$this->_params['currencyID'] = CRM_Utils_Array::value('currency',
}
if ($isQuickConfig && !empty($this->_params["price_{$priceField->id}"])) {
if ($this->_values['fee'][$priceField->id]['html_type'] != 'Text') {
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
$this->_params['amount_level'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue',
$this->_params["price_{$priceField->id}"], 'label');
}
$amountID = CRM_Utils_Array::value('amount', $params);
if ($amountID) {
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
$params['amount_level'] = CRM_Utils_Array::value('label', $formValues[$amountID]);
$amount = CRM_Utils_Array::value('value', $formValues[$amountID]);
}
));
}
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
if (isset($this->_params['amount_other']) || isset($this->_params['selectMembership'])) {
$this->_params['amount_level'] = '';
}
$price_set_amount = array();
CRM_Price_BAO_PriceSet::processAmount($price_set['fields'], $event_price_values, $price_set_amount);
$cost = $event_price_values['amount'];
+ // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+ // function to get correct amount level consistently. Remove setting of the amount level in
+ // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+ // to cover all variants.
$amount_level = $event_price_values['amount_level'];
$price_details[$price_set_id] = $price_set_amount;
}
}
}
+ /**
+ * Get the amount level for the event payment.
+ *
+ * The amount level is the string stored on the contribution record that describes the purchase.
+ *
+ * @param array $params
+ * @param int|null $discountID
+ *
+ * @return string
+ */
+ protected function getAmountLevel($params, $discountID) {
+ // @todo move handling of discount ID to the BAO function - preferably by converting it to a price_set with
+ // time settings.
+ if (!empty($this->_values['discount'][$discountID])) {
+ return $this->_values['discount'][$discountID][$params['amount']]['label'];
+ }
+ return CRM_Price_BAO_PriceSet::getAmountLevelText($params);
+ }
+
}
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2015
- * $Id$
- *
*/
/**
- * This class generates form components for processing Event
- *
+ * This class generates form components for processing Event.
*/
class CRM_Event_Form_Registration_AdditionalParticipant extends CRM_Event_Form_Registration {
//added for discount
$discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
-
+ $params['amount_level'] = $this->getAmountLevel($params, $discountId);
if (!empty($this->_values['discount'][$discountId])) {
$params['discount_id'] = $discountId;
- $params['amount_level'] = $this->_values['discount'][$discountId][$params['amount']]['label'];
$params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value'];
}
elseif (empty($params['priceSetId'])) {
- $params['amount_level'] = $this->_values['fee'][$params['amount']]['label'];
$params['amount'] = $this->_values['fee'][$params['amount']]['value'];
}
else {
//added for discount
$discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
-
+ $params['amount_level'] = $this->getAmountLevel($params, $discountId);
if (!empty($this->_values['discount'][$discountId])) {
$params['discount_id'] = $discountId;
- $params['amount_level'] = $this->_values['discount'][$discountId][$params['amount']]['label'];
-
$params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value'];
}
elseif (empty($params['priceSetId'])) {
if (!empty($params['amount'])) {
- $params['amount_level'] = $this->_values['fee'][$params['amount']]['label'];
$params['amount'] = $this->_values['fee'][$params['amount']]['value'];
}
else {
- $params['amount_level'] = $params['amount'] = '';
+ $params['amount'] = '';
}
}
else {
// But, in the interests of being careful when capacity is low - avoiding the known default value
// will get us by.
// Crucially a test has been added so a better solution can be implemented later with some comfort.
+ // @todo - stop setting amount level in this function & call the getAmountLevel function to retrieve it.
if ($values['label'] != ts('Contribution Amount')) {
$amount_level[] = $values['label'] . ' - ' . (float) $values['qty'];
}
if ($totalParticipant > 0) {
$displayParticipantCount = ' Participant Count -' . $totalParticipant;
}
+ // @todo - stop setting amount level in this function & call the getAmountLevel function to retrieve it.
if (!empty($amount_level) && !empty($displayParticipantCount)) {
$params['amount_level'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $amount_level) . $displayParticipantCount . CRM_Core_DAO::VALUE_SEPARATOR;
}
}
}
+ /**
+ * Get the text to record for amount level.
+ *
+ * @param array $params
+ * Submitted parameters
+ * - priceSetId is required to be set in the calling function
+ * (we don't e-notice check it to enforce that - all payments DO have a price set - even if it is the
+ * default one & this function asks that be set if it is the case).
+ *
+ * @return string
+ * Text for civicrm_contribution.amount_level field.
+ */
+ public static function getAmountLevelText($params) {
+ $priceSetID = $params['priceSetId'];
+ $priceFieldSelection = self::filterPriceFieldsFromParams($priceSetID, $params);
+ $priceFieldMetadata = self::getCachedPriceSetDetail($priceSetID);
+ $displayParticipantCount = null;
+ $amount_level = array();
+ foreach ($priceFieldMetadata['fields'] as $field) {
+ if (!empty($priceFieldSelection[$field['id']])) {
+ if ($field['is_enter_qty']) {
+ $qtyString = ' - ' . (float) $params['price_' . $field['id']];
+ }
+ // We deliberately & specifically exclude contribution amount as it has a specific meaning.
+ // ie. it represents the default price field for a contribution. Another approach would be not
+ // to give it a label if we don't want it to show.
+ if ($field['label'] != ts('Contribution Amount')) {
+ $amount_level[] = $field['label'] . $qtyString;
+ }
+ }
+ }
+ return CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $amount_level) . $displayParticipantCount . CRM_Core_DAO::VALUE_SEPARATOR;
+ }
+
+ /**
+ * Get the fields relevant to the price field from the parameters.
+ *
+ * E.g we are looking for price_5 => 7 out of a big array of input parameters.
+ *
+ * @param int $priceSetID
+ * @param array $params
+ *
+ * @return array
+ * Price fields found in the params array
+ */
+ public static function filterPriceFieldsFromParams($priceSetID, $params) {
+ $priceSet = self::getCachedPriceSetDetail($priceSetID);
+ $return = array();
+ foreach ($priceSet['fields'] as $field) {
+ if (!empty($params['price_' . $field['id']])) {
+ $return[$field['id']] = $params['price_' . $field['id']];
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Wrapper for getSetDetail with caching.
+ *
+ * We seem to be passing this array around in a painful way - presumably to avoid the hit
+ * of loading it - so lets make it callable with caching.
+ *
+ * Why not just add caching to the other function? We could do - it just seemed a bit unclear the best caching pattern
+ * & the function was already pretty fugly. Also, I feel like we need to migrate the interaction with price-sets into
+ * a more granular interaction - ie. retrieve specific data using specific functions on this class & have the form
+ * think less about the price sets.
+ *
+ * @param int $priceSetID
+ *
+ * @return array
+ */
+ public static function getCachedPriceSetDetail($priceSetID) {
+ $cacheKey = __CLASS__ . __FUNCTION__ . '_' . $priceSetID;
+ $cache = CRM_Utils_Cache::singleton();
+ $values = (array) $cache->get($cacheKey);
+ if (empty($values)) {
+ $data = self::getSetDetail($priceSetID);
+ $values = $data[$priceSetID];
+ $cache->set($cacheKey, $values);
+ }
+ return $values;
+ }
+
/**
* Build the price set form.
*
/**
* Singleton function used to manage this object.
*
- * @return object
+ * @return CRM_Utils_Cache_Interface
*/
public static function &singleton() {
if (self::$_singleton === NULL) {
}
/**
- * helper function to record participant with paid contribution.
- * @param $feeTotal
- * @param $actualPaidAmt
+ * Helper function to record participant with paid contribution.
+ *
+ * @param int $feeTotal
+ * @param int $actualPaidAmt
*
* @return array
* @throws Exception
*/
- public function _addParticipantWithPayment($feeTotal, $actualPaidAmt) {
- // creating price set, price field
- $paramsSet['title'] = 'Price Set';
- $paramsSet['name'] = CRM_Utils_String::titleToVar('Price Set');
- $paramsSet['is_active'] = FALSE;
- $paramsSet['extends'] = 1;
-
- $priceset = CRM_Price_BAO_PriceSet::create($paramsSet);
- CRM_Price_BAO_PriceSet::addTo('civicrm_event', $this->_eventId, $priceset->id);
- $priceSetId = $priceset->id;
-
- //Checking for priceset added in the table.
- $this->assertDBCompareValue('CRM_Price_BAO_PriceSet', $priceSetId, 'title',
- 'id', $paramsSet['title'], 'Check DB for created priceset'
- );
- $paramsField = array(
- 'label' => 'Price Field',
- 'name' => CRM_Utils_String::titleToVar('Price Field'),
- 'html_type' => 'Text',
- 'price' => $feeTotal,
- 'option_label' => array('1' => 'Price Field'),
- 'option_value' => array('1' => $feeTotal),
- 'option_name' => array('1' => $feeTotal),
- 'option_weight' => array('1' => 1),
- 'option_amount' => array('1' => 1),
- 'is_display_amounts' => 1,
- 'weight' => 1,
- 'options_per_line' => 1,
- 'is_active' => array('1' => 1),
- 'price_set_id' => $priceset->id,
- 'is_enter_qty' => 1,
- 'financial_type_id' => CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', 'Event Fee', 'id', 'name'),
- );
-
- $ids = array();
- $pricefield = CRM_Price_BAO_PriceField::create($paramsField, $ids);
-
- //Checking for priceset added in the table.
- $this->assertDBCompareValue('CRM_Price_BAO_PriceField', $pricefield->id, 'label',
- 'id', $paramsField['label'], 'Check DB for created pricefield'
- );
+ protected function addParticipantWithPayment($feeTotal, $actualPaidAmt) {
+ $priceSetId = $this->eventPriceSetCreate($feeTotal);
+ CRM_Price_BAO_PriceSet::addTo('civicrm_event', $this->_eventId, $priceSetId);
// create participant record
$eventId = $this->_eventId;
$feeAmt = 100;
$amtPaid = 60;
$balance = $feeAmt - $amtPaid;
- list($participant, $contribution) = $this->_addParticipantWithPayment($feeAmt, $amtPaid);
+ list($participant, $contribution) = $this->addParticipantWithPayment($feeAmt, $amtPaid);
$paymentInfo = CRM_Contribute_BAO_Contribution::getPaymentInfo($participant['id'], 'event');
// amount checking
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.7 |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2015 |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM. |
+ | |
+ | CiviCRM is free software; you can copy, modify, and distribute it |
+ | under the terms of the GNU Affero General Public License |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
+ | |
+ | CiviCRM is distributed in the hope that it will be useful, but |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
+ | See the GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public |
+ | License and the CiviCRM Licensing Exception along |
+ | with this program; if not, contact CiviCRM LLC |
+ | at info[AT]civicrm[DOT]org. If you have questions about the |
+ | GNU Affero General Public License or the licensing of CiviCRM, |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+require_once 'CiviTest/CiviUnitTestCase.php';
+
+/**
+ * Test class for CRM_Price_BAO_PriceSet.
+ */
+class CRM_Price_BAO_PriceSetTest extends CiviUnitTestCase {
+
+ /**
+ * Sets up the fixtures.
+ */
+ protected function setUp() {
+ parent::setUp();
+ }
+
+ /**
+ * Tears down the fixture.
+ */
+ protected function tearDown() {
+ }
+
+ /**
+ * Test the correct amount level is returned for an event which is not presented as a price set event.
+ *
+ * (these are denoted as 'quickConfig' in the code - but quickConfig is only supposed to refer to the
+ * configuration interface - there should be no different post process.
+ */
+ public function testGetAmountLevelTextAmount() {
+ $priceSetID = $this->eventPriceSetCreate(9);
+ $priceSet = CRM_Price_BAO_PriceSet::getCachedPriceSetDetail($priceSetID);
+ $field = reset($priceSet['fields']);
+ $params = array('priceSetId' => $priceSetID, 'price_' . $field['id'] => 1);
+ $amountLevel = CRM_Price_BAO_PriceSet::getAmountLevelText($params);
+ $this->assertEquals(CRM_Core_DAO::VALUE_SEPARATOR . 'Price Field - 1' . CRM_Core_DAO::VALUE_SEPARATOR, $amountLevel);
+ }
+
+}
'registration_end_date' => 20081015,
'max_participants' => 100,
'event_full_text' => 'Sorry! We are already full',
- 'is_monetory' => 0,
+ 'is_monetary' => 0,
'is_active' => 1,
'is_show_location' => 0,
), $params);
));
}
+ /**
+ * Create a price set for an event.
+ *
+ * @param int $feeTotal
+ *
+ * @return int
+ * Price Set ID.
+ */
+ protected function eventPriceSetCreate($feeTotal) {
+ // creating price set, price field
+ $paramsSet['title'] = 'Price Set';
+ $paramsSet['name'] = CRM_Utils_String::titleToVar('Price Set');
+ $paramsSet['is_active'] = FALSE;
+ $paramsSet['extends'] = 1;
+
+ $priceset = CRM_Price_BAO_PriceSet::create($paramsSet);
+ $priceSetId = $priceset->id;
+
+ //Checking for priceset added in the table.
+ $this->assertDBCompareValue('CRM_Price_BAO_PriceSet', $priceSetId, 'title',
+ 'id', $paramsSet['title'], 'Check DB for created priceset'
+ );
+ $paramsField = array(
+ 'label' => 'Price Field',
+ 'name' => CRM_Utils_String::titleToVar('Price Field'),
+ 'html_type' => 'Text',
+ 'price' => $feeTotal,
+ 'option_label' => array('1' => 'Price Field'),
+ 'option_value' => array('1' => $feeTotal),
+ 'option_name' => array('1' => $feeTotal),
+ 'option_weight' => array('1' => 1),
+ 'option_amount' => array('1' => 1),
+ 'is_display_amounts' => 1,
+ 'weight' => 1,
+ 'options_per_line' => 1,
+ 'is_active' => array('1' => 1),
+ 'price_set_id' => $priceset->id,
+ 'is_enter_qty' => 1,
+ 'financial_type_id' => CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', 'Event Fee', 'id', 'name'),
+ );
+ CRM_Price_BAO_PriceField::create($paramsField);
+
+ return $priceSetId;
+ }
+
}