SalesSetup.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Sales\Setup;
  7. use Magento\Eav\Model\Entity\Setup\Context;
  8. use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory;
  9. use Magento\Eav\Setup\EavSetup;
  10. use Magento\Framework\App\CacheInterface;
  11. use Magento\Framework\App\Config\ScopeConfigInterface;
  12. use Magento\Framework\App\ResourceConnection;
  13. use Magento\Framework\Encryption\EncryptorInterface;
  14. use Magento\Framework\Setup\ModuleDataSetupInterface;
  15. /**
  16. * Sales module setup class
  17. *
  18. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  19. * @codeCoverageIgnore
  20. */
  21. class SalesSetup extends EavSetup
  22. {
  23. /**
  24. * This should be set explicitly
  25. */
  26. const ORDER_ENTITY_TYPE_ID = 5;
  27. /**
  28. * This should be set explicitly
  29. */
  30. const INVOICE_PRODUCT_ENTITY_TYPE_ID = 6;
  31. /**
  32. * This should be set explicitly
  33. */
  34. const CREDITMEMO_PRODUCT_ENTITY_TYPE_ID = 7;
  35. /**
  36. * This should be set explicitly
  37. */
  38. const SHIPMENT_PRODUCT_ENTITY_TYPE_ID = 8;
  39. /**
  40. * @var ScopeConfigInterface
  41. */
  42. protected $config;
  43. /**
  44. * @var EncryptorInterface
  45. */
  46. protected $encryptor;
  47. /**
  48. * @var string
  49. */
  50. private static $connectionName = 'sales';
  51. /**
  52. * Constructor
  53. *
  54. * @param ModuleDataSetupInterface $setup
  55. * @param Context $context
  56. * @param CacheInterface $cache
  57. * @param CollectionFactory $attrGroupCollectionFactory
  58. * @param ScopeConfigInterface $config
  59. */
  60. public function __construct(
  61. ModuleDataSetupInterface $setup,
  62. Context $context,
  63. CacheInterface $cache,
  64. CollectionFactory $attrGroupCollectionFactory,
  65. ScopeConfigInterface $config
  66. ) {
  67. $this->config = $config;
  68. $this->encryptor = $context->getEncryptor();
  69. parent::__construct($setup, $context, $cache, $attrGroupCollectionFactory);
  70. }
  71. /**
  72. * List of entities converted from EAV to flat data structure
  73. *
  74. * @var $_flatEntityTables array
  75. */
  76. protected $_flatEntityTables = [
  77. 'order' => 'sales_order',
  78. 'order_payment' => 'sales_order_payment',
  79. 'order_item' => 'sales_order_item',
  80. 'order_address' => 'sales_order_address',
  81. 'order_status_history' => 'sales_order_status_history',
  82. 'invoice' => 'sales_invoice',
  83. 'invoice_item' => 'sales_invoice_item',
  84. 'invoice_comment' => 'sales_invoice_comment',
  85. 'creditmemo' => 'sales_creditmemo',
  86. 'creditmemo_item' => 'sales_creditmemo_item',
  87. 'creditmemo_comment' => 'sales_creditmemo_comment',
  88. 'shipment' => 'sales_shipment',
  89. 'shipment_item' => 'sales_shipment_item',
  90. 'shipment_track' => 'sales_shipment_track',
  91. 'shipment_comment' => 'sales_shipment_comment',
  92. ];
  93. /**
  94. * List of entities used with separate grid table
  95. *
  96. * @var string[] $_flatEntitiesGrid
  97. */
  98. protected $_flatEntitiesGrid = ['order', 'invoice', 'shipment', 'creditmemo'];
  99. /**
  100. * Check if table exist for flat entity
  101. *
  102. * @param string $table
  103. * @return bool
  104. */
  105. protected function _flatTableExist($table)
  106. {
  107. $tablesList = $this->getConnection()
  108. ->listTables();
  109. return in_array(
  110. strtoupper($this->getTable($table)),
  111. array_map('strtoupper', $tablesList)
  112. );
  113. }
  114. /**
  115. * Add entity attribute. Overwritten for flat entities support
  116. *
  117. * @param int|string $entityTypeId
  118. * @param string $code
  119. * @param array $attr
  120. * @return $this
  121. */
  122. public function addAttribute($entityTypeId, $code, array $attr)
  123. {
  124. if (isset(
  125. $this->_flatEntityTables[$entityTypeId]
  126. ) && $this->_flatTableExist(
  127. $this->_flatEntityTables[$entityTypeId]
  128. )
  129. ) {
  130. $this->_addFlatAttribute($this->_flatEntityTables[$entityTypeId], $code, $attr);
  131. $this->_addGridAttribute($this->_flatEntityTables[$entityTypeId], $code, $attr, $entityTypeId);
  132. } else {
  133. parent::addAttribute($entityTypeId, $code, $attr);
  134. }
  135. return $this;
  136. }
  137. /**
  138. * Add attribute as separate column in the table
  139. *
  140. * @param string $table
  141. * @param string $attribute
  142. * @param array $attr
  143. * @return $this
  144. */
  145. protected function _addFlatAttribute($table, $attribute, $attr)
  146. {
  147. $tableInfo = $this->getConnection()
  148. ->describeTable($this->getTable($table));
  149. if (isset($tableInfo[$attribute])) {
  150. return $this;
  151. }
  152. $columnDefinition = $this->_getAttributeColumnDefinition($attribute, $attr);
  153. $this->getConnection()->addColumn(
  154. $this->getTable($table),
  155. $attribute,
  156. $columnDefinition
  157. );
  158. return $this;
  159. }
  160. /**
  161. * Add attribute to grid table if necessary
  162. *
  163. * @param string $table
  164. * @param string $attribute
  165. * @param array $attr
  166. * @param string $entityTypeId
  167. * @return $this
  168. */
  169. protected function _addGridAttribute($table, $attribute, $attr, $entityTypeId)
  170. {
  171. if (in_array($entityTypeId, $this->_flatEntitiesGrid) && !empty($attr['grid'])) {
  172. $columnDefinition = $this->_getAttributeColumnDefinition($attribute, $attr);
  173. $this->getConnection()->addColumn(
  174. $this->getTable($table . '_grid'),
  175. $attribute,
  176. $columnDefinition
  177. );
  178. }
  179. return $this;
  180. }
  181. /**
  182. * Retrieve definition of column for create in flat table
  183. *
  184. * @param string $code
  185. * @param array $data
  186. * @return array
  187. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  188. * @SuppressWarnings(PHPMD.NPathComplexity)
  189. */
  190. protected function _getAttributeColumnDefinition($code, $data)
  191. {
  192. // Convert attribute type to column info
  193. $data['type'] = isset($data['type']) ? $data['type'] : 'varchar';
  194. $type = null;
  195. $length = null;
  196. switch ($data['type']) {
  197. case 'timestamp':
  198. $type = \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP;
  199. break;
  200. case 'datetime':
  201. $type = \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME;
  202. break;
  203. case 'decimal':
  204. $type = \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL;
  205. $length = '12,4';
  206. break;
  207. case 'int':
  208. $type = \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER;
  209. break;
  210. case 'text':
  211. $type = \Magento\Framework\DB\Ddl\Table::TYPE_TEXT;
  212. $length = 65536;
  213. break;
  214. case 'char':
  215. case 'varchar':
  216. $type = \Magento\Framework\DB\Ddl\Table::TYPE_TEXT;
  217. $length = 255;
  218. break;
  219. }
  220. if ($type !== null) {
  221. $data['type'] = $type;
  222. $data['length'] = $length;
  223. }
  224. $data['nullable'] = isset($data['required']) ? !$data['required'] : true;
  225. $data['comment'] = isset($data['comment']) ? $data['comment'] : ucwords(str_replace('_', ' ', $code));
  226. return $data;
  227. }
  228. /**
  229. * @return array
  230. */
  231. public function getDefaultEntities()
  232. {
  233. $entities = [
  234. 'order' => [
  235. 'entity_type_id' => self::ORDER_ENTITY_TYPE_ID,
  236. 'entity_model' => \Magento\Sales\Model\ResourceModel\Order::class,
  237. 'table' => 'sales_order',
  238. 'increment_model' => \Magento\Eav\Model\Entity\Increment\NumericValue::class,
  239. 'increment_per_store' => true,
  240. 'attributes' => [],
  241. ],
  242. 'invoice' => [
  243. 'entity_type_id' => self::INVOICE_PRODUCT_ENTITY_TYPE_ID,
  244. 'entity_model' => \Magento\Sales\Model\ResourceModel\Order\Invoice::class,
  245. 'table' => 'sales_invoice',
  246. 'increment_model' => \Magento\Eav\Model\Entity\Increment\NumericValue::class,
  247. 'increment_per_store' => true,
  248. 'attributes' => [],
  249. ],
  250. 'creditmemo' => [
  251. 'entity_type_id' => self::CREDITMEMO_PRODUCT_ENTITY_TYPE_ID,
  252. 'entity_model' => \Magento\Sales\Model\ResourceModel\Order\Creditmemo::class,
  253. 'table' => 'sales_creditmemo',
  254. 'increment_model' => \Magento\Eav\Model\Entity\Increment\NumericValue::class,
  255. 'increment_per_store' => true,
  256. 'attributes' => [],
  257. ],
  258. 'shipment' => [
  259. 'entity_type_id' => self::SHIPMENT_PRODUCT_ENTITY_TYPE_ID,
  260. 'entity_model' => \Magento\Sales\Model\ResourceModel\Order\Shipment::class,
  261. 'table' => 'sales_shipment',
  262. 'increment_model' => \Magento\Eav\Model\Entity\Increment\NumericValue::class,
  263. 'increment_per_store' => true,
  264. 'attributes' => [],
  265. ],
  266. ];
  267. return $entities;
  268. }
  269. /**
  270. * Get config model
  271. *
  272. * @return ScopeConfigInterface
  273. */
  274. public function getConfigModel()
  275. {
  276. return $this->config;
  277. }
  278. /**
  279. * @return EncryptorInterface
  280. */
  281. public function getEncryptor()
  282. {
  283. return $this->encryptor;
  284. }
  285. /**
  286. * @return \Magento\Framework\DB\Adapter\AdapterInterface
  287. */
  288. public function getConnection()
  289. {
  290. return $this->getSetup()->getConnection(self::$connectionName);
  291. }
  292. /**
  293. * Get table name
  294. *
  295. * @param string $table
  296. * @return string
  297. */
  298. public function getTable($table)
  299. {
  300. return $this->getSetup()->getTable($table, self::$connectionName);
  301. }
  302. /**
  303. * Update entity types
  304. *
  305. * @return void
  306. */
  307. public function updateEntityTypes()
  308. {
  309. $this->updateEntityType(
  310. \Magento\Sales\Model\Order::ENTITY,
  311. 'entity_model',
  312. \Magento\Sales\Model\ResourceModel\Order::class
  313. );
  314. $this->updateEntityType(
  315. \Magento\Sales\Model\Order::ENTITY,
  316. 'increment_model',
  317. \Magento\Eav\Model\Entity\Increment\NumericValue::class
  318. );
  319. $this->updateEntityType(
  320. 'invoice',
  321. 'entity_model',
  322. \Magento\Sales\Model\ResourceModel\Order::class
  323. );
  324. $this->updateEntityType(
  325. 'invoice',
  326. 'increment_model',
  327. \Magento\Eav\Model\Entity\Increment\NumericValue::class
  328. );
  329. $this->updateEntityType(
  330. 'creditmemo',
  331. 'entity_model',
  332. \Magento\Sales\Model\ResourceModel\Order\Creditmemo::class
  333. );
  334. $this->updateEntityType(
  335. 'creditmemo',
  336. 'increment_model',
  337. \Magento\Eav\Model\Entity\Increment\NumericValue::class
  338. );
  339. $this->updateEntityType(
  340. 'shipment',
  341. 'entity_model',
  342. \Magento\Sales\Model\ResourceModel\Order\Shipment::class
  343. );
  344. $this->updateEntityType(
  345. 'shipment',
  346. 'increment_model',
  347. \Magento\Eav\Model\Entity\Increment\NumericValue::class
  348. );
  349. }
  350. }