From 0ae57b4c2b796d5f6f2511d227d2684d27cfe12b Mon Sep 17 00:00:00 2001 From: Klaas Eikelboom Date: Tue, 3 Jan 2017 05:50:39 -0500 Subject: [PATCH] CRM-19273 Fix in the usage of insertedLines and added test --- CRM/Event/BAO/Participant.php | 17 +- tests/phpunit/CRM/Event/BAO/CRM19273Test.php | 248 +++++++++++++++++++ 2 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 tests/phpunit/CRM/Event/BAO/CRM19273Test.php diff --git a/CRM/Event/BAO/Participant.php b/CRM/Event/BAO/Participant.php index 2b4dbc402a..54ca31c2f4 100644 --- a/CRM/Event/BAO/Participant.php +++ b/CRM/Event/BAO/Participant.php @@ -1906,7 +1906,12 @@ WHERE civicrm_participant.contact_id = {$contactID} AND // if found in submitted items, do not use it for new item creations if (in_array($previousLineItem['price_field_value_id'], $submittedFieldValueIds)) { // if submitted line items are existing don't fire INSERT query - unset($insertLines[$previousLineItem['price_field_value_id']]); + if ($previousLineItem['line_total'] != 0) { + unset($insertLines[$previousLineItem['price_field_value_id']]); + } + else { + $insertLines[$previousLineItem['price_field_value_id']]['skip'] = TRUE; + } // for updating the line items i.e. use-case - once deselect-option selecting again if (($previousLineItem['line_total'] != $submittedLineItems[$previousLineItem['price_field_value_id']]['line_total']) || ($submittedLineItems[$previousLineItem['price_field_value_id']]['line_total'] == 0 && $submittedLineItems[$previousLineItem['price_field_value_id']]['qty'] == 1) || @@ -2026,10 +2031,12 @@ WHERE (li.entity_table = 'civicrm_participant' AND li.entity_id = {$participantI // insert new line items if (!empty($insertLines)) { foreach ($insertLines as $valueId => $lineParams) { - $lineParams['entity_table'] = 'civicrm_participant'; - $lineParams['entity_id'] = $participantId; - $lineParams['contribution_id'] = $contributionId; - $lineObj = CRM_Price_BAO_LineItem::create($lineParams); + if (!array_key_exists('skip', $lineParams)) { + $lineParams['entity_table'] = 'civicrm_participant'; + $lineParams['entity_id'] = $participantId; + $lineParams['contribution_id'] = $contributionId; + $lineObj = CRM_Price_BAO_LineItem::create($lineParams); + } } } diff --git a/tests/phpunit/CRM/Event/BAO/CRM19273Test.php b/tests/phpunit/CRM/Event/BAO/CRM19273Test.php new file mode 100644 index 0000000000..0b04ba580a --- /dev/null +++ b/tests/phpunit/CRM/Event/BAO/CRM19273Test.php @@ -0,0 +1,248 @@ +cleanup(); + $this->_contactId = $this->individualCreate(); + $event = $this->eventCreate(array('is_monetary' => 1)); + $this->_eventId = $event['id']; + $this->_priceSetID = $this->eventPriceSetCreate(); + CRM_Price_BAO_PriceSet::addTo('civicrm_event', $this->_eventId, $this->_priceSetID); + $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(); + } + + /** + * Clean up after test. + */ + public function tearDown() { + $this->eventDelete($this->_eventId); + $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. + * + * @todo resolve this with parent function. + * + * @param int $amount + * @param int $min_fee + * @return int + */ + protected function eventPriceSetCreate($amount = 0, $min_fee = 0) { + + $paramsSet['title'] = 'Two Options'; + $paramsSet['name'] = CRM_Utils_String::titleToVar('Two Options'); + $paramsSet['is_active'] = FALSE; + $paramsSet['extends'] = 1; + + $priceSet = CRM_Price_BAO_PriceSet::create($paramsSet); + + $paramsField = array( + 'label' => 'Price Field', + 'name' => CRM_Utils_String::titleToVar('Two Options'), + 'html_type' => 'Radio', + //'price' => $feeTotal, + 'option_label' => array('1' => 'Expensive Room', '2' => "Cheap Room", '3' => 'Very Expensive'), + 'option_value' => array('1' => 'E', '2' => 'C', '3' => 'V'), + 'option_name' => array('1' => 'Expensive', '2' => "Cheap", "3" => "Very Expensive"), + 'option_weight' => array('1' => 1, '2' => 2, '3' => 3), + 'option_amount' => array('1' => $this->_expensiveFee, '2' => $this->_cheapFee, '3' => $this->_veryExpensive), + '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' => $this->getFinancialTypeId('Event Fee'), + ); + $field = CRM_Price_BAO_PriceField::create($paramsField); + $this->priceSetFieldID = $field->id; + return $priceSet->id; + } + + /** + * Get the total for the invoice. + * + * @param int $contributionId + * @return mixed + */ + private function contributionInvoice($contributionId) { + + $query = " + SELECT SUM(line_total) total + FROM civicrm_line_item + WHERE entity_table = 'civicrm_participant' + AND entity_id = {$contributionId}"; + $dao = CRM_Core_DAO::executeQuery($query); + + $this->assertTrue($dao->fetch(), "Succeeded retrieving invoicetotal"); + return $dao->total; + } + + /** + * Get the total income from the participant record. + * + * @param int $participantId + * + * @return mixed + */ + private function totalIncome($participantId) { + + // @todo use INNER JOINS, this is not our style. + $query = " + SELECT SUM(et.amount) total + FROM civicrm_entity_financial_trxn et + , civicrm_financial_item fi + , civicrm_line_item li + WHERE et.entity_table='civicrm_financial_item' + AND fi.id = et.entity_id + AND fi.entity_table='civicrm_line_item' + AND fi.entity_id = li.id + AND li.entity_table = 'civicrm_participant' + AND li.entity_id = ${participantId} + "; + $dao = CRM_Core_DAO::executeQuery($query); + + $this->assertTrue($dao->fetch(), "Succeeded retrieving total Income"); + return $dao->total; + } + + /** + * Check the relevant entity balances. + * + * @param float $amount + */ + private function balanceCheck($amount) { + $this->assertEquals($this->contributionInvoice($this->contributionID), $amount, "Invoice must a total of $amount"); + $this->assertEquals($this->totalIncome($this->participantID), $amount, "The recorded income must be $amount "); + $this->assertEquals($this->totalIncome($this->contributionID), $amount, "The accumulated assets must be $amount "); + } + + /** + * Prepare records for editing. + */ + public function registerParticipantAndPay() { + $params = array( + 'send_receipt' => 1, + 'is_test' => 0, + 'is_pay_later' => 0, + 'event_id' => $this->_eventId, + 'register_date' => date('Y-m-d') . " 00:00:00", + 'role_id' => 1, + 'status_id' => 1, + 'source' => 'Event_' . $this->_eventId, + 'contact_id' => $this->_contactId, + //'fee_level' => CRM_Core_DAO::VALUE_SEPARATOR.'Expensive Room'.CRM_Core_DAO::VALUE_SEPARATOR, + ); + $participant = $this->callAPISuccess('Participant', 'create', $params); + $this->_participantId = $participant['id']; + + $actualPaidAmt = $this->_expensiveFee; + + $contributionParams = array( + 'total_amount' => $actualPaidAmt, + 'source' => 'Testset with information', + 'currency' => 'USD', + 'non_deductible_amount' => 'null', + 'receipt_date' => date('Y-m-d') . " 00:00:00", + 'contact_id' => $this->_contactId, + 'financial_type_id' => 4, + 'payment_instrument_id' => 4, + 'contribution_status_id' => 1, + 'receive_date' => date('Y-m-d') . " 00:00:00", + 'skipLineItem' => 1, + 'partial_payment_total' => $this->_expensiveFee, + 'partial_amount_pay' => $actualPaidAmt, + ); + + $contribution = CRM_Contribute_BAO_Contribution::create($contributionParams); + $this->_contributionId = $contribution->id; + + $this->callAPISuccess('participant_payment', 'create', array( + 'participant_id' => $this->_participantId, + 'contribution_id' => $this->_contributionId, + )); + + $PSparams['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, $PSparams, $lineItem); + $lineItemVal[$this->_priceSetID] = $lineItem; + CRM_Price_BAO_LineItem::processPriceSet($participant['id'], $lineItemVal, $contribution, 'civicrm_participant'); + + $this->contributionID = $this->callAPISuccessGetValue('Contribution', array('return' => 'id')); + $this->participantID = $this->callAPISuccessGetValue('Participant', array('return' => 'id')); + $this->balanceCheck($this->_expensiveFee); + } + + public function testCRM19273() { + + $PSparams['price_1'] = 2; + $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant'); + CRM_Event_BAO_Participant::changeFeeSelections($PSparams, $this->participantID, $this->_contributionId, $this->_feeBlock, $lineItem, $this->_expensiveFee, $this->_priceSetID); + $this->balanceCheck($this->_cheapFee); + + $PSparams['price_1'] = 1; + $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant'); + CRM_Event_BAO_Participant::changeFeeSelections($PSparams, $this->participantID, $this->_contributionId, $this->_feeBlock, $lineItem, $this->_expensiveFee, $this->_priceSetID); + $this->balanceCheck($this->_expensiveFee); + + $PSparams['price_1'] = 3; + $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant'); + + CRM_Event_BAO_Participant::changeFeeSelections($PSparams, $this->participantID, $this->_contributionId, $this->_feeBlock, $lineItem, $this->_expensiveFee, $this->_priceSetID); + $this->balanceCheck($this->_veryExpensive); + } + +} -- 2.25.1