TaxRuleRepositoryTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Tax\Model;
  7. use Magento\Framework\Api\Filter;
  8. use Magento\TestFramework\Helper\Bootstrap;
  9. /**
  10. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  11. */
  12. class TaxRuleRepositoryTest extends \PHPUnit\Framework\TestCase
  13. {
  14. /**
  15. * @var \Magento\Framework\ObjectManagerInterface
  16. */
  17. private $objectManager;
  18. /**
  19. * @var \Magento\Tax\Api\Data\TaxRuleInterfaceFactory
  20. */
  21. private $taxRuleFactory;
  22. /**
  23. * @var \Magento\Tax\Api\TaxRuleRepositoryInterface
  24. */
  25. private $taxRuleRepository;
  26. /**
  27. * @var TaxRuleFixtureFactory
  28. */
  29. private $taxRuleFixtureFactory;
  30. /**
  31. * Array of default tax classes ids
  32. *
  33. * Key is class name
  34. *
  35. * @var int[]
  36. */
  37. private $taxClasses;
  38. /**
  39. * Array of default tax rates ids.
  40. *
  41. * Key is rate percentage as string.
  42. *
  43. * @var int[]
  44. */
  45. private $taxRates;
  46. /**
  47. * Array of default tax rules ids.
  48. *
  49. * Key is rule code.
  50. *
  51. * @var int[]
  52. */
  53. private $taxRules;
  54. /**
  55. * @var \Magento\Tax\Api\TaxRateRepositoryInterface
  56. */
  57. private $taxRateRepository;
  58. /**
  59. * @var \Magento\Framework\Api\DataObjectHelper
  60. */
  61. private $dataObjectHelper;
  62. protected function setUp()
  63. {
  64. $this->objectManager = Bootstrap::getObjectManager();
  65. $this->taxRuleRepository = $this->objectManager->get(\Magento\Tax\Api\TaxRuleRepositoryInterface::class);
  66. $this->taxRateRepository = $this->objectManager->get(\Magento\Tax\Api\TaxRateRepositoryInterface::class);
  67. $this->taxRuleFactory = $this->objectManager->create(\Magento\Tax\Api\Data\TaxRuleInterfaceFactory::class);
  68. $this->dataObjectHelper = $this->objectManager->create(\Magento\Framework\Api\DataObjectHelper::class);
  69. $this->taxRuleFixtureFactory = new TaxRuleFixtureFactory();
  70. }
  71. /**
  72. * @magentoDbIsolation enabled
  73. */
  74. public function testSave()
  75. {
  76. // Tax rule data object created
  77. $taxRuleDataObject = $this->createTaxRuleDataObject();
  78. //Tax rule service call
  79. $taxRule = $this->taxRuleRepository->save($taxRuleDataObject);
  80. //Assertions
  81. $this->assertInstanceOf(\Magento\Tax\Api\Data\TaxRuleInterface::class, $taxRule);
  82. $this->assertEquals($taxRuleDataObject->getCode(), $taxRule->getCode());
  83. $this->assertEquals(
  84. $taxRuleDataObject->getCustomerTaxClassIds(),
  85. $taxRule->getCustomerTaxClassIds()
  86. );
  87. $this->assertEquals($taxRuleDataObject->getProductTaxClassIds(), $taxRule->getProductTaxClassIds());
  88. $this->assertEquals($taxRuleDataObject->getPriority(), $taxRule->getPriority());
  89. $this->assertEquals($taxRuleDataObject->getPosition(), $taxRule->getPosition());
  90. $this->assertNotNull($taxRule->getId());
  91. }
  92. /**
  93. * @expectedException \Magento\Framework\Exception\NoSuchEntityException
  94. * @expectedExceptionMessage No such entity with taxRuleId = 9999
  95. * @magentoDbIsolation enabled
  96. */
  97. public function testSaveThrowsExceptionIdIfTargetTaxRuleDoesNotExist()
  98. {
  99. $taxRuleDataObject = $this->taxRuleFactory->create();
  100. $taxRuleDataObject->setId(9999)
  101. ->setCode('code')
  102. ->setCustomerTaxClassIds([3])
  103. ->setProductTaxClassIds([2])
  104. ->setTaxRateIds([2])
  105. ->setPriority(0)
  106. ->setPosition(1);
  107. $this->taxRuleRepository->save($taxRuleDataObject);
  108. }
  109. /**
  110. * @magentoDbIsolation enabled
  111. * @expectedException \Magento\Framework\Exception\CouldNotSaveException
  112. * @expectedExceptionMessage No such entity
  113. */
  114. public function testSaveThrowsExceptionIfProvidedTaxClassIdsAreInvalid()
  115. {
  116. $taxRuleData = [
  117. 'code' => 'code',
  118. // These TaxClassIds exist, but '2' is should be a productTaxClassId and
  119. // '3' should be a customerTaxClassId. See MAGETWO-25683.
  120. 'customer_tax_class_ids' => [2],
  121. 'product_tax_class_ids' => [3],
  122. 'tax_rate_ids' => [1],
  123. 'priority' => 0,
  124. 'position' => 0,
  125. ];
  126. // Tax rule data object created
  127. $taxRule = $this->taxRuleFactory->create();
  128. $this->dataObjectHelper->populateWithArray(
  129. $taxRule,
  130. $taxRuleData,
  131. \Magento\Tax\Api\Data\TaxRuleInterface::class
  132. );
  133. $this->taxRuleRepository->save($taxRule);
  134. }
  135. /**
  136. * @magentoDbIsolation enabled
  137. * @expectedException \Magento\Framework\Exception\CouldNotSaveException
  138. * @expectedExceptionMessage The position value of "-1" must be greater than or equal to 0.
  139. */
  140. public function testSaveThrowsExceptionIfProvidedPositionIsInvalid()
  141. {
  142. $taxRuleData = [
  143. 'code' => 'code',
  144. 'customer_tax_class_ids' => [3],
  145. 'product_tax_class_ids' => [2],
  146. 'tax_rate_ids' => [1],
  147. 'priority' => 0,
  148. 'position' => -1,
  149. ];
  150. // Tax rule data object created
  151. $taxRule = $this->taxRuleFactory->create();
  152. $this->dataObjectHelper->populateWithArray(
  153. $taxRule,
  154. $taxRuleData,
  155. \Magento\Tax\Api\Data\TaxRuleInterface::class
  156. );
  157. //Tax rule service call
  158. $this->taxRuleRepository->save($taxRule);
  159. $this->fail('Did not throw expected InputException');
  160. }
  161. /**
  162. * @magentoDbIsolation enabled
  163. */
  164. public function testGetReturnsTaxRuleCreatedByRepository()
  165. {
  166. // Tax rule data object created
  167. $taxRuleDataObject = $this->createTaxRuleDataObject();
  168. //Tax rule service call to create rule
  169. $ruleId = $this->taxRuleRepository->save($taxRuleDataObject)->getId();
  170. // Call getTaxRule and verify
  171. $taxRule = $this->taxRuleRepository->get($ruleId);
  172. $this->assertEquals('code', $taxRule->getCode());
  173. $this->assertEquals([3], $taxRule->getCustomerTaxClassIds());
  174. $this->assertEquals([2], $taxRule->getProductTaxClassIds());
  175. $this->assertEquals([2], $taxRule->getTaxRateIds());
  176. $this->assertEquals(0, $taxRule->getPriority());
  177. $this->assertEquals(1, $taxRule->getPosition());
  178. }
  179. /**
  180. * @magentoDataFixture Magento/Tax/_files/tax_classes.php
  181. */
  182. public function testGetReturnsTaxRuleCreatedFromModel()
  183. {
  184. /** @var $registry \Magento\Framework\Registry */
  185. $registry = $this->objectManager->get(\Magento\Framework\Registry::class);
  186. /** @var $taxRuleModel \Magento\Tax\Model\Calculation\Rule */
  187. $taxRuleModel = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rule');
  188. $this->assertNotNull($taxRuleModel);
  189. $ruleId = $taxRuleModel->getId();
  190. $taxRateId = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rate')->getId();
  191. $customerTaxClassIds = array_values(array_unique($taxRuleModel->getCustomerTaxClasses()));
  192. // Call getTaxRule and verify
  193. $taxRule = $this->taxRuleRepository->get($ruleId);
  194. $this->assertEquals($customerTaxClassIds, $taxRule->getCustomerTaxClassIds());
  195. $this->assertEquals([$taxRateId], $taxRule->getTaxRateIds());
  196. }
  197. /**
  198. * @magentoDataFixture Magento/Tax/_files/tax_classes.php
  199. * @expectedException \Magento\Framework\Exception\NoSuchEntityException
  200. * @expectedExceptionMessage No such entity with taxRuleId
  201. */
  202. public function testDeleteById()
  203. {
  204. /** @var $registry \Magento\Framework\Registry */
  205. $registry = $this->objectManager->get(\Magento\Framework\Registry::class);
  206. /** @var $taxRule \Magento\Tax\Model\Calculation\Rule */
  207. $taxRule = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rule');
  208. $this->assertNotNull($taxRule);
  209. $ruleId = $taxRule->getId();
  210. // Delete the new tax rate
  211. $this->assertTrue($this->taxRuleRepository->deleteById($ruleId));
  212. // Get the new tax rule, this should fail
  213. $this->taxRuleRepository->get($ruleId);
  214. }
  215. /**
  216. * @magentoDataFixture Magento/Tax/_files/tax_classes.php
  217. * @expectedException \Magento\Framework\Exception\NoSuchEntityException
  218. * @expectedExceptionMessage No such entity with taxRuleId
  219. */
  220. public function testDeleteByIdThrowsExceptionIfTargetTaxRuleDoesNotExist()
  221. {
  222. /** @var $registry \Magento\Framework\Registry */
  223. $registry = $this->objectManager->get(\Magento\Framework\Registry::class);
  224. /** @var $taxRule \Magento\Tax\Model\Calculation\Rule */
  225. $taxRule = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rule');
  226. $this->assertNotNull($taxRule);
  227. $ruleId = $taxRule->getId();
  228. // Delete the new tax rule
  229. $this->assertTrue($this->taxRuleRepository->deleteById($ruleId));
  230. // Delete the new tax rule again, this should fail
  231. $this->taxRuleRepository->deleteById($ruleId);
  232. }
  233. /**
  234. * @magentoDbIsolation enabled
  235. */
  236. public function testSaveUpdatesExistingTaxRule()
  237. {
  238. $taxRule = $this->createTaxRuleDataObject();
  239. //Tax rule service call
  240. $taxRule = $this->taxRuleRepository->save($taxRule);
  241. $taxRule->setCode('updated code');
  242. $this->taxRuleRepository->save($taxRule);
  243. $retrievedRule = $this->taxRuleRepository->get($taxRule->getId());
  244. $this->assertEquals('updated code', $retrievedRule->getCode());
  245. }
  246. /**
  247. * @magentoDbIsolation enabled
  248. * @expectedException \Magento\Framework\Exception\CouldNotSaveException
  249. * @expectedExceptionMessage "code" is required. Enter and try again.
  250. */
  251. public function testSaveThrowsExceptionIsRequiredFieldsAreMissing()
  252. {
  253. $taxRule = $this->taxRuleRepository->save($this->createTaxRuleDataObject());
  254. $taxRule->setCode(null);
  255. $this->taxRuleRepository->save($taxRule);
  256. }
  257. /**
  258. *
  259. * @param Filter[] $filters
  260. * @param Filter[] $filterGroup
  261. * @param string[] $expectedRuleCodes The codes of the tax rules that are expected to be found
  262. *
  263. * @magentoDbIsolation enabled
  264. * @dataProvider searchTaxRulesDataProvider
  265. */
  266. public function testGetList($filters, $filterGroup, $expectedRuleCodes)
  267. {
  268. $this->setUpDefaultRules();
  269. /** @var \Magento\Framework\Api\SearchCriteriaBuilder $searchBuilder */
  270. $searchBuilder = Bootstrap::getObjectManager()
  271. ->create(\Magento\Framework\Api\SearchCriteriaBuilder::class);
  272. foreach ($filters as $filter) {
  273. $searchBuilder->addFilters([$filter]);
  274. }
  275. if ($filterGroup !== null) {
  276. $searchBuilder->addFilters($filterGroup);
  277. }
  278. $searchCriteria = $searchBuilder->create();
  279. $searchResults = $this->taxRuleRepository->getList($searchCriteria);
  280. $items = [];
  281. foreach ($expectedRuleCodes as $ruleCode) {
  282. $ruleId = $this->taxRules[$ruleCode];
  283. $items[] = $this->taxRuleRepository->get($ruleId);
  284. }
  285. $this->assertEquals($searchCriteria, $searchResults->getSearchCriteria());
  286. $this->assertEquals(count($expectedRuleCodes), $searchResults->getTotalCount());
  287. foreach ($searchResults->getItems() as $rule) {
  288. $this->assertContains($rule->getCode(), $expectedRuleCodes);
  289. }
  290. $this->tearDownDefaultRules();
  291. }
  292. public function searchTaxRulesDataProvider()
  293. {
  294. $filterBuilder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  295. return [
  296. 'code eq "Default Rule"' => [
  297. [$filterBuilder->setField('code')->setValue('Default Rule')->create()],
  298. null,
  299. ['Default Rule'],
  300. ],
  301. 'customer_tax_class_ids eq 3 AND priority eq 0' => [
  302. [
  303. $filterBuilder->setField('customer_tax_class_ids')->setValue(3)->create(),
  304. $filterBuilder->setField('priority')->setValue('0')->create(),
  305. ],
  306. [],
  307. ['Default Rule', 'Higher Rate Rule'],
  308. ],
  309. 'code eq "Default Rule" OR code eq "Higher Rate Rule"' => [
  310. [],
  311. [
  312. $filterBuilder->setField('code')->setValue('Default Rule')->create(),
  313. $filterBuilder->setField('code')->setValue('Higher Rate Rule')->create(),
  314. ],
  315. ['Default Rule', 'Higher Rate Rule'],
  316. ],
  317. 'code like "%Rule"' => [
  318. [
  319. $filterBuilder->setField('code')->setValue('%Rule')->setConditionType('like')
  320. ->create(),
  321. ],
  322. [],
  323. ['Default Rule', 'Higher Rate Rule'],
  324. ],
  325. ];
  326. }
  327. /**
  328. * Helper function that sets up some default rules
  329. */
  330. private function setUpDefaultRules()
  331. {
  332. $this->taxClasses = $this->taxRuleFixtureFactory->createTaxClasses([
  333. ['name' => 'DefaultCustomerClass', 'type' => ClassModel::TAX_CLASS_TYPE_CUSTOMER],
  334. ['name' => 'DefaultProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
  335. ['name' => 'HigherProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
  336. ]);
  337. $this->taxRates = $this->taxRuleFixtureFactory->createTaxRates([
  338. ['percentage' => 7.5, 'country' => 'US', 'region' => 42],
  339. ['percentage' => 7.5, 'country' => 'US', 'region' => 12], // Default store rate
  340. ]);
  341. $higherRates = $this->taxRuleFixtureFactory->createTaxRates([
  342. ['percentage' => 22, 'country' => 'US', 'region' => 42],
  343. ['percentage' => 10, 'country' => 'US', 'region' => 12], // Default store rate
  344. ]);
  345. $this->taxRules = $this->taxRuleFixtureFactory->createTaxRules([
  346. [
  347. 'code' => 'Default Rule',
  348. 'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
  349. 'product_tax_class_ids' => [$this->taxClasses['DefaultProductClass']],
  350. 'tax_rate_ids' => array_values($this->taxRates),
  351. 'sort_order' => 0,
  352. 'priority' => 0,
  353. 'calculate_subtotal' => 1,
  354. ],
  355. [
  356. 'code' => 'Higher Rate Rule',
  357. 'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
  358. 'product_tax_class_ids' => [$this->taxClasses['HigherProductClass']],
  359. 'tax_rate_ids' => array_values($higherRates),
  360. 'sort_order' => 0,
  361. 'priority' => 0,
  362. 'calculate_subtotal' => 1,
  363. ],
  364. [
  365. 'code' => 'Highest Rate',
  366. 'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
  367. 'product_tax_class_ids' => [$this->taxClasses['HigherProductClass']],
  368. 'tax_rate_ids' => array_values($higherRates),
  369. 'sort_order' => 1,
  370. 'priority' => 1,
  371. 'calculate_subtotal' => 0,
  372. ],
  373. ]);
  374. // For cleanup
  375. $this->taxRates = array_merge($this->taxRates, $higherRates);
  376. }
  377. /**
  378. * Helper function that tears down some default rules
  379. */
  380. private function tearDownDefaultRules()
  381. {
  382. $this->taxRuleFixtureFactory->deleteTaxRules(array_values($this->taxRules));
  383. $this->taxRuleFixtureFactory->deleteTaxRates(array_values($this->taxRates));
  384. $this->taxRuleFixtureFactory->deleteTaxClasses(array_values($this->taxClasses));
  385. }
  386. /**
  387. * Creates Tax Rule Data Object
  388. *
  389. * @return \Magento\Tax\Api\Data\TaxRuleInterface
  390. */
  391. private function createTaxRuleDataObject()
  392. {
  393. $taxRule = $this->taxRuleFactory->create();
  394. $taxRule->setCode('code')
  395. ->setCustomerTaxClassIds([3])
  396. ->setProductTaxClassIds([2])
  397. ->setTaxRateIds([2])
  398. ->setPriority(0)
  399. ->setPosition(1);
  400. return $taxRule;
  401. }
  402. }