ProductTaxClassSentToVertexTest.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <?php
  2. /**
  3. * @copyright Vertex. All rights reserved. https://www.vertexinc.com/
  4. * @author Mediotype https://www.mediotype.com/
  5. */
  6. namespace Vertex\Tax\Test\Integration\ApiValidation;
  7. use Magento\Catalog\Api\Data\ProductInterface;
  8. use Magento\Catalog\Model\Product\Attribute\Source\Status;
  9. use Magento\Catalog\Model\Product\Visibility;
  10. use Magento\CatalogInventory\Model\StockRegistryStorage;
  11. use Magento\Checkout\Api\Data\TotalsInformationInterface;
  12. use Magento\Checkout\Api\Data\TotalsInformationInterfaceFactory;
  13. use Magento\Checkout\Api\TotalsInformationManagementInterface;
  14. use Magento\Quote\Api\Data\AddressInterface;
  15. use Magento\Quote\Api\Data\AddressInterfaceFactory;
  16. use Vertex\Tax\Test\Integration\Builder\GuestCartBuilder;
  17. use Vertex\Tax\Test\Integration\Builder\ProductBuilder;
  18. use Vertex\Tax\Test\Integration\Builder\TaxClassBuilder;
  19. use Vertex\Tax\Test\Integration\TestCase;
  20. /**
  21. * Ensure that when totals are collected our tax request being sent to Vertex also sends the Product's Tax Class
  22. *
  23. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  24. */
  25. class ProductTaxClassSentToVertexTest extends TestCase
  26. {
  27. const PRODUCT_SKU = ProductBuilder::EXAMPLE_PRODUCT_SKU;
  28. const TAX_CLASS_NAME = 'Testable Tax Class';
  29. /** @var AddressInterfaceFactory */
  30. private $addressFactory;
  31. /** @var GuestCartBuilder */
  32. private $guestCartBuilder;
  33. /** @var ProductBuilder */
  34. private $productBuilder;
  35. /** @var StockRegistryStorage */
  36. private $stockRegistryStorage;
  37. /** @var TaxClassBuilder */
  38. private $taxClassBuilder;
  39. /** @var TotalsInformationManagementInterface */
  40. private $totalManager;
  41. /** @var TotalsInformationInterfaceFactory */
  42. private $totalsInformationFactory;
  43. /**
  44. * Fetch objects necessary for running our test
  45. */
  46. protected function setUp()
  47. {
  48. parent::setUp();
  49. $this->totalManager = $this->getObject(TotalsInformationManagementInterface::class);
  50. $this->totalsInformationFactory = $this->getObject(TotalsInformationInterfaceFactory::class);
  51. $this->addressFactory = $this->getObject(AddressInterfaceFactory::class);
  52. $this->stockRegistryStorage = $this->getObject(StockRegistryStorage::class);
  53. $this->productBuilder = $this->getObject(ProductBuilder::class);
  54. $this->taxClassBuilder = $this->getObject(TaxClassBuilder::class);
  55. $this->guestCartBuilder = $this->getObject(GuestCartBuilder::class);
  56. }
  57. /**
  58. * Ensure that when totals are collected our tax request being sent to Vertex also sends the Product's Tax Class
  59. *
  60. * @magentoConfigFixture default_store tax/vertex_settings/enable_vertex 1
  61. * @magentoConfigFixture default_store tax/vertex_settings/api_url https://example.org/CalculateTax70
  62. * @magentoDbIsolation enabled
  63. *
  64. * @throws \Magento\Framework\Exception\CouldNotSaveException
  65. * @throws \Magento\Framework\Exception\InputException
  66. * @throws \Magento\Framework\Exception\LocalizedException
  67. * @throws \Magento\Framework\Exception\NoSuchEntityException
  68. * @throws \Magento\Framework\Exception\StateException
  69. * @return void
  70. */
  71. public function testOutgoingRequestContainsProductTaxClass()
  72. {
  73. $taxClassId = $this->createTaxClass(static::TAX_CLASS_NAME);
  74. $product = $this->createProduct($taxClassId);
  75. $cart = $this->createCartWithProduct($product);
  76. $soapClient = $this->createPartialMock(\SoapClient::class, ['CalculateTax70']);
  77. $soapClient->expects($this->atLeastOnce())
  78. ->method('CalculateTax70')
  79. ->with(
  80. $this->callback(
  81. function (\stdClass $request) {
  82. $lineItems = $request->QuotationRequest->LineItem;
  83. foreach ($lineItems as $lineItem) {
  84. $product = $lineItem->Product;
  85. if ($product->_ === static::PRODUCT_SKU) {
  86. $this->assertEquals(static::TAX_CLASS_NAME, $product->productClass);
  87. return true;
  88. }
  89. }
  90. $this->fail(
  91. 'Product with SKU "' . static::PRODUCT_SKU . '" not found in Vertex Request:' . PHP_EOL
  92. . print_r($request, true)
  93. );
  94. return false;
  95. }
  96. )
  97. )
  98. ->willReturn(new \stdClass());
  99. $this->getSoapFactory()->setSoapClient($soapClient);
  100. $address = $this->createShippingAddress();
  101. /** @var TotalsInformationInterface $totalsInfo */
  102. $totalsInfo = $this->totalsInformationFactory->create();
  103. $totalsInfo->setAddress($address);
  104. $totalsInfo->setShippingCarrierCode('flatrate');
  105. $totalsInfo->setShippingMethodCode('flatrate');
  106. $this->totalManager->calculate($cart->getId(), $totalsInfo);
  107. }
  108. /**
  109. * Creates a guest cart containing 1 of the provided product
  110. *
  111. * @param ProductInterface $product
  112. * @return \Magento\Quote\Api\Data\CartInterface
  113. * @throws \Magento\Framework\Exception\CouldNotSaveException
  114. * @throws \Magento\Framework\Exception\NoSuchEntityException
  115. */
  116. private function createCartWithProduct(ProductInterface $product)
  117. {
  118. return $this->guestCartBuilder->setItems()
  119. ->addItem($product)
  120. ->create();
  121. }
  122. /**
  123. * Create and save our test's needed Product
  124. *
  125. * @param int|string $taxClassId
  126. * @return ProductInterface
  127. * @throws \Magento\Framework\Exception\CouldNotSaveException
  128. * @throws \Magento\Framework\Exception\InputException
  129. * @throws \Magento\Framework\Exception\NoSuchEntityException
  130. * @throws \Magento\Framework\Exception\StateException
  131. */
  132. private function createProduct($taxClassId)
  133. {
  134. return $this->productBuilder->createExampleProduct(
  135. function (ProductInterface $product) use ($taxClassId) {
  136. $product->setCustomAttribute('tax_class_id', $taxClassId);
  137. return $product;
  138. }
  139. );
  140. }
  141. /**
  142. * Create a shipping address for our order
  143. *
  144. * @return AddressInterface
  145. */
  146. private function createShippingAddress()
  147. {
  148. /** @var AddressInterface $address */
  149. $address = $this->addressFactory->create();
  150. $address->setCity('West Chester');
  151. $address->setCountryId('US');
  152. $address->setFirstname('John');
  153. $address->setLastname('Doe');
  154. $address->setPostcode('19382');
  155. $address->setRegion('Pennsylvania');
  156. $address->setRegionCode('PA');
  157. $address->setRegionId(51);
  158. $address->setStreet(['233 West Gay St']);
  159. $address->setTelephone('1234567890');
  160. return $address;
  161. }
  162. /**
  163. * Create and save our test's needed tax class
  164. *
  165. * @param string $taxClassName
  166. * @return string Tax Class ID
  167. * @throws \Magento\Framework\Exception\InputException
  168. * @throws \Magento\Framework\Exception\LocalizedException
  169. */
  170. private function createTaxClass($taxClassName)
  171. {
  172. return $this->taxClassBuilder->createTaxClass($taxClassName, 'PRODUCT');
  173. }
  174. }