Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
SetupUtil.php
Go to the documentation of this file.
1 <?php
8 
12 
16 class SetupUtil
17 {
23  protected $defaultConfig = [
25  Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX => 0, //Excluding tax
27  Config::CONFIG_XML_PATH_BASED_ON => 'shipping', // or 'billing'
32  //@TODO: add config for cross border trade
33  ];
34 
35  const TAX_RATE_TX = 'tax_rate_tx';
36  const TAX_RATE_AUSTIN = 'tax_rate_austin';
37  const TAX_RATE_SHIPPING = 'tax_rate_shipping';
38  const TAX_STORE_RATE = 'tax_store_rate';
39  const REGION_TX = '57';
40  const REGION_CA = '12';
41  const COUNTRY_US = 'US';
42  const AUSTIN_POST_CODE = '79729';
43 
49  protected $taxRates = [
50  self::TAX_RATE_TX => [
51  'data' => [
52  'tax_country_id' => self::COUNTRY_US,
53  'tax_region_id' => self::REGION_TX,
54  'tax_postcode' => '*',
55  'code' => self::TAX_RATE_TX,
56  'rate' => '20',
57  ],
58  'id' => null,
59  ],
60  self::TAX_RATE_AUSTIN => [
61  'data' => [
62  'tax_country_id' => self::COUNTRY_US,
63  'tax_region_id' => self::REGION_TX,
64  'tax_postcode' => self::AUSTIN_POST_CODE,
65  'code' => self::TAX_RATE_AUSTIN,
66  'rate' => '5',
67  ],
68  'id' => null,
69  ],
70  self::TAX_RATE_SHIPPING => [
71  'data' => [
72  'tax_country_id' => self::COUNTRY_US,
73  'tax_region_id' => '*',
74  'tax_postcode' => '*',
75  'code' => self::TAX_RATE_SHIPPING,
76  'rate' => '7.5',
77  ],
78  'id' => null,
79  ],
80  self::TAX_STORE_RATE => [
81  'data' => [
82  'tax_country_id' => self::COUNTRY_US,
83  'tax_region_id' => self::REGION_CA,
84  'tax_postcode' => '*',
85  'code' => self::TAX_STORE_RATE,
86  'rate' => '8.25',
87  ],
88  'id' => null,
89  ],
90  ];
91 
92  const PRODUCT_TAX_CLASS_1 = 'product_tax_class_1';
93  const PRODUCT_TAX_CLASS_2 = 'product_tax_class_2';
94  const SHIPPING_TAX_CLASS = 'shipping_tax_class';
95 
101  protected $productTaxClasses = [
102  self::PRODUCT_TAX_CLASS_1 => null,
103  self::PRODUCT_TAX_CLASS_2 => null,
104  self::SHIPPING_TAX_CLASS => null,
105  ];
106 
107  const CUSTOMER_TAX_CLASS_1 = 'customer_tax_class_1';
108  const CUSTOMER_PASSWORD = 'password';
109 
115  protected $customerTaxClasses = [
116  self::CUSTOMER_TAX_CLASS_1 => null,
117  ];
118 
124  protected $taxRules = [];
125 
126  const CONFIG_OVERRIDES = 'config_overrides';
127  const TAX_RATE_OVERRIDES = 'tax_rate_overrides';
128  const TAX_RULE_OVERRIDES = 'tax_rule_overrides';
129 
136  'name' => 'Shopping Cart Rule',
137  'is_active' => 1,
140  'simple_action' => 'by_percent',
141  'discount_amount' => 40,
142  'discount_step' => 0,
143  'stop_rules_processing' => 1,
144  'apply_to_shipping' => 0,
145  'website_ids' => [1],
146  ];
147 
154 
159 
164 
168  public function __construct($objectManager)
169  {
170  $this->objectManager = $objectManager;
171  $this->customerRepository = $this->objectManager->create(
172  \Magento\Customer\Api\CustomerRepositoryInterface::class
173  );
174  $this->accountManagement = $this->objectManager->create(
175  \Magento\Customer\Api\AccountManagementInterface::class
176  );
177  }
178 
184  protected function createCustomerTaxClass()
185  {
186  foreach (array_keys($this->customerTaxClasses) as $className) {
187  $this->customerTaxClasses[$className] = $this->objectManager->create(\Magento\Tax\Model\ClassModel::class)
188  ->setClassName($className)
189  ->setClassType(\Magento\Tax\Model\ClassModel::TAX_CLASS_TYPE_CUSTOMER)
190  ->save()
191  ->getId();
192  }
193 
194  return $this;
195  }
196 
202  protected function createProductTaxClass()
203  {
204  foreach (array_keys($this->productTaxClasses) as $className) {
205  $this->productTaxClasses[$className] = $this->objectManager->create(\Magento\Tax\Model\ClassModel::class)
206  ->setClassName($className)
207  ->setClassType(\Magento\Tax\Model\ClassModel::TAX_CLASS_TYPE_PRODUCT)
208  ->save()
209  ->getId();
210  }
211 
212  return $this;
213  }
214 
221  protected function setConfig($configData)
222  {
224  $config = $this->objectManager->get(\Magento\Config\Model\ResourceModel\Config::class);
225  foreach ($configData as $path => $value) {
227  $value = $this->productTaxClasses[$value];
228  }
229  $config->saveConfig(
230  $path,
231  $value,
233  0
234  );
235  }
236 
238  $config = $this->objectManager->get(\Magento\Framework\App\Config\ReinitableConfigInterface::class);
239  $config->reinit();
240 
241  return $this;
242  }
243 
250  protected function createTaxRates($overrides)
251  {
252  $taxRateOverrides = empty($overrides[self::TAX_RATE_OVERRIDES]) ? [] : $overrides[self::TAX_RATE_OVERRIDES];
253  foreach (array_keys($this->taxRates) as $taxRateCode) {
254  if (isset($taxRateOverrides[$taxRateCode])) {
255  $this->taxRates[$taxRateCode]['data']['rate'] = $taxRateOverrides[$taxRateCode];
256  }
257  $this->taxRates[$taxRateCode]['id'] = $this->objectManager->create(
258  \Magento\Tax\Model\Calculation\Rate::class
259  )
260  ->setData($this->taxRates[$taxRateCode]['data'])
261  ->save()
262  ->getId();
263  }
264  return $this;
265  }
266 
274  protected function processTaxRuleOverrides($taxRuleOverrideData, $taxRateIds)
275  {
276  if (!empty($taxRuleOverrideData['customer_tax_class_ids'])) {
277  $customerTaxClassIds = [];
278  foreach ($taxRuleOverrideData['customer_tax_class_ids'] as $customerClassCode) {
279  $customerTaxClassIds[] = $this->customerTaxClasses[$customerClassCode];
280  }
281  $taxRuleOverrideData['customer_tax_class_ids'] = $customerTaxClassIds;
282  }
283  if (!empty($taxRuleOverrideData['product_tax_class_ids'])) {
284  $productTaxClassIds = [];
285  foreach ($taxRuleOverrideData['product_tax_class_ids'] as $productClassCode) {
286  $productTaxClassIds[] = $this->productTaxClasses[$productClassCode];
287  }
288  $taxRuleOverrideData['product_tax_class_ids'] = $productTaxClassIds;
289  }
290  if (!empty($taxRuleOverrideData['tax_rate_ids'])) {
291  $taxRateIdsForRule = [];
292  foreach ($taxRuleOverrideData['tax_rate_ids'] as $taxRateCode) {
293  $taxRateIdsForRule[] = $taxRateIds[$taxRateCode];
294  }
295  $taxRuleOverrideData['tax_rate_ids'] = $taxRateIdsForRule;
296  }
297 
298  return $taxRuleOverrideData;
299  }
300 
306  protected function getProductTaxClassIds()
307  {
308  $productTaxClassIds = [];
309  foreach ($this->productTaxClasses as $productTaxClassName => $productTaxClassId) {
310  if ($productTaxClassName != self::SHIPPING_TAX_CLASS) {
311  $productTaxClassIds[] = $productTaxClassId;
312  }
313  }
314 
315  return $productTaxClassIds;
316  }
317 
323  protected function getDefaultTaxRateIds()
324  {
325  $taxRateIds = [
326  $this->taxRates[self::TAX_RATE_TX]['id'],
327  $this->taxRates[self::TAX_STORE_RATE]['id'],
328  ];
329 
330  return $taxRateIds;
331  }
332 
338  public function getDefaultCustomerTaxClassId()
339  {
341  $groupManagement = $this->objectManager->get(\Magento\Customer\Api\GroupManagementInterface::class);
342  $defaultGroup = $groupManagement->getDefaultGroup();
343  return $defaultGroup->getTaxClassId();
344  }
345 
352  protected function createTaxRules($overrides)
353  {
354  $taxRateIds = [];
355  foreach ($this->taxRates as $taxRateCode => $taxRate) {
356  $taxRateIds[$taxRateCode] = $taxRate['id'];
357  }
358 
359  //The default customer tax class id is used to calculate store tax rate
360  $customerClassIds = [
361  $this->customerTaxClasses[self::CUSTOMER_TAX_CLASS_1],
362  $this->getDefaultCustomerTaxClassId()
363  ];
364 
365  //By default create tax rule that covers all product tax classes except SHIPPING_TAX_CLASS
366  //The tax rule will cover all tax rates except TAX_RATE_SHIPPING
367  $taxRuleDefaultData = [
368  'code' => 'Test Rule',
369  'priority' => '0',
370  'position' => '0',
371  'customer_tax_class_ids' => $customerClassIds,
372  'product_tax_class_ids' => $this->getProductTaxClassIds(),
373  'tax_rate_ids' => $this->getDefaultTaxRateIds(),
374  ];
375 
376  //Create tax rules
377  if (empty($overrides[self::TAX_RULE_OVERRIDES])) {
378  //Create separate shipping tax rule
379  $shippingTaxRuleData = [
380  'code' => 'Shipping Tax Rule',
381  'priority' => '0',
382  'position' => '0',
383  'customer_tax_class_ids' => $customerClassIds,
384  'product_tax_class_ids' => [$this->productTaxClasses[self::SHIPPING_TAX_CLASS]],
385  'tax_rate_ids' => [$this->taxRates[self::TAX_RATE_SHIPPING]['id']],
386  ];
387  $this->taxRules[$shippingTaxRuleData['code']] = $this->objectManager
388  ->create(\Magento\Tax\Model\Calculation\Rule::class)
389  ->setData($shippingTaxRuleData)
390  ->save()
391  ->getId();
392 
393  //Create a default tax rule
394  $this->taxRules[$taxRuleDefaultData['code']] = $this->objectManager
395  ->create(\Magento\Tax\Model\Calculation\Rule::class)
396  ->setData($taxRuleDefaultData)
397  ->save()
398  ->getId();
399  } else {
400  foreach ($overrides[self::TAX_RULE_OVERRIDES] as $taxRuleOverrideData) {
401  //convert code to id for productTaxClass, customerTaxClass and taxRate
402  $taxRuleOverrideData = $this->processTaxRuleOverrides($taxRuleOverrideData, $taxRateIds);
403  $mergedTaxRuleData = array_merge($taxRuleDefaultData, $taxRuleOverrideData);
404  $this->taxRules[$mergedTaxRuleData['code']] = $this->objectManager
405  ->create(\Magento\Tax\Model\Calculation\Rule::class)
406  ->setData($mergedTaxRuleData)
407  ->save()
408  ->getId();
409  }
410  }
411 
412  return $this;
413  }
414 
441  public function setupTax($overrides)
442  {
443  //Create product tax classes
444  $this->createProductTaxClass();
445 
446  //Create customer tax classes
447  $this->createCustomerTaxClass();
448 
449  //Create tax rates
450  $this->createTaxRates($overrides);
451 
452  //Create tax rules
453  $this->createTaxRules($overrides);
454 
455  //Tax calculation configuration
456  if (!empty($overrides[self::CONFIG_OVERRIDES])) {
457  $this->setConfig($overrides[self::CONFIG_OVERRIDES]);
458  }
459  }
460 
469  public function createSimpleProduct($sku, $price, $taxClassId)
470  {
472  $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class);
473  $product->isObjectNew(true);
474  $product->setTypeId('simple')
475  ->setAttributeSetId(4)
476  ->setName('Simple Product' . $sku)
477  ->setSku($sku)
478  ->setPrice($price)
479  ->setTaxClassId($taxClassId)
480  ->setStockData(
481  [
482  'use_config_manage_stock' => 1,
483  'qty' => 100,
484  'is_qty_decimal' => 0,
485  'is_in_stock' => 1
486  ]
487  )->setMetaTitle('meta title')
488  ->setMetaKeyword('meta keyword')
489  ->setMetaDescription('meta description')
490  ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
491  ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
492  ->save();
493 
494  $product = $product->load($product->getId());
495  return $product;
496  }
497 
504  protected function createCustomerGroup($customerTaxClassId)
505  {
507  $groupRepository = $this->objectManager->create(\Magento\Customer\Api\GroupRepositoryInterface::class);
508  $customerGroupFactory = $this->objectManager->create(\Magento\Customer\Api\Data\GroupInterfaceFactory::class);
509  $customerGroup = $customerGroupFactory->create()
510  ->setCode('custom_group')
511  ->setTaxClassId($customerTaxClassId);
512  $customerGroupId = $groupRepository->save($customerGroup)->getId();
513  return $customerGroupId;
514  }
515 
521  protected function createCustomer()
522  {
523  $customerGroupId = $this->createCustomerGroup($this->customerTaxClasses[self::CUSTOMER_TAX_CLASS_1]);
525  $customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class);
526  $customer->isObjectNew(true);
527  $customer->setWebsiteId(1)
528  ->setEntityTypeId(1)
529  ->setAttributeSetId(1)
530  ->setEmail('[email protected]')
531  ->setPassword('password')
532  ->setGroupId($customerGroupId)
533  ->setStoreId(1)
534  ->setIsActive(1)
535  ->setFirstname('Firstname')
536  ->setLastname('Lastname')
537  ->save();
538 
539  return $this->customerRepository->getById($customer->getId());
540  }
541 
549  protected function createCustomerAddress($addressOverride, $customerId)
550  {
551  $defaultAddressData = [
552  'attribute_set_id' => 2,
553  'telephone' => 3468676,
554  'postcode' => self::AUSTIN_POST_CODE,
555  'country_id' => self::COUNTRY_US,
556  'city' => 'CityM',
557  'company' => 'CompanyName',
558  'street' => ['Green str, 67'],
559  'lastname' => 'Smith',
560  'firstname' => 'John',
561  'parent_id' => 1,
562  'region_id' => self::REGION_TX,
563  ];
564  $addressData = array_merge($defaultAddressData, $addressOverride);
565 
567  $customerAddress = $this->objectManager->create(\Magento\Customer\Model\Address::class);
569  ->setCustomerId($customerId)
570  ->save();
571 
572  return $customerAddress;
573  }
574 
581  protected function createCartRule($ruleDataOverride)
582  {
584  $salesRule = $this->objectManager->create(\Magento\SalesRule\Model\Rule::class);
585  $ruleData = array_merge($this->defaultShoppingCartPriceRule, $ruleDataOverride);
586  $salesRule->setData($ruleData);
587  $salesRule->save();
588 
589  return $this;
590  }
591 
599  protected function createQuote($quoteData, $customer)
600  {
602  $addressService = $this->objectManager->create(\Magento\Customer\Api\AddressRepositoryInterface::class);
603 
605  $shippingAddressOverride = empty($quoteData['shipping_address']) ? [] : $quoteData['shipping_address'];
607  $shippingAddress = $this->createCustomerAddress($shippingAddressOverride, $customer->getId());
608 
610  $quoteShippingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class);
611  $quoteShippingAddress->importCustomerAddressData($addressService->getById($shippingAddress->getId()));
612 
614  $billingAddressOverride = empty($quoteData['billing_address']) ? [] : $quoteData['billing_address'];
616  $billingAddress = $this->createCustomerAddress($billingAddressOverride, $customer->getId());
617 
619  $quoteBillingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class);
620  $quoteBillingAddress->importCustomerAddressData($addressService->getById($billingAddress->getId()));
621 
623  $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class);
624  $quote->setStoreId(1)
625  ->setIsActive(true)
626  ->setIsMultiShipping(false)
627  ->assignCustomerWithAddressChange($customer, $quoteBillingAddress, $quoteShippingAddress)
628  ->setCheckoutMethod('register')
629  ->setPasswordHash($this->accountManagement->getPasswordHash(static::CUSTOMER_PASSWORD));
630 
631  return $quote;
632  }
633 
641  protected function addProductToQuote($quote, $itemsData)
642  {
643  foreach ($itemsData as $itemData) {
644  $sku = $itemData['sku'];
645  $price = $itemData['price'];
646  $qty = isset($itemData['qty']) ? $itemData['qty'] : 1;
647  $taxClassName =
648  isset($itemData['tax_class_name']) ? $itemData['tax_class_name'] : self::PRODUCT_TAX_CLASS_1;
649  $taxClassId = $this->productTaxClasses[$taxClassName];
650  $product = $this->createSimpleProduct($sku, $price, $taxClassId);
651  $quote->addProduct($product, $qty);
652  }
653  return $this;
654  }
655 
662  public function setupQuote($quoteData)
663  {
664  $customer = $this->createCustomer();
665 
666  $quote = $this->createQuote($quoteData, $customer);
667 
668  $this->addProductToQuote($quote, $quoteData['items']);
669 
670  //Set shipping amount
671  if (isset($quoteData['shipping_method'])) {
672  $quote->getShippingAddress()->setShippingMethod($quoteData['shipping_method']);
673  $quote->getShippingAddress()->setCollectShippingRates(true);
674  }
675 
676  //create shopping cart rules if necessary
677  if (!empty($quoteData['shopping_cart_rules'])) {
678  foreach ($quoteData['shopping_cart_rules'] as $ruleData) {
679  $ruleData['customer_group_ids'] = [$customer->getGroupId()];
680  $this->createCartRule($ruleData);
681  }
682  }
683 
684  return $quote;
685  }
686 }
const CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT
Definition: Config.php:42
$groupRepository
$billingAddress
Definition: order.php:25
const CONFIG_XML_PATH_APPLY_ON
Definition: Config.php:40
$customer
Definition: customers.php:11
$config
Definition: fraud_order.php:17
$quote
$shippingAddress
Definition: order.php:40
const CONFIG_XML_PATH_DISCOUNT_TAX
Definition: Config.php:44
processTaxRuleOverrides($taxRuleOverrideData, $taxRateIds)
Definition: SetupUtil.php:274
$price
const CONFIG_XML_PATH_SHIPPING_INCLUDES_TAX
Definition: Config.php:36
$addressData
Definition: order.php:19
$value
Definition: gender.phtml:16
$ruleData
Definition: tax_rule.php:26
const CONFIG_XML_PATH_SHIPPING_TAX_CLASS
Definition: Config.php:31
const CONFIG_XML_PATH_PRICE_INCLUDES_TAX
Definition: Config.php:34
const CONFIG_XML_PATH_BASED_ON
Definition: Config.php:38
$taxRate
Definition: tax_rule.php:12
$quoteShippingAddress
$customerAddress
if($currentSelectedMethod==$_code) $className
Definition: form.phtml:31