4 +--------------------------------------------------------------------+
5 | CiviCRM version 4.6 |
6 +--------------------------------------------------------------------+
7 | Copyright CiviCRM LLC (c) 2004-2014 |
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
20 | You should have received a copy of the GNU Affero General Public |
21 | License and the CiviCRM Licensing Exception along |
22 | with this program; if not, contact CiviCRM LLC |
23 | at info[AT]civicrm[DOT]org. If you have questions about the |
24 | GNU Affero General Public License or the licensing of CiviCRM, |
25 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
26 +--------------------------------------------------------------------+
29 require_once 'CiviTest/CiviUnitTestCase.php';
32 * Class api_v3_TaxContributionPageTest
34 class api_v3_TaxContributionPageTest
extends CiviUnitTestCase
{
35 protected $_apiversion = 3;
37 protected $financialtypeID;
38 protected $financialAccountId;
39 protected $_entity = 'contribution_page';
40 protected $_priceSetParams = array();
41 protected $_paymentProcessorType;
42 protected $payParams = array();
43 protected $paymentProceParams = array();
44 protected $settingValue = array();
45 protected $setInvoiceSettings;
46 protected $_ids = array();
47 protected $_individualId;
48 protected $financialAccHalftax;
49 protected $financialtypeHalftax;
50 protected $financialRelationHalftax;
51 protected $halfFinancialAccId;
52 protected $halfFinancialTypeId;
53 public $DBResetRequired = TRUE;
55 public function setUp() {
57 $this->_individualId
= $this->individualCreate();
58 $this->_orgId
= $this->organizationCreate(NULL);
60 $this->params
= array(
61 'title' => "Test Contribution Page".substr(sha1(rand()), 0, 7),
62 'financial_type_id' => 1,
63 'payment_processor' => 1,
67 'pay_later_text' => 'I will pay later',
68 'pay_later_receipt' => "I will pay later",
69 'is_monetary' => TRUE,
70 'is_billing_required' => True
73 $this->_priceSetParams
= array(
74 'name' => 'tax_contribution'.substr(sha1(rand()), 0, 7),
75 'title' => 'contributiontax'.substr(sha1(rand()), 0, 7),
77 'help_pre' => "Where does your goat sleep",
78 'help_post' => "thank you for your time",
80 'financial_type_id' => 3,
81 'is_quick_config' => 0,
84 // Financial Account with 20% tax rate
85 $financialAccountSetparams = array(
87 'name' => 'vat full taxrate account'.substr(sha1(rand()), 0, 7),
88 'contact_id' => $this->_orgId
,
89 'financial_account_type_id' => 2,
97 $financialAccount = $this->callAPISuccess('financial_account', 'create', $financialAccountSetparams);
98 $this->financialAccountId
= $financialAccount['id'];
100 // Financial type having 'Sales Tax Account is' with liability financail account
101 $financialType = array(
102 'name' => 'grassvariety1'.substr(sha1(rand()), 0, 7),
106 $priceField = $this->callAPISuccess('financial_type','create', $financialType);
107 $this->financialtypeID
= $priceField['id'];
108 $financialRelationParams = array(
109 'entity_table' => 'civicrm_financial_type',
110 'entity_id' => $this->financialtypeID
,
111 'account_relationship' => 10,
112 'financial_account_id' => $this->financialAccountId
114 $financialRelation = CRM_Financial_BAO_FinancialTypeAccount
::add($financialRelationParams);
116 // Financial type with 5% tax rate
117 $financialAccHalftax = array(
118 'name' => 'vat half taxrate account'.substr(sha1(rand()), 0, 7),
119 'contact_id' => $this->_orgId
,
120 'financial_account_type_id' => 2,
127 $halfFinancialAccount = CRM_Financial_BAO_FinancialAccount
::add($financialAccHalftax);
128 $this->halfFinancialAccId
= $halfFinancialAccount->id
;
129 $halfFinancialtypeHalftax = array(
130 'name' => 'grassvariety2'.substr(sha1(rand()), 0, 7),
135 $halfFinancialType = CRM_Financial_BAO_FinancialType
::add($halfFinancialtypeHalftax);
136 $this->halfFinancialTypeId
= $halfFinancialType->id
;
137 $financialRelationHalftax = array(
138 'entity_table' => 'civicrm_financial_type',
139 'entity_id' => $this->halfFinancialTypeId
,
140 'account_relationship' => 10,
141 'financial_account_id' => $this->halfFinancialAccId
144 $halfFinancialRelation = CRM_Financial_BAO_FinancialTypeAccount
::add($financialRelationHalftax);
146 // Enable component contribute setting
147 $contributeSetting = array (
149 'invoice_prefix' => 'INV_',
150 'credit_notes_prefix' => 'CN_',
152 'due_date_period' => 'days',
155 'tax_term' => 'Sales Tax',
156 'tax_display_settings' => 'Inclusive',
158 $setInvoiceSettings = CRM_Core_BAO_Setting
::setItem($contributeSetting, CRM_Core_BAO_Setting
::CONTRIBUTE_PREFERENCES_NAME
, 'contribution_invoice_settings');
161 $paymentProceParams = array(
163 'name' => 'dummy'.substr(sha1(rand()), 0, 7),
164 'payment_processor_type_id' => 10,
165 'financial_account_id' => 12,
169 'user_name' => 'dummy',
170 'url_site' => 'http://dummy.com',
171 'url_recur' => 'http://dummyrecur.com',
172 'class_name' => 'Payment_Dummy',
177 $result = $this->callAPISuccess('payment_processor', 'create', $paymentProceParams);
178 $this->_ids
['paymentProcessID'] = $result['id'];
179 require_once 'api/v3/examples/PaymentProcessor/Create.php';
180 $this->assertAPISuccess($result);
183 public function tearDown() {
184 $this->quickCleanup(array(
185 'civicrm_contribution',
186 'civicrm_contribution_soft',
188 'civicrm_contribution_page',
189 'civicrm_participant',
190 'civicrm_participant_payment',
192 'civicrm_financial_trxn',
193 'civicrm_financial_item',
194 'civicrm_entity_financial_trxn',
196 'civicrm_membership',
197 'civicrm_membership_payment',
198 'civicrm_payment_processor'
200 CRM_Core_PseudoConstant
::flush('taxRates');
203 public function setUpContributionPage() {
204 $contributionPageResult = $this->callAPISuccess($this->_entity
, 'create', $this->params
);
205 if (empty($this->_ids
['price_set'])) {
206 $priceSet = $this->callAPISuccess('price_set', 'create', $this->_priceSetParams
);
207 $this->_ids
['price_set'][] = $priceSet['id'];
209 $priceSetID = $this->_price
= reset($this->_ids
['price_set']);
210 CRM_Price_BAO_PriceSet
::addTo('civicrm_contribution_page', $contributionPageResult['id'], $priceSetID );
212 if (empty($this->_ids
['price_field'])) {
213 $priceField = $this->callAPISuccess('price_field', 'create', array(
214 'price_set_id' => $priceSetID,
215 'label' => 'Goat Breed',
216 'html_type' => 'Radio',
218 $this->_ids
['price_field'] = array($priceField['id']);
220 if (empty($this->_ids
['price_field_value'])) {
221 $this->callAPISuccess('price_field_value', 'create', array(
222 'price_set_id' => $priceSetID,
223 'price_field_id' => $priceField['id'],
224 'label' => 'Long Haired Goat',
226 'financial_type_id' => $this->financialtypeID
228 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
229 'price_set_id' => $priceSetID,
230 'price_field_id' => $priceField['id'],
231 'label' => 'Shoe-eating Goat',
233 'financial_type_id' => $this->halfFinancialTypeId
235 $this->_ids
['price_field_value'] = array($priceFieldValue['id']);
237 $this->_ids
['contribution_page'] = $contributionPageResult['id'];
241 * Online and offline contrbution from above created contrbution page
243 public function testCreateContributionOnline() {
244 $this->setUpContributionPage();
246 'contact_id' => $this->_individualId
,
247 'receive_date' => '20120511',
248 'total_amount' => 100.00,
249 'financial_type_id' => $this->financialtypeID
,
250 'contribution_page_id' => $this->_ids
['contribution_page'],
251 'payment_processor' => $this->_ids
['paymentProcessID'],
253 'invoice_id' => 67890,
255 'contribution_status_id' => 1
258 $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__
, __FILE__
);
259 $this->_ids
['contributionId'] = $contribution['id'];
260 $this->assertEquals($contribution['values'][$contribution['id']]['contact_id'], $this->_individualId
, 'In line ' . __LINE__
);
261 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 120.00, 'In line ' . __LINE__
);
262 $this->assertEquals($contribution['values'][$contribution['id']]['financial_type_id'],$this->financialtypeID
, 'In line ' . __LINE__
);
263 $this->assertEquals($contribution['values'][$contribution['id']]['trxn_id'], 12345, 'In line ' . __LINE__
);
264 $this->assertEquals($contribution['values'][$contribution['id']]['invoice_id'], 67890, 'In line ' . __LINE__
);
265 $this->assertEquals($contribution['values'][$contribution['id']]['source'], 'SSF', 'In line ' . __LINE__
);
266 $this->assertEquals($contribution['values'][$contribution['id']]['tax_amount'], 20, 'In line ' . __LINE__
);
267 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status_id'], 1, 'In line ' . __LINE__
);
268 $this->_checkFinancialRecords($contribution, 'online');
271 public function testCreateContributionChainedLineItems() {
272 $this->setUpContributionPage();
274 'contact_id' => $this->_individualId
,
275 'receive_date' => '20120511',
276 'total_amount' => 400.00,
277 'financial_type_id' => $this->financialtypeID
,
279 'invoice_id' => 67890,
281 'contribution_status_id' => 1,
283 'api.line_item.create' => array(
285 'price_field_id' => $this->_ids
['price_field'],
287 'line_total' => '100',
288 'unit_price' => '100',
289 'financial_type_id' => $this->financialtypeID
,
292 'price_field_id' => $this->_ids
['price_field'],
294 'line_total' => '300',
295 'unit_price' => '300',
296 'financial_type_id' => $this->halfFinancialTypeId
,
301 $description = "Create Contribution with Nested Line Items";
302 $subfile = "CreateWithNestedLineItems";
303 $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__
,__FILE__
, $description, $subfile);
305 $lineItems = $this->callAPISuccess('line_item','get',array(
306 'entity_id' => $contribution['id'],
307 'contribution_id' => $contribution['id'],
308 'entity_table' => 'civicrm_contribution',
311 $this->assertEquals(2, $lineItems['count']);
314 public function testCreateContributionPayLaterOnline() {
315 $this->setUpContributionPage();
317 'contact_id' => $this->_individualId
,
318 'receive_date' => '20120511',
319 'total_amount' => 100.00,
320 'financial_type_id' => $this->financialtypeID
,
321 'contribution_page_id' => $this->_ids
['contribution_page'],
324 'invoice_id' => 67890,
326 'contribution_status_id' => 2,
328 $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__
, __FILE__
);
329 $this->assertEquals($contribution['values'][$contribution['id']]['contact_id'], $this->_individualId
, 'In line ' . __LINE__
);
330 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 120.00, 'In line ' . __LINE__
);
331 $this->assertEquals($contribution['values'][$contribution['id']]['financial_type_id'],$this->financialtypeID
, 'In line ' . __LINE__
);
332 $this->assertEquals($contribution['values'][$contribution['id']]['trxn_id'], 12345, 'In line ' . __LINE__
);
333 $this->assertEquals($contribution['values'][$contribution['id']]['invoice_id'], 67890, 'In line ' . __LINE__
);
334 $this->assertEquals($contribution['values'][$contribution['id']]['source'], 'SSF', 'In line ' . __LINE__
);
335 $this->assertEquals($contribution['values'][$contribution['id']]['tax_amount'], 20, 'In line ' . __LINE__
);
336 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status_id'], 2, 'In line ' . __LINE__
);
337 $this->_checkFinancialRecords($contribution, 'payLater');
339 public function testCreateContributionPendingOnline() {
340 $this->setUpContributionPage();
342 'contact_id' => $this->_individualId
,
343 'receive_date' => '20120511',
344 'total_amount' => 100.00,
345 'financial_type_id' => $this->financialtypeID
,
346 'contribution_page_id' => $this->_ids
['contribution_page'],
348 'invoice_id' => 67890,
350 'contribution_status_id' => 2,
353 $contribution = $this->callAPIAndDocument('contribution', 'create', $params, __FUNCTION__
, __FILE__
);
354 $this->assertEquals($contribution['values'][$contribution['id']]['contact_id'], $this->_individualId
, 'In line ' . __LINE__
);
355 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 120.00, 'In line ' . __LINE__
);
356 $this->assertEquals($contribution['values'][$contribution['id']]['financial_type_id'],$this->financialtypeID
, 'In line ' . __LINE__
);
357 $this->assertEquals($contribution['values'][$contribution['id']]['trxn_id'], 12345, 'In line ' . __LINE__
);
358 $this->assertEquals($contribution['values'][$contribution['id']]['invoice_id'], 67890, 'In line ' . __LINE__
);
359 $this->assertEquals($contribution['values'][$contribution['id']]['source'], 'SSF', 'In line ' . __LINE__
);
360 $this->assertEquals($contribution['values'][$contribution['id']]['tax_amount'], 20, 'In line ' . __LINE__
);
361 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status_id'], 2, 'In line ' . __LINE__
);
362 $this->_checkFinancialRecords($contribution, 'pending');
366 * Updation of contrbution
367 * Function tests that line items, financial records are updated when contribution amount is changed
369 public function testCreateUpdateContributionChangeTotal() {
370 $this->setUpContributionPage();
371 $this->contributionParams
= array(
372 'contact_id' => $this->_individualId
,
373 'receive_date' => '20120511',
374 'total_amount' => 100.00,
375 'financial_type_id' => $this->financialtypeID
,
377 'contribution_status_id' => 1,
379 $contribution = $this->callAPISuccess('contribution', 'create', $this->contributionParams
);
380 $lineItems = $this->callAPISuccess('line_item','getvalue', array(
381 'entity_id' => $contribution['id'],
382 'entity_table' => 'civicrm_contribution',
384 'return' => 'line_total',
386 $this->assertEquals('100.00', $lineItems);
387 $trxnAmount = $this->_getFinancialTrxnAmount($contribution['id']);
388 $this->assertEquals('120.00', $trxnAmount);
390 'id' => $contribution['id'],
391 'financial_type_id' => 1, // without tax rate i.e Donation
392 'total_amount' => '300'
394 $contribution = $this->callAPISuccess('contribution', 'update', $newParams);
396 $lineItems = $this->callAPISuccess('line_item','getvalue',array(
397 'entity_id' => $contribution['id'],
398 'entity_table' => 'civicrm_contribution',
400 'return' => 'line_total',
403 $this->assertEquals('300.00', $lineItems);
404 $trxnAmount = $this->_getFinancialTrxnAmount($contribution['id']);
405 $fitemAmount = $this->_getFinancialItemAmount($contribution['id']);
406 $this->assertEquals('300.00', $trxnAmount);
407 $this->assertEquals('300.00', $fitemAmount);
413 * @return null|string
415 public function _getFinancialTrxnAmount($contId) {
417 SUM( ft.total_amount ) AS total
418 FROM civicrm_financial_trxn AS ft
419 LEFT JOIN civicrm_entity_financial_trxn AS ceft ON ft.id = ceft.financial_trxn_id
420 WHERE ceft.entity_table = 'civicrm_contribution'
421 AND ceft.entity_id = {$contId}";
422 $result = CRM_Core_DAO
::singleValueQuery($query);
429 * @return null|string
431 public function _getFinancialItemAmount($contId) {
432 $lineItem = key(CRM_Price_BAO_LineItem
::getLineItems($contId, 'contribution'));
435 FROM civicrm_financial_item
436 WHERE entity_table = 'civicrm_line_item'
437 AND entity_id = {$lineItem}";
438 $result = CRM_Core_DAO
::singleValueQuery($query);
443 * @param array $params
446 public function _checkFinancialRecords($params, $context) {
447 $entityParams = array(
448 'entity_id' => $params['id'],
449 'entity_table' => 'civicrm_contribution',
451 if ($context == 'pending') {
452 $trxn = CRM_Financial_BAO_FinancialItem
::retrieveEntityFinancialTrxn($entityParams);
453 $this->assertNull($trxn, 'No Trxn to be created until IPN callback');
456 $trxn = current(CRM_Financial_BAO_FinancialItem
::retrieveEntityFinancialTrxn($entityParams));
458 'id' => $trxn['financial_trxn_id'],
460 if ($context != 'online' && $context != 'payLater') {
461 $compareParams = array(
462 'to_financial_account_id' => 6,
463 'total_amount' => 120,
467 if ($context == 'online') {
468 $compareParams = array(
469 'to_financial_account_id' => 12,
470 'total_amount' => 120,
474 elseif ($context == 'payLater') {
475 $compareParams = array(
476 'to_financial_account_id' => 7,
477 'total_amount' => 120,
481 $this->assertDBCompareValues('CRM_Financial_DAO_FinancialTrxn', $trxnParams, $compareParams);
482 $entityParams = array(
483 'financial_trxn_id' => $trxn['financial_trxn_id'],
484 'entity_table' => 'civicrm_financial_item',
486 $entityTrxn = current(CRM_Financial_BAO_FinancialItem
::retrieveEntityFinancialTrxn($entityParams));
487 $fitemParams = array(
488 'id' => $entityTrxn['entity_id'],
490 $compareParams = array(
493 'financial_account_id' => $this->_getFinancialAccountId($this->financialtypeID
),
495 if ($context == 'payLater') {
496 $compareParams = array(
499 'financial_account_id' => $this->_getFinancialAccountId($this->financialtypeID
),
502 $this->assertDBCompareValues('CRM_Financial_DAO_FinancialItem', $fitemParams, $compareParams);
506 * @param array $params
507 * @param int $financialTypeId
509 public function _getFinancialAccountId($financialTypeId) {
510 $accountRel = key(CRM_Core_PseudoConstant
::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Income Account is' "));
512 $searchParams = array(
513 'entity_table' => 'civicrm_financial_type',
514 'entity_id' => $financialTypeId,
515 'account_relationship' => $accountRel,
519 CRM_Financial_BAO_FinancialTypeAccount
::retrieve( $searchParams, $result );
520 return CRM_Utils_Array
::value( 'financial_account_id', $result );
523 ///////////////// civicrm_contribution_delete methods
524 public function testDeleteContribution() {
525 $contributionID = $this->contributionCreate($this->_individualId
, $this->financialtypeID
, 'dfsdf', 12389);
527 'id' => $contributionID,
529 $this->callAPIAndDocument('contribution', 'delete', $params, __FUNCTION__
, __FILE__
);