TaxRateRepositoryTest.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Tax\Api;
  7. use Magento\Framework\Api\FilterBuilder;
  8. use Magento\Framework\Api\SearchCriteriaBuilder;
  9. use Magento\Framework\Api\SortOrder;
  10. use Magento\Framework\Api\SortOrderBuilder;
  11. use Magento\Tax\Model\Calculation\Rate;
  12. use Magento\TestFramework\Helper\Bootstrap;
  13. use Magento\TestFramework\TestCase\WebapiAbstract;
  14. /**
  15. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  16. */
  17. class TaxRateRepositoryTest extends WebapiAbstract
  18. {
  19. const SERVICE_NAME = "taxTaxRateRepositoryV1";
  20. const SERVICE_VERSION = "V1";
  21. const RESOURCE_PATH = "/V1/taxRates";
  22. /** @var \Magento\Tax\Model\Calculation\Rate[] */
  23. private $fixtureTaxRates;
  24. /** @var \Magento\Tax\Model\ClassModel[] */
  25. private $fixtureTaxClasses;
  26. /** @var \Magento\Tax\Model\Calculation\Rule[] */
  27. private $fixtureTaxRules;
  28. /**
  29. * @var \Magento\Tax\Api\TaxRateRepositoryInterface
  30. */
  31. private $taxRateService;
  32. /** @var FilterBuilder */
  33. private $filterBuilder;
  34. /** @var SearchCriteriaBuilder */
  35. private $searchCriteriaBuilder;
  36. /** @var SortOrderBuilder */
  37. private $sortOrderBuilder;
  38. /**
  39. * Other rates created during tests, to be deleted in tearDown()
  40. *
  41. * @var \Magento\Tax\Model\Calculation\Rate[]
  42. */
  43. private $otherRates = [];
  44. /**
  45. * Execute per test initialization.
  46. */
  47. public function setUp()
  48. {
  49. $objectManager = Bootstrap::getObjectManager();
  50. $this->taxRateService = $objectManager->get(\Magento\Tax\Api\TaxRateRepositoryInterface::class);
  51. $this->searchCriteriaBuilder = $objectManager->create(
  52. \Magento\Framework\Api\SearchCriteriaBuilder::class
  53. );
  54. $this->filterBuilder = $objectManager->create(
  55. \Magento\Framework\Api\FilterBuilder::class
  56. );
  57. $this->sortOrderBuilder = $objectManager->create(
  58. \Magento\Framework\Api\SortOrderBuilder::class
  59. );
  60. /** Initialize tax classes, tax rates and tax rules defined in fixture Magento/Tax/_files/tax_classes.php */
  61. $this->getFixtureTaxRates();
  62. $this->getFixtureTaxClasses();
  63. $this->getFixtureTaxRules();
  64. }
  65. public function tearDown()
  66. {
  67. $taxRules = $this->getFixtureTaxRules();
  68. if (count($taxRules)) {
  69. $taxRates = $this->getFixtureTaxRates();
  70. $taxClasses = $this->getFixtureTaxClasses();
  71. foreach ($taxRules as $taxRule) {
  72. $taxRule->delete();
  73. }
  74. foreach ($taxRates as $taxRate) {
  75. $taxRate->delete();
  76. }
  77. foreach ($taxClasses as $taxClass) {
  78. $taxClass->delete();
  79. }
  80. }
  81. if (count($this->otherRates)) {
  82. foreach ($this->otherRates as $taxRate) {
  83. $taxRate->delete();
  84. }
  85. }
  86. }
  87. public function testCreateTaxRateExistingCode()
  88. {
  89. $expectedMessage = '%1 already exists.';
  90. $data = [
  91. 'tax_rate' => [
  92. 'tax_country_id' => 'US',
  93. 'tax_region_id' => 12,
  94. 'tax_postcode' => '*',
  95. 'code' => 'US-CA-*-Rate 1',
  96. 'rate' => '8.2501',
  97. ],
  98. ];
  99. $serviceInfo = [
  100. 'rest' => [
  101. 'resourcePath' => self::RESOURCE_PATH,
  102. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  103. ],
  104. 'soap' => [
  105. 'service' => self::SERVICE_NAME,
  106. 'serviceVersion' => self::SERVICE_VERSION,
  107. 'operation' => self::SERVICE_NAME . 'Save',
  108. ],
  109. ];
  110. try {
  111. $this->_webApiCall($serviceInfo, $data);
  112. $this->fail('Expected exception was not raised');
  113. } catch (\SoapFault $e) {
  114. $this->assertContains(
  115. $expectedMessage,
  116. $e->getMessage(),
  117. 'SoapFault does not contain expected message.'
  118. );
  119. } catch (\Exception $e) {
  120. $errorObj = $this->processRestExceptionResult($e);
  121. $this->assertEquals($expectedMessage, $errorObj['message']);
  122. $this->assertEquals(['Code'], $errorObj['parameters']);
  123. }
  124. }
  125. public function testCreateTaxRateWithoutValue()
  126. {
  127. $data = [
  128. 'tax_rate' => [
  129. 'tax_country_id' => 'US',
  130. 'tax_region_id' => 12,
  131. 'tax_postcode' => '*',
  132. 'code' => 'US-CA-*-Rate 1',
  133. ],
  134. ];
  135. $serviceInfo = [
  136. 'rest' => [
  137. 'resourcePath' => self::RESOURCE_PATH,
  138. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  139. ],
  140. 'soap' => [
  141. 'service' => self::SERVICE_NAME,
  142. 'serviceVersion' => self::SERVICE_VERSION,
  143. 'operation' => self::SERVICE_NAME . 'Save',
  144. ],
  145. ];
  146. try {
  147. $this->_webApiCall($serviceInfo, $data);
  148. $this->fail('Expected exception was not raised');
  149. } catch (\SoapFault $e) {
  150. $this->assertContains(
  151. 'SOAP-ERROR: Encoding: object has no \'rate\' property',
  152. $e->getMessage(),
  153. 'SoapFault does not contain expected message.'
  154. );
  155. } catch (\Exception $e) {
  156. $errorObj = $this->processRestExceptionResult($e);
  157. $this->assertEquals('"%fieldName" is required. Enter and try again.', $errorObj['message']);
  158. $this->assertEquals(['fieldName' => 'percentage_rate'], $errorObj['parameters']);
  159. }
  160. }
  161. public function testCreateTaxRate()
  162. {
  163. $data = [
  164. 'tax_rate' => [
  165. 'tax_country_id' => 'US',
  166. 'tax_region_id' => 12,
  167. 'tax_postcode' => '*',
  168. 'code' => 'Test Tax Rate ' . microtime(),
  169. 'rate' => '8.2501',
  170. ],
  171. ];
  172. $serviceInfo = [
  173. 'rest' => [
  174. 'resourcePath' => self::RESOURCE_PATH,
  175. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  176. ],
  177. 'soap' => [
  178. 'service' => self::SERVICE_NAME,
  179. 'serviceVersion' => self::SERVICE_VERSION,
  180. 'operation' => self::SERVICE_NAME . 'Save',
  181. ],
  182. ];
  183. $result = $this->_webApiCall($serviceInfo, $data);
  184. $this->assertArrayHasKey('id', $result);
  185. $taxRateId = $result['id'];
  186. /** Ensure that tax rate was actually created in DB */
  187. /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
  188. $taxRate = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rate::class);
  189. $this->assertEquals($taxRateId, $taxRate->load($taxRateId)->getId(), 'Tax rate was not created in DB.');
  190. $taxRate->delete();
  191. }
  192. public function testCreateTaxRateWithZipRange()
  193. {
  194. $data = [
  195. 'tax_rate' => [
  196. 'tax_country_id' => 'US',
  197. 'tax_region_id' => 12,
  198. 'code' => 'Test Tax Rate ' . microtime(),
  199. 'rate' => '8.2501',
  200. 'zip_is_range' => 1,
  201. 'zip_from' => 17,
  202. 'zip_to' => 25,
  203. ],
  204. ];
  205. $serviceInfo = [
  206. 'rest' => [
  207. 'resourcePath' => self::RESOURCE_PATH,
  208. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  209. ],
  210. 'soap' => [
  211. 'service' => self::SERVICE_NAME,
  212. 'serviceVersion' => self::SERVICE_VERSION,
  213. 'operation' => self::SERVICE_NAME . 'Save',
  214. ],
  215. ];
  216. $result = $this->_webApiCall($serviceInfo, $data);
  217. $this->assertArrayHasKey('id', $result);
  218. $taxRateId = $result['id'];
  219. /** Ensure that tax rate was actually created in DB */
  220. /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
  221. $taxRate = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rate::class);
  222. $this->assertEquals($taxRateId, $taxRate->load($taxRateId)->getId(), 'Tax rate was not created in DB.');
  223. $this->assertEquals('17-25', $taxRate->getTaxPostcode(), 'Zip range is not saved in DB.');
  224. $taxRate->delete();
  225. }
  226. public function testCreateTaxRateWithZeroValue()
  227. {
  228. $data = [
  229. 'tax_rate' => [
  230. 'tax_country_id' => 'US',
  231. 'tax_region_id' => 12,
  232. 'tax_postcode' => '*',
  233. 'code' => 'Test Tax Rate ' . microtime(),
  234. 'rate' => '0.0',
  235. ],
  236. ];
  237. $serviceInfo = [
  238. 'rest' => [
  239. 'resourcePath' => self::RESOURCE_PATH,
  240. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  241. ],
  242. 'soap' => [
  243. 'service' => self::SERVICE_NAME,
  244. 'serviceVersion' => self::SERVICE_VERSION,
  245. 'operation' => self::SERVICE_NAME . 'Save',
  246. ],
  247. ];
  248. $result = $this->_webApiCall($serviceInfo, $data);
  249. $this->assertArrayHasKey('id', $result);
  250. $taxRateId = $result['id'];
  251. /** Ensure that tax rate was actually created in DB */
  252. /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
  253. $taxRate = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rate::class);
  254. $taxModel = $taxRate->load($taxRateId);
  255. $this->assertEquals($taxRateId, $taxModel->getId(), 'Tax rate was not created in DB.');
  256. $this->assertEquals(0, $taxModel->getRate(), 'Tax rate value is wrong.');
  257. $taxRate->delete();
  258. }
  259. /**
  260. * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
  261. */
  262. public function testUpdateTaxRate()
  263. {
  264. $fixtureRate = $this->getFixtureTaxRates()[0];
  265. $data = [
  266. 'tax_rate' => [
  267. 'id' => $fixtureRate->getId(),
  268. 'tax_region_id' => 43,
  269. 'tax_country_id' => 'US',
  270. 'tax_postcode' => '07400',
  271. 'code' => 'Test Tax Rate ' . microtime(),
  272. 'rate' => 3.456,
  273. ],
  274. ];
  275. $serviceInfo = [
  276. 'rest' => [
  277. 'resourcePath' => self::RESOURCE_PATH,
  278. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  279. ],
  280. 'soap' => [
  281. 'service' => self::SERVICE_NAME,
  282. 'serviceVersion' => self::SERVICE_VERSION,
  283. 'operation' => self::SERVICE_NAME . 'Save',
  284. ],
  285. ];
  286. $this->_webApiCall($serviceInfo, $data);
  287. $expectedRateData = $data['tax_rate'];
  288. /** Ensure that tax rate was actually updated in DB */
  289. /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
  290. $taxRate = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rate::class);
  291. $taxRateModel = $taxRate->load($fixtureRate->getId());
  292. $this->assertEquals($expectedRateData['id'], $taxRateModel->getId(), 'Tax rate was not updated in DB.');
  293. $this->assertEquals(
  294. $expectedRateData['tax_region_id'],
  295. $taxRateModel->getTaxRegionId(),
  296. 'Tax rate was not updated in DB.'
  297. );
  298. $this->assertEquals(
  299. $expectedRateData['tax_country_id'],
  300. $taxRateModel->getTaxCountryId(),
  301. 'Tax rate was not updated in DB.'
  302. );
  303. $this->assertEquals(
  304. $expectedRateData['tax_postcode'],
  305. $taxRateModel->getTaxPostcode(),
  306. 'Tax rate was not updated in DB.'
  307. );
  308. $this->assertEquals($expectedRateData['code'], $taxRateModel->getCode(), 'Tax rate was not updated in DB.');
  309. $this->assertEquals(
  310. $expectedRateData['rate'],
  311. $taxRateModel->getRate(),
  312. 'Tax rate was not updated in DB.'
  313. );
  314. }
  315. public function testUpdateTaxRateNotExisting()
  316. {
  317. $data = [
  318. 'tax_rate' => [
  319. 'id' => 555,
  320. 'tax_region_id' => 43,
  321. 'tax_country_id' => 'US',
  322. 'tax_postcode' => '07400',
  323. 'code' => 'Test Tax Rate ' . microtime(),
  324. 'rate' => 3.456,
  325. ],
  326. ];
  327. $serviceInfo = [
  328. 'rest' => [
  329. 'resourcePath' => self::RESOURCE_PATH,
  330. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  331. ],
  332. 'soap' => [
  333. 'service' => self::SERVICE_NAME,
  334. 'serviceVersion' => self::SERVICE_VERSION,
  335. 'operation' => self::SERVICE_NAME . 'Save',
  336. ],
  337. ];
  338. try {
  339. $this->_webApiCall($serviceInfo, $data);
  340. $this->fail('Expected exception was not raised');
  341. } catch (\Exception $e) {
  342. $expectedMessage = 'No such entity with %fieldName = %fieldValue';
  343. $this->assertContains(
  344. $expectedMessage,
  345. $e->getMessage(),
  346. "Exception does not contain expected message."
  347. );
  348. }
  349. }
  350. public function testGetTaxRate()
  351. {
  352. $taxRateId = 2;
  353. $serviceInfo = [
  354. 'rest' => [
  355. 'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
  356. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  357. ],
  358. 'soap' => [
  359. 'service' => self::SERVICE_NAME,
  360. 'serviceVersion' => self::SERVICE_VERSION,
  361. 'operation' => self::SERVICE_NAME . 'Get',
  362. ],
  363. ];
  364. $result = $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
  365. $expectedRateData = [
  366. 'id' => 2,
  367. 'tax_country_id' => 'US',
  368. 'tax_region_id' => 43,
  369. 'tax_postcode' => '*',
  370. 'code' => 'US-NY-*-Rate 1',
  371. 'rate' => 8.375,
  372. 'titles' => [],
  373. 'region_name' => 'NY',
  374. ];
  375. $this->assertEquals($expectedRateData, $result);
  376. }
  377. public function testGetTaxRateNotExist()
  378. {
  379. $taxRateId = 37865;
  380. $serviceInfo = [
  381. 'rest' => [
  382. 'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
  383. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  384. ],
  385. 'soap' => [
  386. 'service' => self::SERVICE_NAME,
  387. 'serviceVersion' => self::SERVICE_VERSION,
  388. 'operation' => self::SERVICE_NAME . 'Get',
  389. ],
  390. ];
  391. try {
  392. $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
  393. $this->fail('Expected exception was not raised');
  394. } catch (\Exception $e) {
  395. $expectedMessage = 'No such entity with %fieldName = %fieldValue';
  396. $this->assertContains(
  397. $expectedMessage,
  398. $e->getMessage(),
  399. "Exception does not contain expected message."
  400. );
  401. }
  402. }
  403. /**
  404. * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
  405. */
  406. public function testDeleteTaxRate()
  407. {
  408. /** Tax rules must be deleted since tax rate cannot be deleted if there are any tax rules associated with it */
  409. $taxRules = $this->getFixtureTaxRules();
  410. foreach ($taxRules as $taxRule) {
  411. $taxRule->delete();
  412. }
  413. $fixtureRate = $this->getFixtureTaxRates()[0];
  414. $taxRateId = $fixtureRate->getId();
  415. $serviceInfo = [
  416. 'rest' => [
  417. 'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
  418. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  419. ],
  420. 'soap' => [
  421. 'service' => self::SERVICE_NAME,
  422. 'serviceVersion' => self::SERVICE_VERSION,
  423. 'operation' => self::SERVICE_NAME . 'DeleteById',
  424. ],
  425. ];
  426. $result = $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
  427. $this->assertTrue($result);
  428. /** Ensure that tax rate was actually removed from DB */
  429. /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
  430. $taxRate = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rate::class);
  431. $this->assertNull($taxRate->load($taxRateId)->getId(), 'Tax rate was not deleted from DB.');
  432. }
  433. /**
  434. * Insure that tax rate cannot be deleted if it is used for a tax rule.
  435. *
  436. * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
  437. */
  438. public function testCannotDeleteTaxRate()
  439. {
  440. $fixtureRate = $this->getFixtureTaxRates()[0];
  441. $taxRateId = $fixtureRate->getId();
  442. $serviceInfo = [
  443. 'rest' => [
  444. 'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
  445. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  446. ],
  447. 'soap' => [
  448. 'service' => self::SERVICE_NAME,
  449. 'serviceVersion' => self::SERVICE_VERSION,
  450. 'operation' => self::SERVICE_NAME . 'DeleteById',
  451. ],
  452. ];
  453. try {
  454. $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
  455. $this->fail('Expected exception was not raised');
  456. } catch (\Exception $e) {
  457. $expectedMessage = "The tax rate can't be removed because it exists in a tax rule.";
  458. $this->assertContains(
  459. $expectedMessage,
  460. $e->getMessage(),
  461. "Exception does not contain expected message."
  462. );
  463. }
  464. }
  465. public function testSearchTaxRates()
  466. {
  467. $rates = $this->setupTaxRatesForSearch();
  468. // Find rates whose code is 'codeUs12'
  469. $filter = $this->filterBuilder->setField(Rate::KEY_CODE)
  470. ->setValue('codeUs12')
  471. ->create();
  472. $this->searchCriteriaBuilder->addFilters([$filter]);
  473. $searchData = $this->searchCriteriaBuilder->create()->__toArray();
  474. $requestData = ['searchCriteria' => $searchData];
  475. $serviceInfo = [
  476. 'rest' => [
  477. 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData),
  478. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  479. ],
  480. 'soap' => [
  481. 'service' => self::SERVICE_NAME,
  482. 'serviceVersion' => self::SERVICE_VERSION,
  483. 'operation' => self::SERVICE_NAME . 'GetList',
  484. ],
  485. ];
  486. /** @var \Magento\Framework\Api\SearchResults $searchResults */
  487. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  488. $this->assertEquals(1, $searchResults['total_count']);
  489. $expectedRuleData = [
  490. [
  491. 'id' => (int)$rates['codeUs12']->getId(),
  492. 'tax_country_id' => $rates['codeUs12']->getTaxCountryId(),
  493. 'tax_region_id' => (int)$rates['codeUs12']->getTaxRegionId(),
  494. 'region_name' => 'CA',
  495. 'tax_postcode' => $rates['codeUs12']->getTaxPostcode(),
  496. 'code' => $rates['codeUs12']->getCode(),
  497. 'rate' => ((float) $rates['codeUs12']->getRate()),
  498. 'titles' => [],
  499. ],
  500. ];
  501. $this->assertEquals($expectedRuleData, $searchResults['items']);
  502. }
  503. public function testSearchTaxRatesCz()
  504. {
  505. // TODO: This test fails in SOAP, a generic bug searching in SOAP
  506. $this->_markTestAsRestOnly();
  507. $rates = $this->setupTaxRatesForSearch();
  508. $filterBR = $this->filterBuilder->setField(Rate::KEY_COUNTRY_ID)
  509. ->setValue('BR')
  510. ->create();
  511. $filterUS = $this->filterBuilder->setField(Rate::KEY_COUNTRY_ID)
  512. ->setValue('US')
  513. ->create();
  514. // Find rates which country id 'CZ'
  515. $filterCZ = $this->filterBuilder->setField(Rate::KEY_COUNTRY_ID)
  516. ->setValue('CZ')
  517. ->create();
  518. $sortOrder = $this->sortOrderBuilder
  519. ->setField(Rate::KEY_POSTCODE)
  520. ->setDirection(SortOrder::SORT_DESC)
  521. ->create();
  522. $filterRate = $this->filterBuilder->setField(Rate::KEY_PERCENTAGE_RATE)
  523. ->setValue('2.2000')
  524. ->create();
  525. $this->searchCriteriaBuilder->addFilters([$filterBR, $filterUS, $filterCZ]);
  526. // Order them by descending postcode (not the default order)
  527. $this->searchCriteriaBuilder->addFilters([$filterCZ, $filterRate])
  528. ->addSortOrder($sortOrder);
  529. $searchData = $this->searchCriteriaBuilder->create()->__toArray();
  530. $requestData = ['searchCriteria' => $searchData];
  531. $serviceInfo = [
  532. 'rest' => [
  533. 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData),
  534. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  535. ],
  536. 'soap' => [
  537. 'service' => self::SERVICE_NAME,
  538. 'serviceVersion' => self::SERVICE_VERSION,
  539. 'operation' => self::SERVICE_NAME . 'GetList',
  540. ],
  541. ];
  542. /** @var \Magento\Framework\Api\SearchResults $searchResults */
  543. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  544. $this->assertEquals(2, $searchResults['total_count']);
  545. $expectedRuleData = [
  546. [
  547. 'id' => (int)$rates['codeCz2']->getId(),
  548. 'tax_country_id' => $rates['codeCz2']->getTaxCountryId(),
  549. 'tax_postcode' => $rates['codeCz2']->getTaxPostcode(),
  550. 'code' => $rates['codeCz2']->getCode(),
  551. 'rate' => ((float) $rates['codeCz2']->getRate()),
  552. 'tax_region_id' => 0,
  553. 'titles' => [],
  554. ],
  555. [
  556. 'id' => (int)$rates['codeCz1']->getId(),
  557. 'tax_country_id' => $rates['codeCz1']->getTaxCountryId(),
  558. 'tax_postcode' => $rates['codeCz1']->getTaxPostcode(),
  559. 'code' => $rates['codeCz1']->getCode(),
  560. 'rate' => ((float) $rates['codeCz1']->getRate()),
  561. 'tax_region_id' => 0,
  562. 'titles' => [],
  563. ],
  564. ];
  565. $this->assertEquals($expectedRuleData, $searchResults['items']);
  566. }
  567. /**
  568. * Get tax rates created in Magento\Tax\_files\tax_classes.php
  569. *
  570. * @return \Magento\Tax\Model\Calculation\Rate[]
  571. */
  572. private function getFixtureTaxRates()
  573. {
  574. if ($this->fixtureTaxRates === null) {
  575. $this->fixtureTaxRates = [];
  576. if ($this->getFixtureTaxRules()) {
  577. $taxRateIds = (array)$this->getFixtureTaxRules()[0]->getRates();
  578. foreach ($taxRateIds as $taxRateId) {
  579. /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
  580. $taxRate = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rate::class);
  581. $this->fixtureTaxRates[] = $taxRate->load($taxRateId);
  582. }
  583. }
  584. }
  585. return $this->fixtureTaxRates;
  586. }
  587. /**
  588. * Get tax classes created in Magento\Tax\_files\tax_classes.php
  589. *
  590. * @return \Magento\Tax\Model\ClassModel[]
  591. */
  592. private function getFixtureTaxClasses()
  593. {
  594. if ($this->fixtureTaxClasses === null) {
  595. $this->fixtureTaxClasses = [];
  596. if ($this->getFixtureTaxRules()) {
  597. $taxClassIds = array_merge(
  598. (array)$this->getFixtureTaxRules()[0]->getCustomerTaxClasses(),
  599. (array)$this->getFixtureTaxRules()[0]->getProductTaxClasses()
  600. );
  601. foreach ($taxClassIds as $taxClassId) {
  602. /** @var \Magento\Tax\Model\ClassModel $taxClass */
  603. $taxClass = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\ClassModel::class);
  604. $this->fixtureTaxClasses[] = $taxClass->load($taxClassId);
  605. }
  606. }
  607. }
  608. return $this->fixtureTaxClasses;
  609. }
  610. /**
  611. * Get tax rule created in Magento\Tax\_files\tax_classes.php
  612. *
  613. * @return \Magento\Tax\Model\Calculation\Rule[]
  614. */
  615. private function getFixtureTaxRules()
  616. {
  617. if ($this->fixtureTaxRules === null) {
  618. $this->fixtureTaxRules = [];
  619. $taxRuleCodes = ['Test Rule Duplicate', 'Test Rule'];
  620. foreach ($taxRuleCodes as $taxRuleCode) {
  621. /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
  622. $taxRule = Bootstrap::getObjectManager()->create(\Magento\Tax\Model\Calculation\Rule::class);
  623. $taxRule->load($taxRuleCode, 'code');
  624. if ($taxRule->getId()) {
  625. $this->fixtureTaxRules[] = $taxRule;
  626. }
  627. }
  628. }
  629. return $this->fixtureTaxRules;
  630. }
  631. /**
  632. * Creates rates for search tests.
  633. *
  634. * @return \Magento\Tax\Model\Calculation\Rate[]
  635. */
  636. private function setupTaxRatesForSearch()
  637. {
  638. $objectManager = Bootstrap::getObjectManager();
  639. $taxRateUs12 = [
  640. 'tax_country_id' => 'US',
  641. 'tax_region_id' => 12,
  642. 'tax_postcode' => '*',
  643. 'code' => 'codeUs12',
  644. 'rate' => 22,
  645. 'region_name' => 'CA',
  646. ];
  647. $rates['codeUs12'] = $objectManager->create(\Magento\Tax\Model\Calculation\Rate::class)
  648. ->setData($taxRateUs12)
  649. ->save();
  650. $taxRateUs14 = [
  651. 'tax_country_id' => 'US',
  652. 'tax_region_id' => 14,
  653. 'tax_postcode' => '*',
  654. 'code' => 'codeUs14',
  655. 'rate' => 22,
  656. ];
  657. $rates['codeUs14'] = $objectManager->create(\Magento\Tax\Model\Calculation\Rate::class)
  658. ->setData($taxRateUs14)
  659. ->save();
  660. $taxRateBr13 = [
  661. 'tax_country_id' => 'BR',
  662. 'tax_region_id' => 13,
  663. 'tax_postcode' => '*',
  664. 'code' => 'codeBr13',
  665. 'rate' => 7.5,
  666. ];
  667. $rates['codeBr13'] = $objectManager->create(\Magento\Tax\Model\Calculation\Rate::class)
  668. ->setData($taxRateBr13)
  669. ->save();
  670. $taxRateCz1 = [
  671. 'tax_country_id' => 'CZ',
  672. 'tax_postcode' => '110 00',
  673. 'code' => 'codeCz1',
  674. 'rate' => 1.1,
  675. ];
  676. $rates['codeCz1'] = $objectManager->create(\Magento\Tax\Model\Calculation\Rate::class)
  677. ->setData($taxRateCz1)
  678. ->save();
  679. $taxRateCz2 = [
  680. 'tax_country_id' => 'CZ',
  681. 'tax_postcode' => '250 00',
  682. 'code' => 'codeCz2',
  683. 'rate' => 2.2,
  684. ];
  685. $rates['codeCz2'] = $objectManager->create(\Magento\Tax\Model\Calculation\Rate::class)
  686. ->setData($taxRateCz2)
  687. ->save();
  688. // Set class variable so rates will be deleted on tearDown()
  689. $this->otherRates = $rates;
  690. return $rates;
  691. }
  692. }