CustomerBuilder.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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\Model\Api\Data;
  7. use Magento\Customer\Api\CustomerRepositoryInterface;
  8. use Magento\Customer\Api\Data\AddressInterface;
  9. use Magento\Customer\Api\Data\RegionInterface;
  10. use Magento\Customer\Api\GroupManagementInterface as CustomerGroupManagement;
  11. use Magento\Customer\Api\GroupRepositoryInterface;
  12. use Magento\Sales\Api\Data\OrderAddressInterface;
  13. use Magento\Sales\Model\Order;
  14. use Vertex\Data\CustomerInterface;
  15. use Vertex\Data\CustomerInterfaceFactory;
  16. use Vertex\Tax\Model\Config;
  17. use Vertex\Tax\Model\ExceptionLogger;
  18. use Vertex\Tax\Model\Repository\TaxClassNameRepository;
  19. /**
  20. * Builds a Customer object for use with the Vertex SDK
  21. */
  22. class CustomerBuilder
  23. {
  24. /** @var AddressBuilder */
  25. private $addressBuilder;
  26. /** @var Config */
  27. private $config;
  28. /** @var CustomerInterfaceFactory */
  29. private $customerFactory;
  30. /** @var CustomerGroupManagement */
  31. private $customerGroupManagement;
  32. /** @var CustomerRepositoryInterface */
  33. private $customerRepository;
  34. /** @var GroupRepositoryInterface */
  35. private $groupRepository;
  36. /** @var ExceptionLogger */
  37. private $logger;
  38. /** @var TaxClassNameRepository */
  39. private $taxClassNameRepository;
  40. /** @var TaxRegistrationBuilder */
  41. private $taxRegistrationBuilder;
  42. /**
  43. * @param Config $config
  44. * @param AddressBuilder $addressBuilder
  45. * @param CustomerRepositoryInterface $customerRepository
  46. * @param CustomerGroupManagement $customerGroupManagement
  47. * @param TaxClassNameRepository $taxClassNameRepository
  48. * @param CustomerInterfaceFactory $customerFactory
  49. * @param ExceptionLogger $logger
  50. * @param GroupRepositoryInterface $groupRepository
  51. * @param TaxRegistrationBuilder $builder
  52. */
  53. public function __construct(
  54. Config $config,
  55. AddressBuilder $addressBuilder,
  56. CustomerRepositoryInterface $customerRepository,
  57. CustomerGroupManagement $customerGroupManagement,
  58. TaxClassNameRepository $taxClassNameRepository,
  59. CustomerInterfaceFactory $customerFactory,
  60. ExceptionLogger $logger,
  61. GroupRepositoryInterface $groupRepository,
  62. TaxRegistrationBuilder $builder
  63. ) {
  64. $this->addressBuilder = $addressBuilder;
  65. $this->config = $config;
  66. $this->customerRepository = $customerRepository;
  67. $this->customerGroupManagement = $customerGroupManagement;
  68. $this->taxClassNameRepository = $taxClassNameRepository;
  69. $this->customerFactory = $customerFactory;
  70. $this->logger = $logger;
  71. $this->groupRepository = $groupRepository;
  72. $this->taxRegistrationBuilder = $builder;
  73. }
  74. /**
  75. * Create a properly formatted array of Customer Data for a Vertex API
  76. *
  77. * @param AddressInterface $taxAddress
  78. * @param int|null $customerId
  79. * @param int|null $taxClassId
  80. * @param string|null $storeCode
  81. * @return CustomerInterface
  82. */
  83. public function buildFromCustomerAddress(
  84. AddressInterface $taxAddress = null,
  85. $customerId = null,
  86. $taxClassId = null,
  87. $storeCode = null
  88. ) {
  89. return $this->buildFromAddress($taxAddress, $customerId, $taxClassId, $storeCode);
  90. }
  91. /**
  92. * Create a {@see CustomerInterface} from an {@see Order}
  93. *
  94. * @param Order $order
  95. * @return CustomerInterface
  96. */
  97. public function buildFromOrder(Order $order)
  98. {
  99. $orderAddress = $order->getIsVirtual() ? $order->getBillingAddress() : $order->getShippingAddress();
  100. $customer = $this->buildFromOrderAddress($orderAddress);
  101. $customer->setTaxClass($this->getCustomerClassById($order->getCustomerId()));
  102. $customer->setCode($this->getCustomerCodeById($order->getCustomerId()));
  103. return $customer;
  104. }
  105. /**
  106. * Create a properly formatted array of Customer Data for a Vertex API
  107. *
  108. * @param OrderAddressInterface $taxAddress
  109. * @param int|null $customerId
  110. * @param int|null $customerGroupId
  111. * @param string|null $storeCode
  112. * @return CustomerInterface
  113. */
  114. public function buildFromOrderAddress(
  115. OrderAddressInterface $taxAddress = null,
  116. $customerId = null,
  117. $customerGroupId = null,
  118. $storeCode = null
  119. ) {
  120. try {
  121. $group = $customerGroupId ? $this->groupRepository->getById($customerGroupId) : null;
  122. } catch (\Exception $e) {
  123. $group = null;
  124. }
  125. $taxClassId = $group ? $group->getTaxClassId() : null;
  126. return $this->buildFromAddress($taxAddress, $customerId, $taxClassId, $storeCode);
  127. }
  128. /**
  129. * Create a properly formatted array of Customer Data for the Vertex API
  130. *
  131. * This method exists to build addresses based off any number of Magento's
  132. * Address interfaces.
  133. *
  134. * @param AddressInterface|OrderAddressInterface|null $taxAddress
  135. * @param int $customerId
  136. * @param int $taxClassId
  137. * @param string $storeCode
  138. * @return CustomerInterface
  139. */
  140. private function buildFromAddress($taxAddress = null, $customerId = null, $taxClassId = null, $storeCode = null)
  141. {
  142. /** @var CustomerInterface $customer */
  143. $customer = $this->customerFactory->create();
  144. if ($taxAddress !== null) {
  145. if (!($taxAddress instanceof AddressInterface || $taxAddress instanceof OrderAddressInterface)) {
  146. throw new \InvalidArgumentException(
  147. '$taxAddress must be one of '
  148. . AddressInterface::class . ' or ' . OrderAddressInterface::class
  149. );
  150. }
  151. $addressBuilder = $this->addressBuilder
  152. ->setStreet($taxAddress->getStreet())
  153. ->setCity($taxAddress->getCity())
  154. ->setPostalCode($taxAddress->getPostcode())
  155. ->setCountryCode($taxAddress->getCountryId());
  156. $region = $taxAddress->getRegion();
  157. if ($region instanceof RegionInterface && $region->getRegionId()) {
  158. $addressBuilder->setRegionId($region->getRegionId());
  159. } elseif ($region instanceof RegionInterface && $region->getRegion()) {
  160. $addressBuilder->setRegion($region->getRegion());
  161. } elseif ($taxAddress->getRegionId()) {
  162. $addressBuilder->setRegionId($taxAddress->getRegionId());
  163. } else if (is_string($region)) {
  164. $addressBuilder->setRegion($region);
  165. }
  166. $customer->setDestination($addressBuilder->build());
  167. if ($taxAddress->getVatId()) {
  168. $this->updateCustomerWithRegistration($customer, $taxAddress);
  169. }
  170. }
  171. $customer->setCode($this->getCustomerCodeById($customerId, $storeCode));
  172. $class = $taxClassId
  173. ? $this->taxClassNameRepository->getById($taxClassId)
  174. : $this->getCustomerClassById($customerId);
  175. $customer->setTaxClass($class);
  176. return $customer;
  177. }
  178. /**
  179. * Retrieve a Customer's Tax Class given their ID
  180. *
  181. * @param int $customerId
  182. * @return string
  183. */
  184. private function getCustomerClassById($customerId = 0)
  185. {
  186. $customerGroupId = 0;
  187. $taxClassId = 0;
  188. try {
  189. if ($customerId) {
  190. $customerData = $this->customerRepository->getById($customerId);
  191. $customerGroupId = $customerData->getGroupId();
  192. } else {
  193. $taxClassId = $this->customerGroupManagement->getNotLoggedInGroup()->getTaxClassId();
  194. }
  195. } catch (\Exception $e) {
  196. $this->logger->warning($e);
  197. }
  198. return $customerGroupId
  199. ? $this->taxClassNameRepository->getByCustomerGroupId($customerGroupId)
  200. : $this->taxClassNameRepository->getById($taxClassId);
  201. }
  202. /**
  203. * Retrieve a Customer's Custom Code given their ID
  204. *
  205. * @param int $customerId
  206. * @param string|null $store
  207. * @return string|null
  208. */
  209. private function getCustomerCodeById($customerId = 0, $store = null)
  210. {
  211. if ($customerId === 0 || $customerId === null) {
  212. return $this->config->getDefaultCustomerCode($store);
  213. }
  214. $customerCode = null;
  215. try {
  216. $customer = $this->customerRepository->getById($customerId);
  217. $extensions = $customer->getExtensionAttributes();
  218. if ($extensions !== null && $extensions->getVertexCustomerCode()) {
  219. $customerCode = $extensions->getVertexCustomerCode();
  220. }
  221. } catch (\Exception $e) {
  222. $this->logger->warning($e);
  223. }
  224. return $customerCode ?: $this->config->getDefaultCustomerCode($store);
  225. }
  226. /**
  227. * Add a VAT Tax Registration to a Customer record
  228. *
  229. * @param CustomerInterface $customer
  230. * @param AddressInterface|OrderAddressInterface $taxAddress
  231. * @return CustomerInterface
  232. */
  233. private function updateCustomerWithRegistration($customer, $taxAddress)
  234. {
  235. if ($taxAddress instanceof AddressInterface) {
  236. $registration = $this->taxRegistrationBuilder->buildFromCustomerAddress($taxAddress);
  237. } elseif ($taxAddress instanceof OrderAddressInterface) {
  238. $registration = $this->taxRegistrationBuilder->buildFromOrderAddress($taxAddress);
  239. } else {
  240. throw new \InvalidArgumentException('taxAddress must be one of AddressInterface, OrderAddressInterface');
  241. }
  242. $customer->setTaxRegistrations([$registration]);
  243. return $customer;
  244. }
  245. }