CustomerTaxClassSentToVertexTest.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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\Checkout\Api\Data\TotalsInformationInterface;
  9. use Magento\Checkout\Api\Data\TotalsInformationInterfaceFactory;
  10. use Magento\Checkout\Api\TotalsInformationManagementInterface;
  11. use Magento\Customer\Api\Data\CustomerInterface;
  12. use Magento\Customer\Api\Data\GroupInterfaceFactory;
  13. use Magento\Customer\Api\GroupRepositoryInterface;
  14. use Magento\Quote\Api\Data\AddressInterface;
  15. use Magento\Quote\Api\Data\AddressInterfaceFactory;
  16. use Vertex\Tax\Test\Integration\Builder\CartBuilder;
  17. use Vertex\Tax\Test\Integration\Builder\CustomerBuilder;
  18. use Vertex\Tax\Test\Integration\Builder\ProductBuilder;
  19. use Vertex\Tax\Test\Integration\Builder\TaxClassBuilder;
  20. use Vertex\Tax\Test\Integration\TestCase;
  21. /**
  22. * Ensure that when totals are collected our tax request being sent to Vertex also sends the Customer's Tax Class
  23. *
  24. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  25. */
  26. class CustomerTaxClassSentToVertexTest extends TestCase
  27. {
  28. const TAX_CLASS_NAME = 'Testable Tax Class';
  29. /** @var AddressInterfaceFactory */
  30. private $addressFactory;
  31. /** @var CartBuilder */
  32. private $cartBuilder;
  33. /** @var CustomerBuilder */
  34. private $customerBuilder;
  35. /** @var GroupInterfaceFactory */
  36. private $customerGroupFactory;
  37. /** @var GroupRepositoryInterface */
  38. private $customerGroupRepository;
  39. /** @var ProductBuilder */
  40. private $productBuilder;
  41. /** @var TaxClassBuilder */
  42. private $taxClassBuilder;
  43. /** @var TotalsInformationManagementInterface */
  44. private $totalManager;
  45. /** @var TotalsInformationInterfaceFactory */
  46. private $totalsInformationFactory;
  47. /**
  48. * Fetch objects necessary for running our test
  49. */
  50. protected function setUp()
  51. {
  52. parent::setUp();
  53. $this->totalManager = $this->getObject(TotalsInformationManagementInterface::class);
  54. $this->totalsInformationFactory = $this->getObject(TotalsInformationInterfaceFactory::class);
  55. $this->addressFactory = $this->getObject(AddressInterfaceFactory::class);
  56. $this->customerGroupFactory = $this->getObject(GroupInterfaceFactory::class);
  57. $this->customerGroupRepository = $this->getObject(GroupRepositoryInterface::class);
  58. $this->customerBuilder = $this->getObject(CustomerBuilder::class);
  59. $this->productBuilder = $this->getObject(ProductBuilder::class);
  60. $this->taxClassBuilder = $this->getObject(TaxClassBuilder::class);
  61. $this->cartBuilder = $this->getObject(CartBuilder::class);
  62. }
  63. /**
  64. * Ensure that when totals are collected our tax request being sent to Vertex also sends the Product's Tax Class
  65. *
  66. * @magentoConfigFixture default_store tax/vertex_settings/enable_vertex 1
  67. * @magentoConfigFixture default_store tax/vertex_settings/api_url https://example.org/CalculateTax70
  68. * @magentoDbIsolation enabled
  69. *
  70. * @throws \Magento\Framework\Exception\CouldNotSaveException
  71. * @throws \Magento\Framework\Exception\InputException
  72. * @throws \Magento\Framework\Exception\LocalizedException
  73. * @throws \Magento\Framework\Exception\NoSuchEntityException
  74. * @throws \Magento\Framework\Exception\StateException
  75. * @return void
  76. */
  77. public function testOutgoingRequestContainsCustomerTaxClass()
  78. {
  79. $productTaxClassId = $this->createTaxClass('Testable Product Tax Class', 'PRODUCT');
  80. $customerTaxClassId = $this->createTaxClass(static::TAX_CLASS_NAME);
  81. $product = $this->createProduct($productTaxClassId);
  82. $customer = $this->createCustomer($customerTaxClassId);
  83. $cart = $this->createCartWithProduct($product, $customer->getId());
  84. $soapClient = $this->createPartialMock(\SoapClient::class, ['CalculateTax70']);
  85. $soapClient->expects($this->atLeastOnce())
  86. ->method('CalculateTax70')
  87. ->with(
  88. $this->callback(
  89. function (\stdClass $request) {
  90. $customerData = $request->QuotationRequest->Customer;
  91. if (empty($customerData->CustomerCode) || empty($customerData->CustomerCode->classCode)) {
  92. $this->fail(
  93. 'Customer with tax class "' . static::TAX_CLASS_NAME . '" not found in Vertex Request:'
  94. . PHP_EOL
  95. . print_r($request, true)
  96. );
  97. return false;
  98. }
  99. $this->assertEquals(static::TAX_CLASS_NAME, $customerData->CustomerCode->classCode);
  100. return true;
  101. }
  102. )
  103. )
  104. ->willReturn(new \stdClass());
  105. $this->getSoapFactory()->setSoapClient($soapClient);
  106. $address = $this->createShippingAddress($customer->getId());
  107. /** @var TotalsInformationInterface $totalsInfo */
  108. $totalsInfo = $this->totalsInformationFactory->create();
  109. $totalsInfo->setAddress($address);
  110. $totalsInfo->setShippingCarrierCode('flatrate');
  111. $totalsInfo->setShippingMethodCode('flatrate');
  112. $this->totalManager->calculate($cart->getId(), $totalsInfo);
  113. }
  114. /**
  115. * Creates a guest cart containing 1 of the provided product
  116. *
  117. * @param ProductInterface $product
  118. * @param int $customerId
  119. * @return \Magento\Quote\Api\Data\CartInterface
  120. * @throws \Magento\Framework\Exception\CouldNotSaveException
  121. * @throws \Magento\Framework\Exception\NoSuchEntityException
  122. */
  123. private function createCartWithProduct(ProductInterface $product, $customerId)
  124. {
  125. return $this->cartBuilder->setItems()
  126. ->addItem($product)
  127. ->create($customerId);
  128. }
  129. /**
  130. * Create and save our test's needed Customer
  131. *
  132. * @param int|string $taxClassId
  133. * @return CustomerInterface
  134. * @throws \Magento\Framework\Exception\InputException
  135. * @throws \Magento\Framework\Exception\NoSuchEntityException
  136. * @throws \Magento\Framework\Exception\StateException
  137. * @throws \Magento\Framework\Exception\State\InvalidTransitionException
  138. * @throws \Magento\Framework\Exception\LocalizedException
  139. */
  140. private function createCustomer($taxClassId)
  141. {
  142. $groupId = $this->createCustomerGroup($taxClassId);
  143. return $this->customerBuilder->createExampleCustomer(
  144. function (CustomerInterface $customer) use ($groupId) {
  145. $customer->setGroupId($groupId);
  146. return $customer;
  147. }
  148. );
  149. }
  150. /**
  151. * Create a new customer group for the given tax class ID.
  152. *
  153. * @param $taxClassId
  154. * @return int
  155. * @throws \Magento\Framework\Exception\InputException
  156. * @throws \Magento\Framework\Exception\NoSuchEntityException
  157. * @throws \Magento\Framework\Exception\State\InvalidTransitionException
  158. * @throws \Magento\Framework\Exception\LocalizedException
  159. */
  160. private function createCustomerGroup($taxClassId)
  161. {
  162. $group = $this->customerGroupFactory->create();
  163. $group->setCode('Test Customer Group');
  164. $group->setTaxClassId($taxClassId);
  165. return $this->customerGroupRepository->save($group)->getId();
  166. }
  167. /**
  168. * Create and save our test's needed Product
  169. *
  170. * @param int|string $taxClassId
  171. * @return ProductInterface
  172. * @throws \Magento\Framework\Exception\CouldNotSaveException
  173. * @throws \Magento\Framework\Exception\InputException
  174. * @throws \Magento\Framework\Exception\NoSuchEntityException
  175. * @throws \Magento\Framework\Exception\StateException
  176. */
  177. private function createProduct($taxClassId)
  178. {
  179. return $this->productBuilder->createExampleProduct(
  180. function (ProductInterface $product) use ($taxClassId) {
  181. $product->setCustomAttribute('tax_class_id', $taxClassId);
  182. return $product;
  183. }
  184. );
  185. }
  186. /**
  187. * Create a shipping address for our order
  188. *
  189. * @param int|null $customerId
  190. * @return AddressInterface
  191. */
  192. private function createShippingAddress($customerId = null)
  193. {
  194. /** @var AddressInterface $address */
  195. $address = $this->addressFactory->create();
  196. $address->setCustomerId($customerId);
  197. $address->setCity('West Chester');
  198. $address->setCountryId('US');
  199. $address->setFirstname('John');
  200. $address->setLastname('Doe');
  201. $address->setPostcode('19382');
  202. $address->setRegion('Pennsylvania');
  203. $address->setRegionCode('PA');
  204. $address->setRegionId(51);
  205. $address->setStreet(['233 West Gay St']);
  206. $address->setTelephone('1234567890');
  207. return $address;
  208. }
  209. /**
  210. * Create and save our test's needed tax class
  211. *
  212. * @param string $taxClassName
  213. * @param string $type
  214. * @return string Tax Class ID
  215. * @throws \Magento\Framework\Exception\InputException
  216. * @throws \Magento\Framework\Exception\LocalizedException
  217. */
  218. private function createTaxClass($taxClassName, $type = 'CUSTOMER')
  219. {
  220. return $this->taxClassBuilder->createTaxClass($taxClassName, $type);
  221. }
  222. }