Skip to content

Commit

Permalink
Fix unit test to not rely on hacking the DB to have ids for price set…
Browse files Browse the repository at this point in the history
…s & associated values
  • Loading branch information
eileenmcnaughton committed Feb 8, 2018
1 parent f4743a1 commit 9a0ae97
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 50 deletions.
97 changes: 97 additions & 0 deletions CRM/Price/BAO/LineItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,56 @@ public static function getLineItemArray(&$params, $entityId = NULL, $entityTable
}
}

/**
* Build the line items for the submitted price field.
*
* This is when first building them - not an update where an entityId is already present
* as this is intended as a subfunction of that. Ideally getLineItemArray would call this
* (resolving to the same format regardless of what type of price set is being used first).
*
* @param array $priceParams
* These are per the way the form processes them - ie
* ['price_1' => 1, 'price_2' => 8]
* This would mean price field id 1, option 1 (or 1 unit if using is_enter_qty).
* @param float|NULL $overrideAmount
* Optional override of the amount.
*
* @param int|NULL $financialTypeID
* Financial type ID is the type should be overridden.
*
* @return array
* Line items formatted for processing. These will look like
* [4] => ['price_field_id' => 4, 'price_field_value_id' => x, 'label....qty...unit_price...line_total...financial_type_id]
* [5] => ['price_field_id' => 5, 'price_field_value_id' => x, 'label....qty...unit_price...line_total...financial_type_id]
*
*/
public static function buildLineItemsForSubmittedPriceField($priceParams, $overrideAmount = NULL, $financialTypeID = NULL) {
$lineItems = array();
foreach ($priceParams as $key => $value) {
$priceField = self::getPriceFieldMetaData($key);

if ($priceField['html_type'] === 'Text') {
$valueSpec = reset($priceField['values']);
}
else {
$valueSpec = $priceField['values'][$value];
}
$qty = $priceField['is_enter_qty'] ? $value : 1;
$lineItems[$priceField['id']] = [
'price_field_id' => $priceField['id'],
'price_field_value_id' => $valueSpec['id'],
'label' => $valueSpec['label'],
'qty' => $qty,
'unit_price' => $overrideAmount ? : $valueSpec['amount'],
'line_total' => $qty * ($overrideAmount ? : $valueSpec['amount']),
'financial_type_id' => $financialTypeID ? : $valueSpec['financial_type_id'],
'membership_type_id' => $valueSpec['membership_type_id'],
'price_set_id' => $priceField['price_set_id'],
];
}
return $lineItems;
}

/**
* Function to update related contribution of a entity and
* add/update/cancel financial records
Expand Down Expand Up @@ -1023,6 +1073,53 @@ protected function updateEntityRecordOnChangeFeeSelection($inputParams, $entityI
}
}

/**
* Get the metadata for a price field.
*
* @param string|int $key
* Price field id. Either as an integer or as 'price_4' where 4 is the id
*
* @return array
* Metadata for the price field with a values key for option values.
*/
protected static function getPriceFieldMetaData($key) {
$priceFieldID = str_replace('price_', '', $key);
if (!isset(Civi::$statics[__CLASS__]['price_fields'][$priceFieldID])) {
$values = civicrm_api3('PriceFieldValue', 'get', [
'price_field_id' => $priceFieldID,
'return' => [
'id',
'amount',
'financial_type_id',
'membership_type_id',
'label',
'price_field_id',
'price_field_id.price_set_id',
'price_field_id.html_type',
'is_enter_qty',
],
]);
$firstValue = reset($values['values']);
$values = $values['values'];
foreach ($values as $index => $value) {
// Let's be nice to calling functions & ensure membership_type_id is set
// so they don't have to handle notices on it. Handle one place not many.
if (!isset($value['membership_type_id'])) {
$values[$index]['membership_type_id'] = NULL;
}
}

Civi::$statics[__CLASS__]['price_fields'][$priceFieldID] = [
'price_set_id' => $firstValue['price_field_id.price_set_id'],
'id' => $firstValue['price_field_id'],
'html_type' => $firstValue['price_field_id.html_type'],
'is_enter_qty' => !empty($firstValue['is_enter_qty']),
'values' => $values,
];
}
return Civi::$statics[__CLASS__]['price_fields'][$priceFieldID];
}

/**
* Helper function to retrieve financial trxn parameters to reverse
* for given financial item identified by $financialItemID
Expand Down
100 changes: 50 additions & 50 deletions tests/phpunit/CRM/Event/BAO/ChangeFeeSelectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class CRM_Event_BAO_ChangeFeeSelectionTest extends CiviUnitTestCase {
protected $_cheapFee = 80;
protected $_expensiveFee = 100;
protected $_veryExpensive = 120;
protected $expensiveFeeValueID;
protected $cheapFeeValueID;
protected $veryExpensiveFeeValueID;

/**
* @var int
Expand All @@ -32,7 +35,6 @@ class CRM_Event_BAO_ChangeFeeSelectionTest extends CiviUnitTestCase {
*/
public function setUp() {
parent::setUp();
$this->cleanup();
$this->_contactId = $this->individualCreate();
$event = $this->eventCreate(array('is_monetary' => 1));
$this->_eventId = $event['id'];
Expand All @@ -41,7 +43,6 @@ public function setUp() {
$priceSet = CRM_Price_BAO_PriceSet::getSetDetail($this->_priceSetID, TRUE, FALSE);
$priceSet = CRM_Utils_Array::value($this->_priceSetID, $priceSet);
$this->_feeBlock = CRM_Utils_Array::value('fields', $priceSet);
$this->registerParticipantAndPay();
}

/**
Expand All @@ -52,24 +53,6 @@ public function tearDown() {
$this->quickCleanUpFinancialEntities();
}

/**
* Remove default price field stuff.
*
* This is not actually good. However resolving this requires
* a lot more fixes & we have a bit of work to do on event tests.
*
* @throws \Exception
*/
protected function cleanup() {
$this->quickCleanup(
array(
'civicrm_price_field_value',
'civicrm_price_field',
'civicrm_price_set',
)
);
}

/**
* Create an event with a price set.
*
Expand Down Expand Up @@ -129,6 +112,26 @@ protected function priceSetCreate($type = 'Radio') {
);
}
$field = CRM_Price_BAO_PriceField::create($paramsField);
$values = $this->callAPISuccess('PriceFieldValue', 'get',[
'price_field_id' => $field->id,
'return' => ['id', 'label']
]);
foreach ($values['values'] as $value) {
switch ($value['label']) {
case 'Expensive Room' :
$this->expensiveFeeValueID = $value['id'];
break;

case 'Cheap Room' :
$this->cheapFeeValueID = $value['id'];
break;

case 'Very Expensive' :
$this->veryExpensiveFeeValueID = $value['id'];
break;
}
}

$this->priceSetFieldID = $field->id;
return $priceSet->id;
}
Expand Down Expand Up @@ -224,28 +227,31 @@ public function registerParticipantAndPay($actualPaidAmt = NULL) {
'contribution_id' => $this->_contributionId,
));

$priceSetParams['price_1'] = 1; // 1 is the option of the expensive room
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_PriceSet::processAmount($this->_feeBlock, $priceSetParams, $lineItem);
$lineItemVal[$this->_priceSetID] = $lineItem;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->expensiveFeeValueID;

$lineItems = CRM_Price_BAO_LineItem::buildLineItemsForSubmittedPriceField($priceSetParams);
CRM_Price_BAO_PriceSet::processAmount($this->_feeBlock, $priceSetParams, $lineItems);
$lineItemVal[$this->_priceSetID] = $lineItems;
CRM_Price_BAO_LineItem::processPriceSet($participant['id'], $lineItemVal, $this->getContributionObject($contribution['id']), 'civicrm_participant');
$this->balanceCheck($this->_expensiveFee);
}

public function testCRM19273() {
$priceSetParams['price_1'] = 2;
$this->registerParticipantAndPay();

$priceSetParams['price_' . $this->priceSetFieldID] = $this->cheapFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, $this->_expensiveFee);
$this->balanceCheck($this->_cheapFee);

$priceSetParams['price_1'] = 1;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->expensiveFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');

CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, $this->_expensiveFee);

$this->balanceCheck($this->_expensiveFee);

$priceSetParams['price_1'] = 3;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->veryExpensiveFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, $this->_expensiveFee);
$this->balanceCheck($this->_veryExpensive);
Expand All @@ -259,7 +265,7 @@ public function testCRM21245() {
$partiallyPaidContribuitonStatus = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Partially paid');
$this->assertEquals($this->callAPISuccessGetValue('Contribution', array('id' => $this->_contributionId, 'return' => 'contribution_status_id')), $partiallyPaidContribuitonStatus);

$priceSetParams['price_1'] = 3;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->veryExpensiveFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
$this->assertEquals($this->callAPISuccessGetValue('Contribution', array('id' => $this->_contributionId, 'return' => 'contribution_status_id')), $partiallyPaidContribuitonStatus);
Expand All @@ -269,12 +275,13 @@ public function testCRM21245() {
* Test that proper financial items are recorded for cancelled line items
*/
public function testCRM20611() {
$priceSetParams['price_1'] = 1;
$this->registerParticipantAndPay();
$priceSetParams['price_' . $this->priceSetFieldID] = $this->expensiveFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
$this->balanceCheck($this->_expensiveFee);

$priceSetParams['price_1'] = 2;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->cheapFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
$this->balanceCheck($this->_cheapFee);
Expand Down Expand Up @@ -313,16 +320,6 @@ public function testCRM20611() {
* Test to ensure that correct financial records are entered on text price field fee change on event registration
*/
public function testCRM21513() {
$this->quickCleanup(
array(
'civicrm_price_field_value',
'civicrm_price_field',
'civicrm_price_set',
'civicrm_line_item',
'civicrm_financial_item',
)
);

$this->_priceSetID = $this->priceSetCreate('Text');
CRM_Price_BAO_PriceSet::addTo('civicrm_event', $this->_eventId, $this->_priceSetID);
$priceSet = CRM_Price_BAO_PriceSet::getSetDetail($this->_priceSetID, TRUE, FALSE);
Expand All @@ -341,6 +338,7 @@ public function testCRM21513() {
'contact_id' => $this->_contactId,
);
$participant = $this->callAPISuccess('Participant', 'create', $params);
$this->_participantId = $participant['id'];
$contributionParams = array(
'total_amount' => 10,
'source' => 'Testset with information',
Expand All @@ -363,21 +361,21 @@ public function testCRM21513() {
));

// CASE 1: Choose text price qty 1 (x$10 = $10 amount)
$priceSetParams['price_1'] = 1;
$priceSetParams['price_' . $this->priceSetFieldID] = 1;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_PriceSet::processAmount($this->_feeBlock, $priceSetParams, $lineItem);
$lineItemVal[$this->_priceSetID] = $lineItem;
CRM_Price_BAO_LineItem::processPriceSet($this->_participantId, $lineItemVal, $this->getContributionObject($contribution['id']), 'civicrm_participant');

// CASE 2: Choose text price qty 3 (x$10 = $30 amount)
$priceSetParams['price_1'] = 3;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, 0);
$priceSetParams['price_' . $this->priceSetFieldID] = 3;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($participant['id'], 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $participant['id'], 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, 0);

// CASE 3: Choose text price qty 2 (x$10 = $20 amount)
$priceSetParams['price_1'] = 2;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, 0);
$priceSetParams['price_' . $this->priceSetFieldID] = 2;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($participant['id'], 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $participant['id'], 'participant', $this->_contributionId, $this->_feeBlock, $lineItem, 0);

$financialItems = $this->callAPISuccess('FinancialItem', 'Get', array(
'entity_table' => 'civicrm_line_item',
Expand Down Expand Up @@ -421,20 +419,22 @@ public function testCRM21513() {
* CRM-17151: Test that Contribution status change to 'Completed' if balance is zero.
*/
public function testCRM17151() {
$this->registerParticipantAndPay();

$contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
$partiallyPaidStatusId = array_search('Partially paid', $contributionStatuses);
$pendingRefundStatusId = array_search('Pending refund', $contributionStatuses);
$completedStatusId = array_search('Completed', $contributionStatuses);
$this->assertDBCompareValue('CRM_Contribute_BAO_Contribution', $this->_contributionId, 'contribution_status_id', 'id', $completedStatusId, 'Payment t be completed');
$priceSetParams['price_1'] = 2;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->cheapFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
$this->assertDBCompareValue('CRM_Contribute_BAO_Contribution', $this->_contributionId, 'contribution_status_id', 'id', $pendingRefundStatusId, 'Contribution must be refunding');
$priceSetParams['price_1'] = 1;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->expensiveFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
$this->assertDBCompareValue('CRM_Contribute_BAO_Contribution', $this->_contributionId, 'contribution_status_id', 'id', $completedStatusId, 'Contribution must, after complete payment be in state completed');
$priceSetParams['price_1'] = 3;
$priceSetParams['price_' . $this->priceSetFieldID] = $this->veryExpensiveFeeValueID;
$lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_participantId, 'participant');
CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
$this->assertDBCompareValue('CRM_Contribute_BAO_Contribution', $this->_contributionId, 'contribution_status_id', 'id', $partiallyPaidStatusId, 'Partial Paid');
Expand Down

0 comments on commit 9a0ae97

Please sign in to comment.