From b59352030ac28e8e62afd4a0b757669101da38cf Mon Sep 17 00:00:00 2001 From: dpradeep Date: Fri, 5 Sep 2014 20:43:50 +0530 Subject: [PATCH] create api test for contributions for sales tax --- CRM/Contribute/BAO/Contribution.php | 74 +++ api/v3/Contribution.php | 1 + api/v3/LineItem.php | 1 + .../api/v3/TaxContributionPageTest.php | 531 ++++++++++++++++++ 4 files changed, 607 insertions(+) create mode 100644 tests/phpunit/api/v3/TaxContributionPageTest.php diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index 6a9307f646..876a43c175 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -3438,4 +3438,78 @@ WHERE con.id = {$contributionId} return CRM_Utils_Array::value( 'financial_account_id', $result ); } + + function checkTaxAmount($params, $isLineItem = FALSE) { + $taxRates = CRM_Core_PseudoConstant::getTaxRates(); + + // Update contribution + if (!empty($params['id'])) { + $id = $params['id']; + $values = $ids = array(); + $contrbutionParams = array('id' => $id); + $prevContributionValue = CRM_Contribute_BAO_Contribution::getValues($contrbutionParams, $values, $ids); + + // To assign pervious finantial type on update of contribution + if (!isset($params['financial_type_id'])) { + $params['financial_type_id'] = $prevContributionValue->financial_type_id; + } + else if (isset($params['financial_type_id']) && !array_key_exists($params['financial_type_id'], $taxRates)) { + // Assisn tax Amount on update of contrbution + if (!empty($prevContributionValue->tax_amount)) { + $params['tax_amount'] = 'null'; + CRM_Price_BAO_LineItem::getLineItemArray($params, array($params['id'])); + foreach ($params['line_item'] as $setID => $priceField) { + foreach ($priceField as $priceFieldID => $priceFieldValue) { + $params['line_item'][$setID][$priceFieldID]['tax_amount'] = $params['tax_amount']; + } + } + } + } + } + + // New Contrbution and update of contribution with tax rate financial type + if (isset($params['financial_type_id']) && array_key_exists($params['financial_type_id'], $taxRates) && + empty($params['skipLineItem']) && !$isLineItem) + { + $taxRateParams = $taxRates[$params['financial_type_id']]; + $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($params['total_amount'], $taxRateParams); + $params['tax_amount'] = round($taxAmount['tax_amount'], 2); + + // Get Line Item on update of contribution + if (isset($params['id'])) { + CRM_Price_BAO_LineItem::getLineItemArray($params, array($params['id'])); + } + else { + CRM_Price_BAO_LineItem::getLineItemArray($params); + } + foreach ($params['line_item'] as $setID => $priceField) { + foreach ($priceField as $priceFieldID => $priceFieldValue) { + $params['line_item'][$setID][$priceFieldID]['tax_amount'] = $params['tax_amount']; + } + } + $params['total_amount'] = $params['total_amount'] + $params['tax_amount']; + } + else if (isset($params['api.line_item.create'])) { + // Update total amount of contribution using lineItem + $taxAmountArray = array(); + foreach ($params['api.line_item.create'] as $key => $value) { + if (isset($value['financial_type_id']) && array_key_exists($value['financial_type_id'], $taxRates)) { + $taxRate = $taxRates[$value['financial_type_id']]; + $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($value['line_total'], $taxRate); + $taxAmountArray[] = round($taxAmount['tax_amount'], 2); + } + } + $params['tax_amount'] = array_sum($taxAmountArray); + $params['total_amount'] = $params['total_amount'] + $params['tax_amount']; + } + else { + // update line item of contrbution + if (isset($params['financial_type_id']) && array_key_exists($params['financial_type_id'], $taxRates) && $isLineItem) { + $taxRate = $taxRates[$params['financial_type_id']]; + $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($params['line_total'], $taxRate); + $params['tax_amount'] = round($taxAmount['tax_amount'], 2); + } + } + return $params; + } } diff --git a/api/v3/Contribution.php b/api/v3/Contribution.php index 0b5b5acc2b..f9190552e4 100644 --- a/api/v3/Contribution.php +++ b/api/v3/Contribution.php @@ -71,6 +71,7 @@ function civicrm_api3_contribution_create(&$params) { throw new API_Exception($error['contribution_status_id']); } } + $params = CRM_Contribute_BAO_Contribution::checkTaxAmount($params); return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params, 'Contribution'); } diff --git a/api/v3/LineItem.php b/api/v3/LineItem.php index a739beec07..cac7163ed3 100644 --- a/api/v3/LineItem.php +++ b/api/v3/LineItem.php @@ -47,6 +47,7 @@ * @access public */ function civicrm_api3_line_item_create($params) { + $params = CRM_Contribute_BAO_Contribution::checkTaxAmount($params,True); return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params); } diff --git a/tests/phpunit/api/v3/TaxContributionPageTest.php b/tests/phpunit/api/v3/TaxContributionPageTest.php new file mode 100644 index 0000000000..0ab0ac71d2 --- /dev/null +++ b/tests/phpunit/api/v3/TaxContributionPageTest.php @@ -0,0 +1,531 @@ +_individualId = $this->individualCreate(); + $this->_orgId = $this->organizationCreate(NULL); + + $this->params = array( + 'title' => "Test Contribution Page".substr(sha1(rand()), 0, 7), + 'financial_type_id' => 1, + 'payment_processor' => 1, + 'currency' => 'NZD', + 'goal_amount' => 350, + 'is_pay_later' => 1, + 'pay_later_text' => 'I will pay later', + 'pay_later_receipt' => "I will pay later", + 'is_monetary' => TRUE, + 'is_billing_required' => True + ); + + $this->_priceSetParams = array( + 'name' => 'tax_contribution'.substr(sha1(rand()), 0, 7), + 'title' => 'contributiontax'.substr(sha1(rand()), 0, 7), + 'is_active' => 1, + 'help_pre' => "Where does your goat sleep", + 'help_post' => "thank you for your time", + 'extends' => 2, + 'financial_type_id' => 3, + 'is_quick_config' => 0, + 'is_reserved' => 0 + ); + // Financial Account with 20% tax rate + $financialAccountSetparams = array( + #[domain_id] => + 'name' => 'vat full taxrate account'.substr(sha1(rand()), 0, 7), + 'contact_id' => $this->_orgId, + 'financial_account_type_id' => 2, + 'is_tax' => 1, + 'tax_rate' => 20.00, + 'is_reserved' => 0, + 'is_active' => 1, + 'is_default' => 0, + ); + + $financialAccount = $this->callAPISuccess('financial_account', 'create', $financialAccountSetparams); + $this->financialAccountId = $financialAccount['id']; + + // Financial type having 'Sales Tax Account is' with liability financail account + $financialType = array( + 'name' => 'grassvariety1'.substr(sha1(rand()), 0, 7), + 'is_reserved' => 0, + 'is_active' => 1, + ); + $priceField = $this->callAPISuccess('financial_type','create', $financialType); + $this->financialtypeID = $priceField['id']; + $financialRelationParams = array( + 'entity_table' => 'civicrm_financial_type', + 'entity_id' => $this->financialtypeID, + 'account_relationship' => 10, + 'financial_account_id' => $this->financialAccountId + ); + $financialRelation = CRM_Financial_BAO_FinancialTypeAccount::add($financialRelationParams); + + // Financial type with 5% tax rate + $financialAccHalftax = array( + 'name' => 'vat half taxrate account'.substr(sha1(rand()), 0, 7), + 'contact_id' => $this->_orgId, + 'financial_account_type_id' => 2, + 'is_tax' => 1, + 'tax_rate' => 5.00, + 'is_reserved' => 0, + 'is_active' => 1, + 'is_default' => 0 + ); + $halfFinancialAccount = CRM_Financial_BAO_FinancialAccount::add($financialAccHalftax); + $this->halfFinancialAccId = $halfFinancialAccount->id; + $halfFinancialtypeHalftax = array( + 'name' => 'grassvariety2'.substr(sha1(rand()), 0, 7), + 'is_reserved' => 0, + 'is_active' => 1, + ); + + $halfFinancialType = CRM_Financial_BAO_FinancialType::add($halfFinancialtypeHalftax); + $this->halfFinancialTypeId = $halfFinancialType->id ; + $financialRelationHalftax = array( + 'entity_table' => 'civicrm_financial_type', + 'entity_id' => $this->halfFinancialTypeId, + 'account_relationship' => 10, + 'financial_account_id' => $this->halfFinancialAccId + ); + + $halfFinancialRelation = CRM_Financial_BAO_FinancialTypeAccount::add($financialRelationHalftax); + + // Enable component contribute setting + $contributeSetting = array ( + 'invoicing' => 1, + 'invoice_prefix' => 'INV_', + 'credit_notes_prefix' => 'CN_', + 'due_date' => 10, + 'due_date_period' => 'days', + 'notes' => '', + 'is_email_pdf' => 1, + 'tax_term' => 'Sales Tax', + 'tax_display_settings' => 'Inclusive', + ); + $setInvoiceSettings = CRM_Core_BAO_Setting::setItem($contributeSetting, CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); + + // Payment Processor + $paymentProceParams = array( + 'domain_id' => 1, + 'name' => 'dummy'.substr(sha1(rand()), 0, 7), + 'payment_processor_type_id' => 10, + 'financial_account_id' => 12, + 'is_active' => 1, + 'is_default' => 1, + 'is_default' => 1, + 'user_name' => 'dummy', + 'url_site' => 'http://dummy.com', + 'url_recur' => 'http://dummyrecur.com', + 'class_name' => 'Payment_Dummy', + 'billing_mode' => 1, + 'is_recur' => 1, + 'payment_type' => 1 + ); + $result = $this->callAPISuccess('payment_processor', 'create', $paymentProceParams); + $this->_ids['paymentProcessID'] = $result['id']; + require_once 'api/v3/examples/PaymentProcessor/Create.php'; + $this->assertAPISuccess($result); + } + + function tearDown() { + $this->quickCleanup(array( + 'civicrm_contribution', + 'civicrm_contribution_soft', + 'civicrm_event', + 'civicrm_contribution_page', + 'civicrm_participant', + 'civicrm_participant_payment', + 'civicrm_line_item', + 'civicrm_financial_trxn', + 'civicrm_financial_item', + 'civicrm_entity_financial_trxn', + 'civicrm_contact', + 'civicrm_membership', + 'civicrm_membership_payment', + 'civicrm_payment_processor' + )); + CRM_Core_PseudoConstant::flush('taxRates'); + } + + function setUpContributionPage() { + $contributionPageResult = $this->callAPISuccess($this->_entity, 'create', $this->params); + if (empty($this->_ids['price_set'])) { + $priceSet = $this->callAPISuccess('price_set', 'create', $this->_priceSetParams); + $this->_ids['price_set'][] = $priceSet['id']; + } + $priceSetID = $this->_price = reset($this->_ids['price_set']); + CRM_Price_BAO_PriceSet::addTo('civicrm_contribution_page', $contributionPageResult['id'], $priceSetID ); + + if (empty($this->_ids['price_field'])) { + $priceField = $this->callAPISuccess('price_field', 'create', array( + 'price_set_id' => $priceSetID, + 'label' => 'Goat Breed', + 'html_type' => 'Radio', + )); + $this->_ids['price_field'] = array($priceField['id']); + } + if (empty($this->_ids['price_field_value'])) { + $this->callAPISuccess('price_field_value', 'create', array( + 'price_set_id' => $priceSetID, + 'price_field_id' => $priceField['id'], + 'label' => 'Long Haired Goat', + 'amount' => 100, + 'financial_type_id' => $this->financialtypeID + )); + $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array( + 'price_set_id' => $priceSetID, + 'price_field_id' => $priceField['id'], + 'label' => 'Shoe-eating Goat', + 'amount' => 300, + 'financial_type_id' => $this->halfFinancialTypeId + )); + $this->_ids['price_field_value'] = array($priceFieldValue['id']); + } + $this->_ids['contribution_page'] = $contributionPageResult['id']; + } + + /** + * online and offline contrbution from above created contrbution page + */ + function testCreateContributionOnline() { + $this->setUpContributionPage(); + $params = array( + 'contact_id' => $this->_individualId, + 'receive_date' => '20120511', + 'total_amount' => 100.00, + 'financial_type_id' => $this->financialtypeID, + 'contribution_page_id' => $this->_ids['contribution_page'], + 'payment_processor' => $this->_ids['paymentProcessID'], + 'trxn_id' => 12345, + 'invoice_id' => 67890, + 'source' => 'SSF', + 'contribution_status_id' => 1 + ); + + $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__, __FILE__); + $this->_ids['contributionId'] = $contribution['id']; + $this->assertEquals($contribution['values'][$contribution['id']]['contact_id'], $this->_individualId, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 120.00, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['financial_type_id'],$this->financialtypeID, 'In line ' . __LINE__ ); + $this->assertEquals($contribution['values'][$contribution['id']]['trxn_id'], 12345, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['invoice_id'], 67890, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['source'], 'SSF', 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['tax_amount'], 20, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status_id'], 1, 'In line ' . __LINE__); + $this->_checkFinancialRecords($contribution, 'online'); + } + + function testCreateContributionChainedLineItems() { + $this->setUpContributionPage(); + $params = array( + 'contact_id' => $this->_individualId, + 'receive_date' => '20120511', + 'total_amount' => 400.00, + 'financial_type_id' => $this->financialtypeID, + 'trxn_id' => 12345, + 'invoice_id' => 67890, + 'source' => 'SSF', + 'contribution_status_id' => 1, + 'skipLineItem' => 1, + 'api.line_item.create' => array( + array( + 'price_field_id' => $this->_ids['price_field'], + 'qty' => 1, + 'line_total' => '100', + 'unit_price' => '100', + 'financial_type_id' => $this->financialtypeID, + ), + array( + 'price_field_id' => $this->_ids['price_field'], + 'qty' => 1, + 'line_total' => '300', + 'unit_price' => '300', + 'financial_type_id' => $this->halfFinancialTypeId, + ), + ), + ); + + $description = "Create Contribution with Nested Line Items"; + $subfile = "CreateWithNestedLineItems"; + $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__,__FILE__, $description, $subfile); + + $lineItems = $this->callAPISuccess('line_item','get',array( + 'entity_id' => $contribution['id'], + 'contribution_id' => $contribution['id'], + 'entity_table' => 'civicrm_contribution', + 'sequential' => 1, + )); + $this->assertEquals(2, $lineItems['count']); + } + + function testCreateContributionPayLaterOnline() { + $this->setUpContributionPage(); + $params = array( + 'contact_id' => $this->_individualId, + 'receive_date' => '20120511', + 'total_amount' => 100.00, + 'financial_type_id' => $this->financialtypeID, + 'contribution_page_id' => $this->_ids['contribution_page'], + 'trxn_id' => 12345, + 'is_pay_later' => 1, + 'invoice_id' => 67890, + 'source' => 'SSF', + 'contribution_status_id' => 2, + ); + $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__, __FILE__); + $this->assertEquals($contribution['values'][$contribution['id']]['contact_id'], $this->_individualId, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 120.00, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['financial_type_id'],$this->financialtypeID, 'In line ' . __LINE__ ); + $this->assertEquals($contribution['values'][$contribution['id']]['trxn_id'], 12345, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['invoice_id'], 67890, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['source'], 'SSF', 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['tax_amount'], 20, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status_id'], 2, 'In line ' . __LINE__); + $this->_checkFinancialRecords($contribution, 'payLater'); + } + function testCreateContributionPendingOnline() { + $this->setUpContributionPage(); + $params = array( + 'contact_id' => $this->_individualId, + 'receive_date' => '20120511', + 'total_amount' => 100.00, + 'financial_type_id' => $this->financialtypeID, + 'contribution_page_id' => $this->_ids['contribution_page'], + 'trxn_id' => 12345, + 'invoice_id' => 67890, + 'source' => 'SSF', + 'contribution_status_id' => 2, + ); + + $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__, __FILE__); + $this->assertEquals($contribution['values'][$contribution['id']]['contact_id'], $this->_individualId, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 120.00, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['financial_type_id'],$this->financialtypeID, 'In line ' . __LINE__ ); + $this->assertEquals($contribution['values'][$contribution['id']]['trxn_id'], 12345, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['invoice_id'], 67890, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['source'], 'SSF', 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['tax_amount'], 20, 'In line ' . __LINE__); + $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status_id'], 2, 'In line ' . __LINE__); + $this->_checkFinancialRecords($contribution, 'pending'); + } + + /* + * Updation of contrbution + * Function tests that line items, financial records are updated when contribution amount is changed + */ + function testCreateUpdateContributionChangeTotal() { + $this->setUpContributionPage(); + $this->contributionParams = array( + 'contact_id' => $this->_individualId, + 'receive_date' => '20120511', + 'total_amount' => 100.00, + 'financial_type_id' => $this->financialtypeID, + 'source' => 'SSF', + 'contribution_status_id' => 1, + ); + $contribution = $this->callAPISuccess('contribution', 'create', $this->contributionParams); + $lineItems = $this->callAPISuccess('line_item','getvalue', array( + 'entity_id' => $contribution['id'], + 'entity_table' => 'civicrm_contribution', + 'sequential' => 1, + 'return' => 'line_total', + )); + $this->assertEquals('100.00', $lineItems); + $trxnAmount = $this->_getFinancialTrxnAmount($contribution['id']); + $this->assertEquals('120.00', $trxnAmount); + $newParams = array( + 'id' => $contribution['id'], + 'financial_type_id' => 1, // without tax rate i.e Donation + 'total_amount' => '300' + ); + $contribution = $this->callAPISuccess('contribution', 'update', $newParams); + + $lineItems = $this->callAPISuccess('line_item','getvalue',array( + 'entity_id' => $contribution['id'], + 'entity_table' => 'civicrm_contribution', + 'sequential' => 1, + 'return' => 'line_total', + )); + + $this->assertEquals('300.00', $lineItems); + $trxnAmount = $this->_getFinancialTrxnAmount($contribution['id']); + $fitemAmount = $this->_getFinancialItemAmount($contribution['id']); + $this->assertEquals('300.00', $trxnAmount); + $this->assertEquals('300.00', $fitemAmount); + } + + /** + * @param $contId + * + * @return null|string + */ + function _getFinancialTrxnAmount($contId) { + $query = "SELECT + SUM( ft.total_amount ) AS total + FROM civicrm_financial_trxn AS ft + LEFT JOIN civicrm_entity_financial_trxn AS ceft ON ft.id = ceft.financial_trxn_id + WHERE ceft.entity_table = 'civicrm_contribution' + AND ceft.entity_id = {$contId}"; + $result = CRM_Core_DAO::singleValueQuery($query); + return $result; + } + + /** + * @param $contId + * + * @return null|string + */ + function _getFinancialItemAmount($contId) { + $lineItem = key(CRM_Price_BAO_LineItem::getLineItems($contId, 'contribution')); + $query = "SELECT + SUM(amount) + FROM civicrm_financial_item + WHERE entity_table = 'civicrm_line_item' + AND entity_id = {$lineItem}"; + $result = CRM_Core_DAO::singleValueQuery($query); + return $result; + } + + /** + * @param $params + * @param $context + */ + function _checkFinancialRecords($params, $context) { + $entityParams = array( + 'entity_id' => $params['id'], + 'entity_table' => 'civicrm_contribution', + ); + if ($context == 'pending') { + $trxn = CRM_Financial_BAO_FinancialItem::retrieveEntityFinancialTrxn($entityParams); + $this->assertNull($trxn, 'No Trxn to be created until IPN callback'); + return; + } + $trxn = current(CRM_Financial_BAO_FinancialItem::retrieveEntityFinancialTrxn($entityParams)); + $trxnParams = array( + 'id' => $trxn['financial_trxn_id'], + ); + if ($context != 'online' && $context != 'payLater') { + $compareParams = array( + 'to_financial_account_id' => 6, + 'total_amount' => 120, + 'status_id' => 1, + ); + } + if ($context == 'online') { + $compareParams = array( + 'to_financial_account_id' => 12, + 'total_amount' => 120, + 'status_id' => 1, + ); + } + elseif ($context == 'payLater') { + $compareParams = array( + 'to_financial_account_id' => 7, + 'total_amount' => 120, + 'status_id' => 2, + ); + } + $this->assertDBCompareValues('CRM_Financial_DAO_FinancialTrxn', $trxnParams, $compareParams); + $entityParams = array( + 'financial_trxn_id' => $trxn['financial_trxn_id'], + 'entity_table' => 'civicrm_financial_item', + ); + $entityTrxn = current(CRM_Financial_BAO_FinancialItem::retrieveEntityFinancialTrxn($entityParams)); + $fitemParams = array( + 'id' => $entityTrxn['entity_id'], + ); + $compareParams = array( + 'amount' => 100, + 'status_id' => 1, + 'financial_account_id' => $this->_getFinancialAccountId($this->financialtypeID), + ); + if ($context == 'payLater') { + $compareParams = array( + 'amount' => 100, + 'status_id' => 3, + 'financial_account_id' => $this->_getFinancialAccountId($this->financialtypeID), + ); + } + $this->assertDBCompareValues('CRM_Financial_DAO_FinancialItem', $fitemParams, $compareParams); + } + + /** + * @param $params + * @param $financialTypeId + */ + function _getFinancialAccountId($financialTypeId) { + $accountRel = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Income Account is' ")); + + $searchParams = array( + 'entity_table' => 'civicrm_financial_type', + 'entity_id' => $financialTypeId, + 'account_relationship' => $accountRel, + ); + + $result = array(); + CRM_Financial_BAO_FinancialTypeAccount::retrieve( $searchParams, $result ); + return CRM_Utils_Array::value( 'financial_account_id', $result ); + } + + ///////////////// civicrm_contribution_delete methods + function testDeleteContribution() { + $contributionID = $this->contributionCreate($this->_individualId, $this->financialtypeID, 'dfsdf', 12389); + $params = array( + 'id' => $contributionID, + ); + $this->callAPIAndDocument('contribution', 'delete', $params, __FUNCTION__, __FILE__); + } +} -- 2.25.1