PageRenderTime 42ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/phpunit/CRM/sepa/BatchingTest.php

https://github.com/systopia/sepa_dd
PHP | 681 lines | 446 code | 71 blank | 164 comment | 0 complexity | 7e686afc790bd4896e7975cef73501b0 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /*-------------------------------------------------------+
  3. | Project 60 - SEPA direct debit |
  4. | Copyright (C) 2013-2014 SYSTOPIA |
  5. | Author: N. Bochan (bochan -at- systopia.de) |
  6. | http://www.systopia.de/ |
  7. +--------------------------------------------------------+
  8. | This program is released as free software under the |
  9. | Affero GPL license. You can redistribute it and/or |
  10. | modify it under the terms of this license which you |
  11. | can read by viewing the included agpl.txt or online |
  12. | at www.gnu.org/licenses/agpl.html. Removal of this |
  13. | copyright header is strictly prohibited without |
  14. | written permission from the original author(s). |
  15. +--------------------------------------------------------*/
  16. require_once 'BaseTestCase.php';
  17. /**
  18. * SEPA Unit Tests
  19. *
  20. * Batching Algorithm
  21. *
  22. */
  23. class CRM_sepa_BatchingTest extends CRM_sepa_BaseTestCase {
  24. private $tablesToTruncate = array("civicrm_sdd_creditor",
  25. //"civicrm_contact",
  26. "civicrm_contribution",
  27. "civicrm_contribution_recur",
  28. "civicrm_sdd_mandate",
  29. "civicrm_sdd_contribution_txgroup",
  30. "civicrm_sdd_txgroup",
  31. "civicrm_sdd_file",
  32. "civicrm_line_item",
  33. "civicrm_financial_item",
  34. "civicrm_financial_trxn"
  35. );
  36. private $creditorId = NULL;
  37. function setUp() {
  38. parent::setUp();
  39. // FIXME: there seems to be a bug in civix, call this explicitely until fixed:
  40. sepa_civicrm_install();
  41. $this->quickCleanup($this->tablesToTruncate);
  42. // create a contact
  43. $this->creditorId = $this->individualCreate();
  44. // create a creditor
  45. $this->assertDBQuery(NULL, "INSERT INTO `civicrm_tests_dev`.`civicrm_sdd_creditor` (`id`, `creditor_id`, `identifier`, `name`, `address`, `country_id`, `iban`, `bic`, `mandate_prefix`, `payment_processor_id`, `category`, `tag`, `mandate_active`, `sepa_file_format_id`) VALUES ('3', '%1', 'TESTCREDITORID', 'TESTCREDITOR', '104 Wayne Street', '1082', '0000000000000000000000', 'COLSDE22XXX', 'TEST', '0', 'MAIN', NULL, '1', '1');", array(1 => array($this->creditorId, "Int")));
  46. }
  47. function tearDown() {
  48. error_reporting(E_ALL & ~E_NOTICE);
  49. $this->quickCleanup($this->tablesToTruncate);
  50. $this->cleanTempDirs();
  51. $this->unsetExtensionSystem();
  52. }
  53. /**
  54. * Test update of one-off (single payment) contributions
  55. *
  56. * @author niko bochan
  57. */
  58. public function testBatchingUpdateOOFF() {
  59. // create a contact
  60. $contactId = $this->individualCreate();
  61. // create a contribution
  62. $txmd5 = md5(date("YmdHis"));
  63. $txref = "SDD-TEST-OOFF-" . $txmd5;
  64. $cparams = array(
  65. "contact_id" => $contactId,
  66. "receive_date" => date("YmdHis"),
  67. "total_amount" => 333.94,
  68. "currency" => "EUR",
  69. "financial_type_id" => 1,
  70. "trxn_id" => $txref,
  71. "invoice_id" => $txref,
  72. "source" => "Test",
  73. "contribution_status_id" => 2,
  74. );
  75. $contrib = $this->callAPISuccess("contribution", "create", $cparams);
  76. $contrib = $contrib["values"][ $contrib["id"] ];
  77. // create a mandate
  78. $apiParams = array(
  79. "type" => "OOFF",
  80. "reference" => $txmd5,
  81. "status" => "OOFF",
  82. "source" => "TestSource",
  83. "date" => date("Y-m-d H:i:s"),
  84. "creditor_id" => "3",
  85. "contact_id" => $contactId,
  86. "iban" => "0000000000000000000000",
  87. "bic" => "COLSDE22XXX",
  88. "creation_date" => date("Y-m-d H:i:s"),
  89. "entity_table" => "civicrm_contribution",
  90. "entity_id" => $contrib["id"],
  91. );
  92. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  93. // create another contact
  94. $contactId = $this->individualCreate();
  95. // create another contribution
  96. $txmd5 = md5(date("YmdHis")."noduplicate");
  97. $txref = "SDD-TEST-OOFF-" . $txmd5;
  98. $cparams = array(
  99. "contact_id" => $contactId,
  100. "receive_date" => date("YmdHis"),
  101. "total_amount" => 123.45,
  102. "currency" => "EUR",
  103. "financial_type_id" => 1,
  104. "trxn_id" => $txref,
  105. "invoice_id" => $txref,
  106. "source" => "Test",
  107. "contribution_status_id" => 2,
  108. );
  109. $contrib = $this->callAPISuccess("contribution", "create", $cparams);
  110. $contrib = $contrib["values"][ $contrib["id"] ];
  111. // create another mandate
  112. $apiParams = array(
  113. "type" => "OOFF",
  114. "reference" => $txmd5,
  115. "status" => "OOFF",
  116. "source" => "TestSource",
  117. "date" => date("Y-m-d H:i:s"),
  118. "creditor_id" => "3",
  119. "contact_id" => $contactId,
  120. "iban" => "0000000000000000000010",
  121. "bic" => "COLSDE22XXX",
  122. "creation_date" => date("Y-m-d H:i:s"),
  123. "entity_table" => "civicrm_contribution",
  124. "entity_id" => $contrib["id"]
  125. );
  126. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  127. $result = $this->callAPISuccess("SepaAlternativeBatching", "update", array("type"=>"OOFF"));
  128. // test whether exactly one txgroup has been created
  129. $this->assertDBQuery(1, 'select count(*) from civicrm_sdd_txgroup;', array());
  130. // check txgroup attributes
  131. $collectionDate = date('Y-m-d', strtotime('+14 days')); // TODO: Use config file instead
  132. $searchParams = array(
  133. "id" => 1,
  134. //"reference" => sprintf("TXG-3-OOFF-%s", $collectionDate), TODO: bug
  135. "type" => "OOFF",
  136. //"collection_date" => sprintf("%s 00:00:00", $collectionDate), TODO: bug
  137. "latest_submission_date" => sprintf("%s 00:00:00", date('Y-m-d')),
  138. "created_date" => sprintf("%s 00:00:00", date('Y-m-d')),
  139. "status_id" => 1,
  140. "sdd_creditor_id" => 3
  141. );
  142. $this->assertDBCompareValues("CRM_Sepa_DAO_SEPATransactionGroup", array("id" => 1), $searchParams);
  143. }
  144. /**
  145. * Test update of recurring payments
  146. *
  147. * @author niko bochan
  148. */
  149. public function testBatchingUpdateRCUR() {
  150. $result = $this->createContactAndRecurContrib();
  151. // create a mandate
  152. $txmd5 = md5(date("YmdHis")."noduplicate1");
  153. $apiParams = array(
  154. "type" => "RCUR",
  155. "reference" => $txmd5,
  156. "status" => "FRST",
  157. "source" => "TestSource",
  158. "date" => date("Y-m-d H:i:s"),
  159. "creditor_id" => "3",
  160. "contact_id" => $result["contactId"],
  161. "iban" => "0000000000000000010001",
  162. "bic" => "COLSDE22XXX",
  163. "creation_date" => date("Y-m-d H:i:s"),
  164. "entity_table" => "civicrm_contribution_recur",
  165. "entity_id" => $result["contribution"]["id"],
  166. );
  167. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  168. // create another mandate
  169. $txmd5 = md5(date("YmdHis")."noduplicate2");
  170. $apiParams = array(
  171. "type" => "RCUR",
  172. "reference" => $txmd5,
  173. "status" => "FRST",
  174. "source" => "TestSource",
  175. "date" => date("Y-m-d H:i:s"),
  176. "creditor_id" => "3",
  177. "contact_id" => $result["contactId"],
  178. "iban" => "0000000000000000000110",
  179. "bic" => "COLSDE22XXX",
  180. "creation_date" => date("Y-m-d H:i:s"),
  181. "entity_table" => "civicrm_contribution_recur",
  182. "entity_id" => $result["contribution"]["id"],
  183. );
  184. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  185. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  186. // test whether exactly one txgroup has been created
  187. $this->assertDBQuery(1, 'select count(*) from civicrm_sdd_txgroup;', array());
  188. // check txgroup attributes
  189. $collectionDate = date('Y-m-d', strtotime('+14 days'));
  190. $searchParams = array(
  191. "id" => 1,
  192. "reference" => sprintf("TXG-3-FRST-%s", $collectionDate),
  193. "type" => "FRST",
  194. "collection_date" => sprintf("%s 00:00:00", $collectionDate),
  195. "created_date" => sprintf("%s 00:00:00", date('Y-m-d')),
  196. "status_id" => 1,
  197. "sdd_creditor_id" => 3
  198. );
  199. $this->assertDBCompareValues("CRM_Sepa_DAO_SEPATransactionGroup", array("id" => 1), $searchParams);
  200. }
  201. /**
  202. * Try to call update method with invalid batching mode
  203. *
  204. * @author niko bochan
  205. */
  206. public function testBatchingWithInvalidMode() {
  207. $this->callAPIFailure("SepaAlternativeBatching", "update", array("type" => "INVALIDBATCHINGMODE"));
  208. }
  209. /**
  210. * Try to call update method with invalid parameters
  211. *
  212. * @author niko bochan
  213. */
  214. public function testBatchingWithInvalidParameters() {
  215. $this->callAPIFailure("SepaAlternativeBatching", "update", 2142);
  216. }
  217. /**
  218. * Test group closing
  219. *
  220. * @author niko bochan
  221. */
  222. public function testCloseGroup() {
  223. // create a contact
  224. $contactId = $this->individualCreate();
  225. // create a contribution
  226. $txmd5 = md5(date("YmdHis"));
  227. $txref = "SDD-TEST-OOFF-" . $txmd5;
  228. $cparams = array(
  229. "contact_id" => $contactId,
  230. "receive_date" => date("YmdHis"),
  231. "total_amount" => 333.94,
  232. "currency" => "EUR",
  233. "financial_type_id" => 1,
  234. "trxn_id" => $txref,
  235. "invoice_id" => $txref,
  236. "source" => "Test",
  237. "contribution_status_id" => 2,
  238. );
  239. $contrib = $this->callAPISuccess("contribution", "create", $cparams);
  240. $contrib = $contrib["values"][ $contrib["id"] ];
  241. // create a mandate
  242. $apiParams = array(
  243. "type" => "OOFF",
  244. "reference" => $txmd5,
  245. "status" => "OOFF",
  246. "source" => "TestSource",
  247. "date" => date("Y-m-d H:i:s"),
  248. "creditor_id" => "3",
  249. "contact_id" => $contactId,
  250. "iban" => "0000000000000000000000",
  251. "bic" => "COLSDE22XXX",
  252. "creation_date" => date("Y-m-d H:i:s"),
  253. "entity_table" => "civicrm_contribution",
  254. "entity_id" => $contrib["id"],
  255. );
  256. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  257. // update txgroup
  258. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type"=>"OOFF"));
  259. // close the group
  260. $this->callAPISuccess("SepaAlternativeBatching", "close", array("txgroup_id"=>1));
  261. // check txgroup attributes
  262. $searchParams = array(
  263. "id" => 1,
  264. "status_id" => 2 // the group should be closed
  265. );
  266. $this->assertDBCompareValues("CRM_Sepa_DAO_SEPATransactionGroup", array("id" => 1), $searchParams);
  267. // check whether the contribution has been marked as "in progress"
  268. $searchParams = array(
  269. "id" => 1,
  270. "contribution_status_id" => (int) CRM_Core_OptionGroup::getValue('contribution_status', 'In Progress', 'name')
  271. );
  272. $this->assertDBCompareValues("CRM_Contribute_DAO_Contribution", array("id" => 1), $searchParams);
  273. }
  274. /**
  275. * Try to call close method with empty parameters
  276. *
  277. * @author niko bochan
  278. */
  279. public function testCloseWithEmptyParameters() {
  280. $this->callAPIFailure("SepaAlternativeBatching", "close", array());
  281. }
  282. /**
  283. * Try to close an invalid group
  284. *
  285. * @author niko bochan
  286. */
  287. public function testCloseWithInvalidParameters() {
  288. $this->callAPIFailure("SepaAlternativeBatching", "close", array("txgroup_id" => "INVALIDTXGID"));
  289. }
  290. /**
  291. * Test if groups are marked correctly as received
  292. *
  293. * @author niko bochan
  294. */
  295. public function testReceivedGroup() {
  296. $this->createMandate(array('type'=>'RCUR', 'status'=>'FRST'));
  297. $this->createMandate(array('type'=>'RCUR', 'status'=>'FRST'));
  298. // update txgroup
  299. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "RCUR"));
  300. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  301. // close the group
  302. $this->callAPISuccess("SepaAlternativeBatching", "close", array("txgroup_id"=>1));
  303. // mark the group as received
  304. $this->callAPISuccess("SepaAlternativeBatching", "received", array("txgroup_id"=>1));
  305. // check txgroup attributes
  306. $searchParams = array(
  307. "id" => 1,
  308. "status_id" => (int) CRM_Core_OptionGroup::getValue('batch_status', 'Received', 'name')
  309. );
  310. $this->assertDBCompareValues("CRM_Sepa_DAO_SEPATransactionGroup", array("id" => 1), $searchParams);
  311. }
  312. /**
  313. * Try to call API with empty parameters
  314. *
  315. * @author niko bochan
  316. */
  317. public function testReceivedWithEmptyParameters() {
  318. $this->callAPIFailure("SepaAlternativeBatching", "received", array());
  319. }
  320. /**
  321. * Try to set an invalid group to received
  322. *
  323. * @author niko bochan
  324. */
  325. public function testReceivedWithInvalidParameters() {
  326. $this->callAPIFailure("SepaAlternativeBatching", "received", array("txgroup_id" => "INVALIDTXGID"));
  327. }
  328. /**
  329. * Test if ended/old groups are closed
  330. *
  331. * @author niko bochan
  332. */
  333. public function testCloseEndedGroup() {
  334. // create a contact
  335. $contactId = $this->individualCreate();
  336. // create a recurring contribution
  337. $txmd5 = md5(date("YmdHis"));
  338. $cparams = array(
  339. 'contact_id' => $contactId,
  340. 'frequency_interval' => '1',
  341. 'frequency_unit' => 'month',
  342. 'amount' => 1337.42,
  343. 'contribution_status_id' => 1,
  344. 'start_date' => date("Ymd", strtotime("-100 days")),
  345. 'end_date' => date("Ymd", strtotime("-50 days")),
  346. 'currency' => "EUR",
  347. 'financial_type_id' => 1
  348. );
  349. $contrib = $this->callAPISuccess("contribution_recur", "create", $cparams);
  350. $contrib = $contrib["values"][ $contrib["id"] ];
  351. // create a mandate
  352. $apiParams = array(
  353. "type" => "RCUR",
  354. "reference" => $txmd5,
  355. "status" => "FRST",
  356. "source" => "TestSource",
  357. "date" => date("Y-m-d H:i:s", strtotime("-110 days")),
  358. "creditor_id" => "3",
  359. "contact_id" => $contactId,
  360. "iban" => "0000000000000000010001",
  361. "bic" => "COLSDE22XXX",
  362. "creation_date" => date("Y-m-d H:i:s", strtotime("-110 days")),
  363. "entity_table" => "civicrm_contribution_recur",
  364. "entity_id" => $contrib["id"]
  365. );
  366. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  367. // update txgroup
  368. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  369. // close the group
  370. $this->callAPISuccess("SepaAlternativeBatching", "closeended", array("txgroup_id"=>1));
  371. // Check whether the mandate has been closed
  372. $searchParams = array(
  373. "id" => 1,
  374. "status" => 'COMPLETE'
  375. );
  376. $this->assertDBCompareValues("CRM_Sepa_DAO_SEPAMandate", array("id" => 1), $searchParams);
  377. // Check whether contribution has been flagged as ended
  378. $searchParams = array(
  379. "id" => 1,
  380. "contribution_status_id" => (int) CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name')
  381. );
  382. $this->assertDBCompareValues("CRM_Contribute_DAO_ContributionRecur", array("id" => 1), $searchParams);
  383. }
  384. /**
  385. * Test support of multiple creditors
  386. *
  387. * @author niko bochan
  388. */
  389. public function testMultipleCreditors() {
  390. // create a contact
  391. $secondCreditorId = $this->individualCreate();
  392. // create a creditor
  393. $this->assertDBQuery(NULL, "INSERT INTO `civicrm_tests_dev`.`civicrm_sdd_creditor` (`id`, `creditor_id`, `identifier`, `name`, `address`, `country_id`, `iban`, `bic`, `mandate_prefix`, `payment_processor_id`, `category`, `tag`, `mandate_active`, `sepa_file_format_id`) VALUES ('4', '%1', 'TESTCREDITORID', 'TESTCREDITOR', '108 Wayne Street', '1082', '0000000000000000000000', 'COLSDE44XXX', 'TEST', '0', 'MAIN', NULL, '1', '1');", array(1 => array($secondCreditorId, "Int")));
  394. $result = $this->createContactAndRecurContrib();
  395. // create a mandate
  396. $txmd5 = md5(date("YmdHis") . "noduplicate1");
  397. $apiParams = array(
  398. "type" => "RCUR",
  399. "reference" => $txmd5,
  400. "status" => "FRST",
  401. "source" => "TestSource",
  402. "date" => date("Y-m-d H:i:s"),
  403. "creditor_id" => "4",
  404. "contact_id" => $result["contactId"],
  405. "iban" => "0000000000000000010001",
  406. "bic" => "COLSDE22XXX",
  407. "creation_date" => date("Y-m-d H:i:s"),
  408. "entity_table" => "civicrm_contribution_recur",
  409. "entity_id" => $result["contribution"]["id"],
  410. );
  411. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  412. $result = $this->createContactAndRecurContrib();
  413. // create another mandate
  414. $txmd5 = md5(date("YmdHis") . "noduplicate2");
  415. $apiParams = array(
  416. "type" => "RCUR",
  417. "reference" => $txmd5,
  418. "status" => "FRST",
  419. "source" => "TestSource",
  420. "date" => date("Y-m-d H:i:s"),
  421. "creditor_id" => "3",
  422. "contact_id" => $result["contribution"]["id"],
  423. "iban" => "0000000000000000000110",
  424. "bic" => "COLSDE22XXX",
  425. "creation_date" => date("Y-m-d H:i:s"),
  426. "entity_table" => "civicrm_contribution_recur",
  427. "entity_id" => $result["contribution"]["id"],
  428. );
  429. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  430. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  431. // test whether exactly one txgroup has been created
  432. $this->assertDBQuery(2, 'select count(*) from civicrm_sdd_txgroup;', array());
  433. }
  434. /**
  435. * Test whether there is an error returned when we set a
  436. * txgroup status to 'received' before closing the group
  437. *
  438. * @author niko bochan
  439. */
  440. public function testReceivedBeforeClosed() {
  441. $result = $this->createContactAndRecurContrib();
  442. // create a mandate
  443. $txmd5 = md5(date("YmdHis") . "noduplicate1");
  444. $apiParams = array(
  445. "type" => "RCUR",
  446. "reference" => $txmd5,
  447. "status" => "FRST",
  448. "source" => "TestSource",
  449. "date" => date("Y-m-d H:i:s"),
  450. "creditor_id" => "3",
  451. "contact_id" => $result["contactId"],
  452. "iban" => "0000000000000000010001",
  453. "bic" => "COLSDE22XXX",
  454. "creation_date" => date("Y-m-d H:i:s"),
  455. "entity_table" => "civicrm_contribution_recur",
  456. "entity_id" => $result["contribution"]["id"],
  457. );
  458. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  459. // create another contact
  460. $result = $this->createContactAndRecurContrib();
  461. // create another mandate
  462. $txmd5 = md5(date("YmdHis") . "noduplicate2");
  463. $apiParams = array(
  464. "type" => "RCUR",
  465. "reference" => $txmd5,
  466. "status" => "FRST",
  467. "source" => "TestSource",
  468. "date" => date("Y-m-d H:i:s"),
  469. "creditor_id" => "3",
  470. "contact_id" => $result["contactId"],
  471. "iban" => "0000000000000000010001",
  472. "bic" => "COLSDE22XXX",
  473. "creation_date" => date("Y-m-d H:i:s"),
  474. "entity_table" => "civicrm_contribution_recur",
  475. "entity_id" => $result["contribution"]["id"],
  476. );
  477. $this->callAPISuccess("SepaMandate", "create", $apiParams);
  478. // update txgroup
  479. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  480. // mark the group as received
  481. $this->callAPIFailure("SepaAlternativeBatching", "received", array("txgroup_id"=>1));
  482. }
  483. /**
  484. * Test if an update after closing a group works correctly
  485. *
  486. * @see https://github.com/Project60/sepa_dd/issues/128
  487. * @author niko bochan
  488. */
  489. public function testUpdateAfterClosedRCUR() {
  490. $this->createMandate(array('type'=>'RCUR', 'status'=>'FRST'));
  491. $this->createMandate(array('type'=>'RCUR', 'status'=>'FRST'));
  492. // close the group
  493. $this->callAPISuccess("SepaAlternativeBatching", "closeended", array("txgroup_id"=>1));
  494. // update txgroup
  495. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  496. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  497. $this->assertDBQuery(1, 'select count(*) from civicrm_sdd_txgroup;', array());
  498. $this->assertDBQuery(2, 'select count(*) from civicrm_contribution_recur;', array());
  499. }
  500. /**
  501. * Test if the correct payment instrument is used throughout the RCUR status changes
  502. *
  503. * @see https://github.com/Project60/sepa_dd/issues/124
  504. * @author endres -at- systopia.de
  505. */
  506. public function testCorrectPaymentInstrumentSet() {
  507. // read the payment instrument ids
  508. $payment_instrument_FRST = (int) CRM_Core_OptionGroup::getValue('payment_instrument', 'FRST', 'name');
  509. $this->assertNotEmpty($payment_instrument_FRST, "Could not find the 'FRST' payment instrument.");
  510. $payment_instrument_RCUR = (int) CRM_Core_OptionGroup::getValue('payment_instrument', 'RCUR', 'name');
  511. $this->assertNotEmpty($payment_instrument_RCUR, "Could not find the 'RCUR' payment instrument.");
  512. // create a contact
  513. $result = $this->createContactAndRecurContrib();
  514. // create a mandate
  515. $apiParams = array(
  516. "type" => "RCUR",
  517. "status" => "FRST",
  518. "reference" => md5(microtime()),
  519. "source" => "TestSource",
  520. "date" => date("Y-m-d H:i:s"),
  521. "creditor_id" => $this->getCreditor(),
  522. "contact_id" => $result["contactId"],
  523. "iban" => "0000000000000000010001",
  524. "bic" => "COLSDE22XXX",
  525. "creation_date" => date("Y-m-d H:i:s"),
  526. "entity_table" => "civicrm_contribution_recur",
  527. "entity_id" => $result["contribution"]["id"],
  528. );
  529. $mandate = $this->callAPISuccess("SepaMandate", "create", $apiParams);
  530. // check the batching creates a contribution with ther right payment instrument
  531. $sql = "select count(*) from civicrm_contribution where payment_instrument_id = '%1';";
  532. $this->assertDBQuery(0, $sql, array(1 => array($payment_instrument_FRST, 'Integer'))); // "There is already a payment in the DB. Weird"
  533. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  534. $this->assertDBQuery(1, $sql, array(1 => array($payment_instrument_FRST, 'Integer'))); // "Batching has not created a correct payment."
  535. // now change the status of the mandate to 'RCUR'
  536. // FIXME: do this via the closegroup API
  537. $this->callAPISuccess("SepaMandate", "create", array('id' => $mandate['id'], 'status' => 'RCUR'));
  538. // again: check the batching creates a contribution with ther right payment instrument
  539. $this->assertDBQuery(0, $sql, array(1 => array($payment_instrument_RCUR, 'Integer'))); // "There is already a payment in the DB. Weird"
  540. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "RCUR"));
  541. $this->assertDBQuery(1, $sql, array(1 => array($payment_instrument_RCUR, 'Integer'))); // "Batching has not created a correct payment."
  542. }
  543. /**
  544. * See if the status change from FRST to RCUR works correctly
  545. *
  546. * @see https://github.com/Project60/sepa_dd/issues/128
  547. * @author endres -at- systopia.de
  548. */
  549. public function testFRSTtoRCURswitch() {
  550. // select cycle day so that the submission would be due today
  551. $frst_notice = CRM_Core_BAO_Setting::getItem('SEPA Direct Debit Preferences', 'batching_alt_FRST_notice');
  552. $this->assertNotEmpty($frst_notice, "No FRST notice period specified!");
  553. CRM_Core_BAO_Setting::setItem('SEPA Direct Debit Preferences', 'batching_alt_RCUR_notice', $frst_notice);
  554. $rcur_notice = CRM_Core_BAO_Setting::getItem('SEPA Direct Debit Preferences', 'batching_alt_RCUR_notice');
  555. $this->assertNotEmpty($rcur_notice, "No RCUR notice period specified!");
  556. $this->assertEquals($frst_notice, $rcur_notice, "Notice periods should be the same.");
  557. $cycle_day = date("d", strtotime("+$frst_notice days"));
  558. // also, horizon mustn't be big enough to create another contribution
  559. CRM_Core_BAO_Setting::setItem(27, 'SEPA Direct Debit Preferences', 'batching_alt_FRST_horizon');
  560. $frst_horizon = CRM_Core_BAO_Setting::getItem('SEPA Direct Debit Preferences', 'batching_alt_FRST_horizon');
  561. $this->assertEquals(27, $frst_horizon);
  562. CRM_Core_BAO_Setting::setItem(27, 'SEPA Direct Debit Preferences', 'batching_alt_RCUR_horizon');
  563. $rcur_horizon = CRM_Core_BAO_Setting::getItem('SEPA Direct Debit Preferences', 'batching_alt_RCUR_horizon');
  564. $this->assertEquals(27, $rcur_horizon);
  565. // 1) create a FRST mandate, due for collection right now
  566. $mandate = $this->createMandate(array('type'=>'RCUR', 'status'=>'FRST'), array('cycle_day' => $cycle_day));
  567. $mandate_before_batching = $this->callAPISuccess("SepaMandate", "getsingle", array("id" => $mandate['id']));
  568. $this->assertTrue(($mandate_before_batching['status']=='FRST'), "Mandate was not created in the correct status.");
  569. // 2) call batching
  570. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  571. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "RCUR"));
  572. // 3) find and check the created contribution
  573. $contribution_recur_id = $mandate['entity_id'];
  574. $this->assertNotEmpty($contribution_recur_id, "No entity set in mandate");
  575. $contribution_id = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_contribution WHERE contribution_recur_id=$contribution_recur_id;");
  576. $this->assertNotEmpty($contribution_id, "Couldn't find created contribution.");
  577. $this->assertDBQuery(1, "SELECT count(id) FROM civicrm_contribution WHERE contribution_recur_id=$contribution_recur_id;");
  578. // 4) close the group
  579. $this->assertDBQuery(1, "SELECT count(txgroup_id) FROM civicrm_sdd_contribution_txgroup WHERE contribution_id=$contribution_id;");
  580. $txgroup_id = CRM_Core_DAO::singleValueQuery("SELECT txgroup_id FROM civicrm_sdd_contribution_txgroup WHERE contribution_id=$contribution_id;");
  581. $this->assertNotEmpty($txgroup_id, "Contribution was not added to a group!");
  582. $txgroup = $this->callAPISuccess("SepaTransactionGroup", "getsingle", array("id" => $txgroup_id));
  583. $latest_submission_date = substr($txgroup['latest_submission_date'], 0, 10);
  584. $this->assertEquals(date('Y-m-d'), $latest_submission_date, "The group should be due today! Check test configuration!");
  585. $this->callAPISuccess("SepaAlternativeBatching", "close", array("txgroup_id" => $txgroup_id));
  586. // 5) check if contribution and mandate are in the correct state (RCUR)
  587. $mandate_after_batching = $this->callAPISuccess("SepaMandate", "getsingle", array("id" => $mandate['id']));
  588. $this->assertTrue(($mandate_after_batching['status']=='RCUR'), "Mandate was not switched to status 'RCUR' after group was closed");
  589. $contribution = $this->callAPISuccess("Contribution", "getsingle", array("id" => $contribution_id));
  590. $this->assertEquals('FRST', $contribution['contribution_payment_instrument'], "Created contribution does not have payment instrument 'FRST'!");
  591. // uncomment this, if you want to provoke an error like https://github.com/Project60/sepa_dd/issues/128
  592. //$this->assertDBQuery(0, "UPDATE civicrm_sdd_mandate SET first_contribution_id=NULL WHERE id=".$mandate['id'].";");
  593. // 5) call batching again
  594. $group_count_before = CRM_Core_DAO::singleValueQuery("SELECT COUNT(id) FROM civicrm_sdd_txgroup;");
  595. $contribution_count_before = CRM_Core_DAO::singleValueQuery("SELECT COUNT(id) FROM civicrm_contribution;");
  596. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "FRST"));
  597. $this->callAPISuccess("SepaAlternativeBatching", "update", array("type" => "RCUR"));
  598. // 6) check that there NO new group and no new contribution has been created
  599. $group_count_after = CRM_Core_DAO::singleValueQuery("SELECT COUNT(id) FROM civicrm_sdd_txgroup;");
  600. $contribution_count_after = CRM_Core_DAO::singleValueQuery("SELECT COUNT(id) FROM civicrm_contribution;");
  601. $this->assertEquals($contribution_count_before, $contribution_count_after, "A new contribution has been created, but shouldn't have!");
  602. $this->assertEquals($group_count_before, $group_count_after, "A new group has been created, but shouldn't have!");
  603. $this->assertDBQuery(1, "SELECT count(id) FROM civicrm_contribution WHERE contribution_recur_id=$contribution_recur_id;");
  604. }
  605. }