diff --git a/tests/phpunit/CRM/Member/Form/MembershipTest.php b/tests/phpunit/CRM/Member/Form/MembershipTest.php index 09476038bc60..c5702268c72d 100644 --- a/tests/phpunit/CRM/Member/Form/MembershipTest.php +++ b/tests/phpunit/CRM/Member/Form/MembershipTest.php @@ -138,6 +138,7 @@ public function tearDown() { ) ); $this->callAPISuccess('contact', 'delete', array('id' => 17, 'skip_undelete' => TRUE)); + $this->callAPISuccess('contact', 'delete', array('id' => 18, 'skip_undelete' => TRUE)); $this->callAPISuccess('contact', 'delete', array('id' => 23, 'skip_undelete' => TRUE)); $this->callAPISuccess('relationship_type', 'delete', array('id' => 20)); } @@ -684,6 +685,126 @@ public function testFormStatusUpdate() { $this->assertEquals($membership['status_id'], $previousStatus); } + /** + * CRM-20946: Test the financial entires especially the reversed amount, + * after related Contribution is cancelled + */ + public function testFinancialEntiriesOnCancelledContribution() { + $form = $this->getForm(NULL); + $form->preProcess(); + $this->createLoggedInUser(); + + // create a price-set of price-field of type checkbox and each price-option corrosponds to a membership type + $priceSet = $this->callAPISuccess('price_set', 'create', array( + 'is_quick_config' => 0, + 'extends' => 'CiviMember', + 'financial_type_id' => 1, + 'title' => 'my Page', + )); + $priceSetID = $priceSet['id']; + // create respective checkbox price-field + $priceField = $this->callAPISuccess('price_field', 'create', array( + 'price_set_id' => $priceSetID, + 'label' => 'Memberships', + 'html_type' => 'Checkbox', + )); + $priceFieldID = $priceField['id']; + // create two price options, each represent a membership type of amount 20 and 10 respectively + $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array( + 'price_set_id' => $priceSetID, + 'price_field_id' => $priceField['id'], + 'label' => 'Long Haired Goat', + 'amount' => 20, + 'financial_type_id' => 'Donation', + 'membership_type_id' => 15, + 'membership_num_terms' => 1, + ) + ); + $pfvIDs = array($priceFieldValue['id'] => 1); + $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array( + 'price_set_id' => $priceSetID, + 'price_field_id' => $priceField['id'], + 'label' => 'Shoe-eating Goat', + 'amount' => 10, + 'financial_type_id' => 'Donation', + 'membership_type_id' => 35, + 'membership_num_terms' => 2, + ) + ); + $pfvIDs[$priceFieldValue['id']] = 1; + + // register for both of this memberships via backoffice membership form submission + $params = array( + 'cid' => $this->_individualId, + 'join_date' => date('m/d/Y', time()), + 'start_date' => '', + 'end_date' => '', + // This format reflects the 23 being the organisation & the 25 being the type. + "price_$priceFieldID" => $pfvIDs, + "price_set_id" => $priceSetID, + 'membership_type_id' => array(1 => 0), + 'auto_renew' => '0', + 'max_related' => '', + 'num_terms' => '2', + 'source' => '', + 'total_amount' => '30.00', + //Member dues, see data.xml + 'financial_type_id' => '2', + 'soft_credit_type_id' => '', + 'soft_credit_contact_id' => '', + 'payment_instrument_id' => 4, + 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>', + 'receipt_text_signup' => 'Thank you text', + 'payment_processor_id' => $this->_paymentProcessorID, + 'record_contribution' => TRUE, + 'trxn_id' => 777, + 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_DAO_Contribution', 'contribution_status_id', 'Pending'), + 'billing_first_name' => 'Test', + 'billing_middlename' => 'Last', + 'billing_street_address-5' => '10 Test St', + 'billing_city-5' => 'Test', + 'billing_state_province_id-5' => '1003', + 'billing_postal_code-5' => '90210', + 'billing_country_id-5' => '1228', + ); + $form->testSubmit($params); + + // cancel the related contribution via API + $contribution = $this->callAPISuccessGetSingle('Contribution', array( + 'contact_id' => $this->_individualId, + 'contribution_status_id' => 2, + )); + $this->callAPISuccess('Contribution', 'create', array( + 'id' => $contribution['id'], + 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_DAO_Contribution', 'contribution_status_id', 'Cancelled'), + )); + + // fetch financial_trxn ID of the related contribution + $sql = "SELECT financial_trxn_id + FROM civicrm_entity_financial_trxn + WHERE entity_id = %1 AND entity_table = 'civicrm_contribution' + ORDER BY id DESC + LIMIT 1 + "; + $financialTrxnID = CRM_Core_DAO::singleValueQuery($sql, array(1 => array($contribution['id'], 'Int'))); + + // fetch entity_financial_trxn records and compare their cancelled records + $result = $this->callAPISuccess('EntityFinancialTrxn', 'Get', array( + 'financial_trxn_id' => $financialTrxnID, + 'entity_table' => 'civicrm_financial_item', + )); + // compare the reversed amounts of respective memberships after cancelling contribution + $cancelledMembershipAmounts = array( + -20.00, + -10.00, + ); + $count = 0; + foreach ($result['values'] as $record) { + $this->assertEquals($cancelledMembershipAmounts[$count], $record['amount']); + $count++; + } + } + /** * Test the submit function of the membership form. */ diff --git a/tests/phpunit/CRM/Member/Form/dataset/data.xml b/tests/phpunit/CRM/Member/Form/dataset/data.xml index 65a279e9548b..9655cea473ad 100644 --- a/tests/phpunit/CRM/Member/Form/dataset/data.xml +++ b/tests/phpunit/CRM/Member/Form/dataset/data.xml @@ -10,6 +10,15 @@ first_name="Joe" last_name="Blow" /> + <civicrm_contact + id="18" + contact_type="Individual" + is_opt_out="0" + display_name="Alex Blow" + sort_name="Blow, Alex" + first_name="Alex" + last_name="Blow" + /> <civicrm_contact id="23" contact_type="Organization" @@ -17,6 +26,13 @@ display_name="Save The Dollars" organization_name="Save The Dollars" /> + <civicrm_contact + id="32" + contact_type="Organization" + is_opt_out="0" + display_name="Save The Rupees" + organization_name="Save The Rupees" + /> <civicrm_relationship_type id="20" @@ -48,5 +64,15 @@ relationship_type_id="20" financial_type_id="2" /> - + <civicrm_membership_type + id="35" + domain_id="1" + name="AnnualRolling1" + member_of_contact_id="32" + duration_unit="year" + duration_interval="1" + period_type="rolling" + relationship_type_id="20" + financial_type_id="2" + /> </dataset>