Merge pull request #14249 from yashodha/959_dev
[civicrm-core.git] / tests / phpunit / CRM / Financial / BAO / FinancialAccountTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * Class CRM_Financial_BAO_FinancialAccountTest
30 * @group headless
31 */
32 class CRM_Financial_BAO_FinancialAccountTest extends CiviUnitTestCase {
33
34 public function setUp() {
35 $this->useTransaction(TRUE);
36 parent::setUp();
37 $this->organizationCreate();
38 }
39
40 /**
41 * Check method add()
42 */
43 public function testAdd() {
44 $params = array(
45 'name' => 'Donations',
46 'is_deductible' => 0,
47 'is_active' => 1,
48 );
49 $ids = array();
50 $financialAccount = CRM_Financial_BAO_FinancialAccount::add($params, $ids);
51
52 $result = $this->assertDBNotNull(
53 'CRM_Financial_BAO_FinancialAccount',
54 $financialAccount->id,
55 'name',
56 'id',
57 'Database check on updated financial type record.'
58 );
59
60 $this->assertEquals($result, 'Donations', 'Verify financial type name.');
61 }
62
63 /**
64 * Check method retrive()
65 */
66 public function testRetrieve() {
67 $params = array(
68 'name' => 'Donations',
69 'is_deductible' => 0,
70 'is_active' => 1,
71 );
72 $ids = $defaults = array();
73 CRM_Financial_BAO_FinancialAccount::add($params);
74
75 $result = CRM_Financial_BAO_FinancialAccount::retrieve($params, $defaults);
76
77 $this->assertEquals($result->name, 'Donations', 'Verify financial account name.');
78 }
79
80 /**
81 * Check method setIsActive()
82 */
83 public function testSetIsActive() {
84 $params = array(
85 'name' => 'Donations',
86 'is_deductible' => 0,
87 'is_active' => 1,
88 );
89 $ids = array();
90 $financialAccount = CRM_Financial_BAO_FinancialAccount::add($params, $ids);
91 $result = CRM_Financial_BAO_FinancialAccount::setIsActive($financialAccount->id, 0);
92 $this->assertEquals($result, TRUE, 'Verify financial account record updation for is_active.');
93
94 $isActive = $this->assertDBNotNull(
95 'CRM_Financial_BAO_FinancialAccount',
96 $financialAccount->id,
97 'is_active',
98 'id',
99 'Database check on updated for financial account is_active.'
100 );
101 $this->assertEquals($isActive, 0, 'Verify financial account is_active.');
102 }
103
104 /**
105 * Check method del()
106 */
107 public function testdel() {
108 $params = array(
109 'name' => 'Donations',
110 'is_deductible' => 0,
111 'is_active' => 1,
112 );
113 $ids = array();
114 $financialAccount = CRM_Financial_BAO_FinancialAccount::add($params, $ids);
115
116 CRM_Financial_BAO_FinancialAccount::del($financialAccount->id);
117 $params = array('id' => $financialAccount->id);
118 $result = CRM_Financial_BAO_FinancialAccount::retrieve($params, $defaults);
119 $this->assertEquals(empty($result), TRUE, 'Verify financial account record deletion.');
120 }
121
122 /**
123 * Check method del()
124 */
125 public function testdelIfHasContribution() {
126 $params = array(
127 'name' => 'Donation Test',
128 'is_active' => 1,
129 'is_deductible' => 1,
130 'is_reserved' => 1,
131 );
132 $financialType = CRM_Financial_BAO_FinancialType::add($params);
133 $defaults = array();
134 $params = array(
135 'name' => 'Donation Test',
136 'is_active' => 1,
137 );
138 $result = CRM_Financial_BAO_FinancialAccount::retrieve($params, $defaults);
139
140 $contactId = $this->individualCreate();
141 $contributionParams = array(
142 'total_amount' => 300,
143 'currency' => 'USD',
144 'contact_id' => $contactId,
145 'financial_type_id' => $financialType->id,
146 'contribution_status_id' => 1,
147 );
148 $this->callAPISuccess('Contribution', 'create', $contributionParams);
149 CRM_Financial_BAO_FinancialAccount::del($result->id);
150 $params = array('id' => $result->id);
151 $result = CRM_Financial_BAO_FinancialAccount::retrieve($params, $defaults);
152 $this->assertEquals(empty($result), FALSE, 'Verify financial account record deletion.');
153 }
154
155 /**
156 * Check method getAccountingCode()
157 */
158 public function testGetAccountingCode() {
159 $params = array(
160 'name' => 'Donations',
161 'is_active' => 1,
162 'is_reserved' => 0,
163 );
164
165 $ids = array();
166 $financialType = CRM_Financial_BAO_FinancialType::add($params, $ids);
167 $financialAccountid = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialAccount', 'Donations', 'id', 'name');
168 CRM_Core_DAO::setFieldValue('CRM_Financial_DAO_FinancialAccount', $financialAccountid, 'accounting_code', '4800');
169 $accountingCode = CRM_Financial_BAO_FinancialAccount::getAccountingCode($financialType->id);
170 $this->assertEquals($accountingCode, 4800, 'Verify accounting code.');
171 }
172
173 /**
174 * Test getting financial account for a given financial Type with a particular relationship.
175 */
176 public function testGetFinancialAccountByFinancialTypeAndRelationshipBuiltIn() {
177 $this->assertEquals(2, CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship(2, 'Income Account Is'));
178 }
179
180 /**
181 * Test getting financial account for a given financial Type with a particular relationship.
182 */
183 public function testGetFinancialAccountByFinancialTypeAndRelationshipBuiltInRefunded() {
184 $this->assertEquals(2, CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship(2, 'Credit/Contra Revenue Account Is'));
185 }
186
187 /**
188 * Test getting financial account for a given financial Type with a particular relationship.
189 */
190 public function testGetFinancialAccountByFinancialTypeAndRelationshipBuiltInChargeBack() {
191 $this->assertEquals(2, CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship(2, 'Chargeback Account Is'));
192 }
193
194 /**
195 * Test getting financial account for a given financial Type with a particular relationship.
196 */
197 public function testGetFinancialAccountByFinancialTypeAndRelationshipCustomAddedRefunded() {
198 $financialAccount = $this->callAPISuccess('FinancialAccount', 'create', array(
199 'name' => 'Refund Account',
200 'is_active' => TRUE,
201 ));
202
203 $this->callAPISuccess('EntityFinancialAccount', 'create', array(
204 'entity_id' => 2,
205 'entity_table' => 'civicrm_financial_type',
206 'account_relationship' => 'Credit/Contra Revenue Account is',
207 'financial_account_id' => 'Refund Account',
208 ));
209 $this->assertEquals($financialAccount['id'],
210 CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship(2, 'Credit/Contra Revenue Account is'));
211 }
212
213 /**
214 * Test getting financial account relations for a given financial type.
215 */
216 public function testGetFinancialAccountRelations() {
217 $fAccounts = $rAccounts = array();
218 $relations = CRM_Financial_BAO_FinancialAccount::getfinancialAccountRelations();
219 $links = array(
220 'Expense Account is' => 'Expenses',
221 'Accounts Receivable Account is' => 'Asset',
222 'Income Account is' => 'Revenue',
223 'Asset Account is' => 'Asset',
224 'Cost of Sales Account is' => 'Cost of Sales',
225 'Premiums Inventory Account is' => 'Asset',
226 'Discounts Account is' => 'Revenue',
227 'Sales Tax Account is' => 'Liability',
228 'Deferred Revenue Account is' => 'Liability',
229 );
230 $dao = CRM_Core_DAO::executeQuery("SELECT ov.value, ov.name
231 FROM civicrm_option_value ov
232 INNER JOIN civicrm_option_group og ON og.id = ov.option_group_id
233 AND og.name = 'financial_account_type'");
234 while ($dao->fetch()) {
235 $fAccounts[$dao->value] = $dao->name;
236 }
237 $dao = CRM_Core_DAO::executeQuery("SELECT ov.value, ov.name
238 FROM civicrm_option_value ov
239 INNER JOIN civicrm_option_group og ON og.id = ov.option_group_id
240 AND og.name = 'account_relationship'");
241 while ($dao->fetch()) {
242 $rAccounts[$dao->value] = $dao->name;
243 }
244 foreach ($links as $accountRelation => $accountType) {
245 $financialAccountLinks[array_search($accountRelation, $rAccounts)] = array_search($accountType, $fAccounts);
246 }
247 $this->assertTrue(($relations == $financialAccountLinks), "The two arrays are not the same");
248 }
249
250 /**
251 * Test getting deferred financial type.
252 */
253 public function testGetDeferredFinancialType() {
254 $result = $this->_createDeferredFinancialAccount();
255 $financialTypes = CRM_Financial_BAO_FinancialAccount::getDeferredFinancialType();
256 $this->assertTrue(array_key_exists($result, $financialTypes), "The financial type created does not have a deferred account relationship");
257 }
258
259 /**
260 * Test getting financial account for a given financial Type with a particular relationship.
261 */
262 public function testValidateFinancialAccount() {
263 // Create a record with financial item having financial account as Event Fee.
264 $this->createParticipantWithContribution();
265 $financialAccounts = CRM_Contribute_PseudoConstant::financialAccount();
266 $financialAccountId = array_search('Event Fee', $financialAccounts);
267 $message = CRM_Financial_BAO_FinancialAccount::validateFinancialAccount($financialAccountId);
268 $this->assertTrue($message, "The financial account cannot be deleted. Failed asserting this was true.");
269 $financialAccountId = array_search('Member Dues', $financialAccounts);
270 $message = CRM_Financial_BAO_FinancialAccount::validateFinancialAccount($financialAccountId);
271 $this->assertFalse($message, "The financial account can be deleted. Failed asserting this was true.");
272 }
273
274 /**
275 * Test for validating financial type has deferred revenue account relationship.
276 */
277 public function testcheckFinancialTypeHasDeferred() {
278 Civi::settings()->set('deferred_revenue_enabled', 1);
279 $params = [];
280 $valid = CRM_Financial_BAO_FinancialAccount::checkFinancialTypeHasDeferred($params);
281 $this->assertFalse($valid, "This should have been false");
282 $cid = $this->individualCreate();
283 $params = array(
284 'contact_id' => $cid,
285 'receive_date' => '2016-01-20',
286 'total_amount' => 100,
287 'financial_type_id' => 4,
288 'revenue_recognition_date' => date('Ymd', strtotime("+1 month")),
289 'line_items' => array(
290 array(
291 'line_item' => array(
292 array(
293 'entity_table' => 'civicrm_contribution',
294 'price_field_id' => 8,
295 'price_field_value_id' => 16,
296 'label' => 'test 1',
297 'qty' => 1,
298 'unit_price' => 100,
299 'line_total' => 100,
300 'financial_type_id' => 4,
301 ),
302 array(
303 'entity_table' => 'civicrm_contribution',
304 'price_field_id' => 8,
305 'price_field_value_id' => 17,
306 'label' => 'Test 2',
307 'qty' => 1,
308 'unit_price' => 200,
309 'line_total' => 200,
310 'financial_type_id' => 4,
311 ),
312 ),
313 ),
314 ),
315 );
316 try {
317 CRM_Financial_BAO_FinancialAccount::checkFinancialTypeHasDeferred($params);
318 }
319 catch (CRM_Core_Exception $e) {
320 $this->fail("Missed expected exception");
321 }
322 $params = array(
323 'contact_id' => $cid,
324 'receive_date' => '2016-01-20',
325 'total_amount' => 100,
326 'financial_type_id' => 1,
327 'revenue_recognition_date' => date('Ymd', strtotime("+1 month")),
328 );
329 try {
330 CRM_Financial_BAO_FinancialAccount::checkFinancialTypeHasDeferred($params);
331 $this->fail("Missed expected exception");
332 }
333 catch (CRM_Core_Exception $e) {
334 $this->assertEquals('Revenue Recognition Date cannot be processed unless there is a Deferred Revenue account setup for the Financial Type. Please remove Revenue Recognition Date, select a different Financial Type with a Deferred Revenue account setup for it, or setup a Deferred Revenue account for this Financial Type.', $e->getMessage());
335 }
336 }
337
338 /**
339 * Test testGetAllDeferredFinancialAccount.
340 */
341 public function testGetAllDeferredFinancialAccount() {
342 $financialAccount = CRM_Financial_BAO_FinancialAccount::getAllDeferredFinancialAccount();
343 // The two deferred financial accounts which are created by default.
344 $expected = array(
345 "Deferred Revenue - Member Dues (2740)",
346 "Deferred Revenue - Event Fee (2730)",
347 );
348 $this->assertEquals(array_count_values($expected), array_count_values($financialAccount), "The two arrays are not the same");
349 $this->_createDeferredFinancialAccount();
350 $financialAccount = CRM_Financial_BAO_FinancialAccount::getAllDeferredFinancialAccount();
351 $expected[] = "TestFinancialAccount_1 (4800)";
352 $this->assertEquals(array_count_values($expected), array_count_values($financialAccount), "The two arrays are not the same");
353 }
354
355 /**
356 * CRM-20037: Test balance due amount, if contribution is done using deferred Financial Type
357 */
358 public function testBalanceDueIfDeferredRevenueEnabled() {
359 Civi::settings()->set('contribution_invoice_settings', array('deferred_revenue_enabled' => '1'));
360 $deferredFinancialTypeID = $this->_createDeferredFinancialAccount();
361
362 $totalAmount = 100.00;
363 $contribution = $this->callAPISuccess('Contribution', 'create', array(
364 'contact_id' => $this->individualCreate(),
365 'receive_date' => '20120511',
366 'total_amount' => $totalAmount,
367 'financial_type_id' => $deferredFinancialTypeID,
368 'non_deductible_amount' => 10.00,
369 'fee_amount' => 5.00,
370 'net_amount' => 95.00,
371 'source' => 'SSF',
372 'contribution_status_id' => 1,
373 ));
374 $balance = CRM_Contribute_BAO_Contribution::getContributionBalance($contribution['id'], $totalAmount);
375 $this->assertEquals(0.0, $balance);
376 Civi::settings()->revert('contribution_invoice_settings');
377 }
378
379 /**
380 * Helper function to create deferred financial account.
381 */
382 public function _createDeferredFinancialAccount() {
383 $params = array(
384 'name' => 'TestFinancialAccount_1',
385 'accounting_code' => 4800,
386 'contact_id' => 1,
387 'is_deductible' => 0,
388 'is_active' => 1,
389 'is_reserved' => 0,
390 );
391
392 $financialAccount = $this->callAPISuccess('FinancialAccount', 'create', $params);
393 $params['name'] = 'test_financialType1';
394 $financialType = $this->callAPISuccess('FinancialType', 'create', $params);
395 $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Deferred Revenue Account is' "));
396 $financialParams = array(
397 'entity_table' => 'civicrm_financial_type',
398 'entity_id' => $financialType['id'],
399 'account_relationship' => $relationTypeId,
400 'financial_account_id' => $financialAccount['id'],
401 );
402
403 $this->callAPISuccess('EntityFinancialAccount', 'create', $financialParams);
404 $result = $this->assertDBNotNull(
405 'CRM_Financial_DAO_EntityFinancialAccount',
406 $financialAccount['id'],
407 'entity_id',
408 'financial_account_id',
409 'Database check on added financial type record.'
410 );
411 $this->assertEquals($result, $financialType['id'], 'Verify Account Type');
412 return $result;
413 }
414
415 }