Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
AdvancedPricing.php
Go to the documentation of this file.
1 <?php
7 
13 
23 {
24  const ENTITY_ADVANCED_PRICING = 'advanced_pricing';
25 
29  protected $_storeResolver;
30 
34  protected $_groupRepository;
35 
39  protected $_entityTypeCode;
40 
44  protected $_resource;
45 
49  protected $_passTierPrice = 0;
50 
56  protected $_priceWebsite = [
57  ImportAdvancedPricing::COL_TIER_PRICE_WEBSITE,
58  ];
59 
65  protected $_priceCustomerGroup = [
66  ImportAdvancedPricing::COL_TIER_PRICE_CUSTOMER_GROUP,
67  ];
68 
74  protected $templateExportData = [
75  ImportAdvancedPricing::COL_SKU => '',
76  ImportAdvancedPricing::COL_TIER_PRICE_WEBSITE => '',
77  ImportAdvancedPricing::COL_TIER_PRICE_CUSTOMER_GROUP => '',
78  ImportAdvancedPricing::COL_TIER_PRICE_QTY => '',
79  ImportAdvancedPricing::COL_TIER_PRICE => '',
80  ImportAdvancedPricing::COL_TIER_PRICE_TYPE => ''
81  ];
82 
86  private $websiteCodesMap = [];
87 
109  public function __construct(
110  \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
111  \Magento\Eav\Model\Config $config,
112  \Magento\Framework\App\ResourceConnection $resource,
113  \Magento\Store\Model\StoreManagerInterface $storeManager,
114  \Psr\Log\LoggerInterface $logger,
115  \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
116  \Magento\ImportExport\Model\Export\ConfigInterface $exportConfig,
117  \Magento\Catalog\Model\ResourceModel\ProductFactory $productFactory,
118  \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFactory,
119  \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryColFactory,
120  \Magento\CatalogInventory\Model\ResourceModel\Stock\ItemFactory $itemFactory,
121  \Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory $optionColFactory,
122  \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $attributeColFactory,
123  \Magento\CatalogImportExport\Model\Export\Product\Type\Factory $_typeFactory,
124  \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider,
125  \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface $rowCustomizer,
126  \Magento\CatalogImportExport\Model\Import\Product\StoreResolver $storeResolver,
127  \Magento\Customer\Api\GroupRepositoryInterface $groupRepository
128  ) {
129  $this->_storeResolver = $storeResolver;
130  $this->_groupRepository = $groupRepository;
131  $this->_resource = $resource;
132  parent::__construct(
133  $localeDate,
134  $config,
135  $resource,
137  $logger,
138  $collectionFactory,
139  $exportConfig,
141  $attrSetColFactory,
142  $categoryColFactory,
143  $itemFactory,
144  $optionColFactory,
145  $attributeColFactory,
147  $linkTypeProvider,
149  );
150  }
151 
156  protected function initTypeModels()
157  {
158  $productTypes = $this->_exportConfig->getEntityTypes(CatalogProduct::ENTITY);
159  foreach ($productTypes as $productTypeName => $productTypeConfig) {
160  if (!($model = $this->_typeFactory->create($productTypeConfig['model']))) {
161  throw new \Magento\Framework\Exception\LocalizedException(
162  __('Entity type model \'%1\' is not found', $productTypeConfig['model'])
163  );
164  }
165  if (!$model instanceof \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType) {
166  throw new \Magento\Framework\Exception\LocalizedException(
167  __(
168  'Entity type model must be an instance of'
169  . ' \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType'
170  )
171  );
172  }
173  if ($model->isSuitable()) {
174  $this->_productTypeModels[$productTypeName] = $model;
175  $this->_disabledAttrs = array_merge($this->_disabledAttrs, $model->getDisabledAttrs());
176  $this->_indexValueAttributes = array_merge(
177  $this->_indexValueAttributes,
178  $model->getIndexValueAttributes()
179  );
180  }
181  }
182  if (!$this->_productTypeModels) {
183  throw new \Magento\Framework\Exception\LocalizedException(
184  __('There are no product types available for export')
185  );
186  }
187  $this->_disabledAttrs = array_unique($this->_disabledAttrs);
188  return $this;
189  }
190 
197  public function export()
198  {
199  //Execution time may be very long
200  set_time_limit(0);
201 
202  $writer = $this->getWriter();
203  $page = 0;
204  while (true) {
205  ++$page;
206  $entityCollection = $this->_getEntityCollection(true);
207  $entityCollection->setOrder('has_options', 'asc');
208  $entityCollection->setStoreId(Store::DEFAULT_STORE_ID);
209  $this->_prepareEntityCollection($entityCollection);
210  $this->paginateCollection($page, $this->getItemsPerPage());
211  if ($entityCollection->count() == 0) {
212  break;
213  }
214  $exportData = $this->getExportData();
215  foreach ($exportData as $dataRow) {
216  $writer->writeRow($dataRow);
217  }
218  if ($entityCollection->getCurPage() >= $entityCollection->getLastPageNumber()) {
219  break;
220  }
221  }
222  return $writer->getContents();
223  }
224 
231  public function filterAttributeCollection(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection $collection)
232  {
233  $collection->load();
234 
235  foreach ($collection as $attribute) {
236  if (in_array($attribute->getAttributeCode(), $this->_disabledAttrs)) {
237  if (isset($this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_SKIP])) {
238  if ($attribute->getAttributeCode() == ImportAdvancedPricing::COL_TIER_PRICE
239  && in_array(
240  $attribute->getId(),
242  )
243  ) {
244  $this->_passTierPrice = 1;
245  }
246  }
247  $collection->removeItemByKey($attribute->getId());
248  }
249  }
250  return $collection;
251  }
252 
262  protected function getExportData()
263  {
264  if ($this->_passTierPrice) {
265  return [];
266  }
267 
268  $exportData = [];
269  try {
270  $productsByStores = $this->loadCollection();
271  if (!empty($productsByStores)) {
272  $linkField = $this->getProductEntityLinkField();
273  $productLinkIds = [];
274 
275  foreach ($productsByStores as $product) {
276  $productLinkIds[array_pop($product)[$linkField]] = true;
277  }
278  $productLinkIds = array_keys($productLinkIds);
279  $tierPricesData = $this->fetchTierPrices($productLinkIds);
280  $exportData = $this->prepareExportData(
281  $productsByStores,
282  $tierPricesData
283  );
284  if (!empty($exportData)) {
285  asort($exportData);
286  }
287  }
288  } catch (\Throwable $e) {
289  $this->_logger->critical($e);
290  }
291 
292  return $exportData;
293  }
294 
302  private function createExportRow(array $tierPriceData): array
303  {
304  //List of columns to display in export row.
305  $exportRow = $this->templateExportData;
306 
307  foreach (array_keys($exportRow) as $keyTemplate) {
308  if (array_key_exists($keyTemplate, $tierPriceData)) {
309  if (in_array($keyTemplate, $this->_priceWebsite)) {
310  //If it's website column then getting website code.
311  $exportRow[$keyTemplate] = $this->_getWebsiteCode(
312  $tierPriceData[$keyTemplate]
313  );
314  } elseif (in_array($keyTemplate, $this->_priceCustomerGroup)) {
315  //If it's customer group column then getting customer
316  //group name by ID.
317  $exportRow[$keyTemplate] = $this->_getCustomerGroupById(
318  $tierPriceData[$keyTemplate],
319  $tierPriceData[ImportAdvancedPricing::VALUE_ALL_GROUPS]
320  );
321  unset($exportRow[ImportAdvancedPricing::VALUE_ALL_GROUPS]);
322  } elseif ($keyTemplate
323  === ImportAdvancedPricing::COL_TIER_PRICE
324  ) {
325  //If it's price column then getting value and type
326  //of tier price.
327  $exportRow[$keyTemplate]
328  = $tierPriceData[ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE]
329  ? $tierPriceData[ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE]
330  : $tierPriceData[ImportAdvancedPricing::COL_TIER_PRICE];
331  $exportRow[ImportAdvancedPricing::COL_TIER_PRICE_TYPE]
332  = $this->tierPriceTypeValue($tierPriceData);
333  } else {
334  //Any other column just goes as is.
335  $exportRow[$keyTemplate] = $tierPriceData[$keyTemplate];
336  }
337  }
338  }
339 
340  return $exportRow;
341  }
342 
351  private function prepareExportData(
352  array $productsData,
353  array $tierPricesData
354  ): array {
355  //Assigning SKUs to tier prices data.
356  $productLinkIdToSkuMap = [];
357  foreach ($productsData as $productData) {
358  $productLinkIdToSkuMap[$productData[Store::DEFAULT_STORE_ID][$this->getProductEntityLinkField()]]
359  = $productData[Store::DEFAULT_STORE_ID]['sku'];
360  }
361 
362  //Adding products' SKUs to tier price data.
363  $linkedTierPricesData = [];
364  foreach ($tierPricesData as $tierPriceData) {
365  $sku = $productLinkIdToSkuMap[$tierPriceData['product_link_id']];
366  $linkedTierPricesData[] = array_merge(
368  [ImportAdvancedPricing::COL_SKU => $sku]
369  );
370  }
371 
372  //Formatting data for export.
373  $customExportData = [];
374  foreach ($linkedTierPricesData as $row) {
375  $customExportData[] = $this->createExportRow($row);
376  }
377 
378  return $customExportData;
379  }
380 
390  protected function correctExportData($exportData)
391  {
392  $customExportData = [];
393  foreach ($exportData as $key => $row) {
394  $exportRow = $this->templateExportData;
395  foreach ($exportRow as $keyTemplate => $valueTemplate) {
396  if (isset($row[$keyTemplate])) {
397  if (in_array($keyTemplate, $this->_priceWebsite)) {
398  $exportRow[$keyTemplate] = $this->_getWebsiteCode(
399  $row[$keyTemplate]
400  );
401  } elseif (in_array($keyTemplate, $this->_priceCustomerGroup)) {
402  $exportRow[$keyTemplate] = $this->_getCustomerGroupById(
403  $row[$keyTemplate],
404  isset($row[ImportAdvancedPricing::VALUE_ALL_GROUPS])
405  ? $row[ImportAdvancedPricing::VALUE_ALL_GROUPS]
406  : null
407  );
408  unset($exportRow[ImportAdvancedPricing::VALUE_ALL_GROUPS]);
409  } elseif ($keyTemplate === ImportAdvancedPricing::COL_TIER_PRICE) {
410  $exportRow[$keyTemplate] = $row[ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE]
411  ? $row[ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE]
412  : $row[ImportAdvancedPricing::COL_TIER_PRICE];
413  $exportRow[ImportAdvancedPricing::COL_TIER_PRICE_TYPE]
414  = $this->tierPriceTypeValue($row[ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE]);
415  } else {
416  $exportRow[$keyTemplate] = $row[$keyTemplate];
417  }
418  }
419  }
420 
421  $customExportData[$key] = $exportRow;
422  unset($exportRow);
423  }
424 
425  return $customExportData;
426  }
427 
434  private function tierPriceTypeValue(array $tierPriceData): string
435  {
436  return $tierPriceData[ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE]
437  ? ImportAdvancedPricing::TIER_PRICE_TYPE_PERCENT
438  : ImportAdvancedPricing::TIER_PRICE_TYPE_FIXED;
439  }
440 
451  private function fetchTierPrices(array $productIds): array
452  {
453  if (empty($productIds)) {
454  throw new \InvalidArgumentException(
455  'Can only load tier prices for specific products'
456  );
457  }
458 
459  $pricesTable = ImportAdvancedPricing::TABLE_TIER_PRICE;
460  $exportFilter = null;
461  $priceFromFilter = null;
462  $priceToFilter = null;
463  if (isset($this->_parameters[Export::FILTER_ELEMENT_GROUP])) {
464  $exportFilter = $this->_parameters[Export::FILTER_ELEMENT_GROUP];
465  }
466  $productEntityLinkField = $this->getProductEntityLinkField();
467  $selectFields = [
468  ImportAdvancedPricing::COL_TIER_PRICE_WEBSITE => 'ap.website_id',
469  ImportAdvancedPricing::VALUE_ALL_GROUPS => 'ap.all_groups',
470  ImportAdvancedPricing::COL_TIER_PRICE_CUSTOMER_GROUP => 'ap.customer_group_id',
471  ImportAdvancedPricing::COL_TIER_PRICE_QTY => 'ap.qty',
472  ImportAdvancedPricing::COL_TIER_PRICE => 'ap.value',
473  ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE => 'ap.percentage_value',
474  'product_link_id' => 'ap.' .$productEntityLinkField,
475  ];
476  if ($exportFilter && array_key_exists('tier_price', $exportFilter)) {
477  if (!empty($exportFilter['tier_price'][0])) {
478  $priceFromFilter = $exportFilter['tier_price'][0];
479  }
480  if (!empty($exportFilter['tier_price'][1])) {
481  $priceToFilter = $exportFilter['tier_price'][1];
482  }
483  }
484 
485  $select = $this->_connection->select()
486  ->from(
487  ['ap' => $this->_resource->getTableName($pricesTable)],
488  $selectFields
489  )
490  ->where(
491  'ap.'.$productEntityLinkField.' IN (?)',
493  );
494 
495  if ($priceFromFilter !== null) {
496  $select->where('ap.value >= ?', $priceFromFilter);
497  }
498  if ($priceToFilter !== null) {
499  $select->where('ap.value <= ?', $priceToFilter);
500  }
501  if ($priceFromFilter || $priceToFilter) {
502  $select->orWhere('ap.percentage_value IS NOT NULL');
503  }
504 
505  return $this->_connection->fetchAll($select);
506  }
507 
519  protected function getTierPrices(array $listSku, $table)
520  {
521  if (isset($this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP])) {
522  $exportFilter = $this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP];
523  }
524  if ($table == ImportAdvancedPricing::TABLE_TIER_PRICE) {
525  $selectFields = [
526  ImportAdvancedPricing::COL_SKU => 'cpe.sku',
527  ImportAdvancedPricing::COL_TIER_PRICE_WEBSITE => 'ap.website_id',
528  ImportAdvancedPricing::VALUE_ALL_GROUPS => 'ap.all_groups',
529  ImportAdvancedPricing::COL_TIER_PRICE_CUSTOMER_GROUP => 'ap.customer_group_id',
530  ImportAdvancedPricing::COL_TIER_PRICE_QTY => 'ap.qty',
531  ImportAdvancedPricing::COL_TIER_PRICE => 'ap.value',
532  ImportAdvancedPricing::COL_TIER_PRICE_PERCENTAGE_VALUE => 'ap.percentage_value',
533  ];
534  if (isset($exportFilter) && !empty($exportFilter)) {
535  $price = $exportFilter['tier_price'];
536  }
537  }
538  if ($listSku) {
539  if (isset($exportFilter) && !empty($exportFilter)) {
541  if (isset($date[0]) && !empty($date[0])) {
542  $updatedAtFrom = $this->_localeDate->date($date[0], null, false)->format('Y-m-d H:i:s');
543  }
544  if (isset($date[1]) && !empty($date[1])) {
545  $updatedAtTo = $this->_localeDate->date($date[1], null, false)->format('Y-m-d H:i:s');
546  }
547  }
548  try {
549  $productEntityLinkField = $this->getProductEntityLinkField();
550  $select = $this->_connection->select()
551  ->from(
552  ['cpe' => $this->_resource->getTableName('catalog_product_entity')],
553  $selectFields
554  )
555  ->joinInner(
556  ['ap' => $this->_resource->getTableName($table)],
557  'ap.' . $productEntityLinkField . ' = cpe.' . $productEntityLinkField,
558  []
559  )
560  ->where('cpe.entity_id IN (?)', $listSku);
561 
562  if (isset($price[0]) && !empty($price[0])) {
563  $select->where('ap.value >= ?', $price[0]);
564  }
565  if (isset($price[1]) && !empty($price[1])) {
566  $select->where('ap.value <= ?', $price[1]);
567  }
568  if (isset($price[0]) && !empty($price[0]) || isset($price[1]) && !empty($price[1])) {
569  $select->orWhere('ap.percentage_value IS NOT NULL');
570  }
571  if (isset($updatedAtFrom) && !empty($updatedAtFrom)) {
572  $select->where('cpe.updated_at >= ?', $updatedAtFrom);
573  }
574  if (isset($updatedAtTo) && !empty($updatedAtTo)) {
575  $select->where('cpe.updated_at <= ?', $updatedAtTo);
576  }
577  $exportData = $this->_connection->fetchAll($select);
578  } catch (\Exception $e) {
579  return false;
580  }
581  }
582  return $exportData;
583  }
584 
592  protected function _getWebsiteCode(int $websiteId): string
593  {
594  if (!array_key_exists($websiteId, $this->websiteCodesMap)) {
595  $storeName = ($websiteId == 0)
596  ? ImportAdvancedPricing::VALUE_ALL_WEBSITES
597  : $this->_storeManager->getWebsite($websiteId)->getCode();
598  $currencyCode = '';
599  if ($websiteId == 0) {
600  $currencyCode = $this->_storeManager->getWebsite($websiteId)
601  ->getBaseCurrencyCode();
602  }
603 
604  if ($storeName && $currencyCode) {
605  $code = $storeName.' ['.$currencyCode.']';
606  } else {
607  $code = $storeName;
608  }
609  $this->websiteCodesMap[$websiteId] = $code;
610  }
611 
612  return $this->websiteCodesMap[$websiteId];
613  }
614 
624  protected function _getCustomerGroupById(
625  int $groupId,
626  int $allGroups = 0
627  ): string {
628  if ($allGroups !== 0) {
629  return ImportAdvancedPricing::VALUE_ALL_GROUPS;
630  }
631  return $this->_groupRepository->getById($groupId)->getCode();
632  }
633 
639  public function getEntityTypeCode()
640  {
641  if (!$this->_entityTypeCode) {
642  $this->_entityTypeCode = CatalogProduct::ENTITY;
643  } else {
644  $this->_entityTypeCode = self::ENTITY_ADVANCED_PRICING;
645  }
646  return $this->_entityTypeCode;
647  }
648 }
__construct(\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Eav\Model\Config $config, \Magento\Framework\App\ResourceConnection $resource, \Magento\Store\Model\StoreManagerInterface $storeManager, \Psr\Log\LoggerInterface $logger, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory, \Magento\ImportExport\Model\Export\ConfigInterface $exportConfig, \Magento\Catalog\Model\ResourceModel\ProductFactory $productFactory, \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFactory, \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryColFactory, \Magento\CatalogInventory\Model\ResourceModel\Stock\ItemFactory $itemFactory, \Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory $optionColFactory, \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $attributeColFactory, \Magento\CatalogImportExport\Model\Export\Product\Type\Factory $_typeFactory, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider, \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface $rowCustomizer, \Magento\CatalogImportExport\Model\Import\Product\StoreResolver $storeResolver, \Magento\Customer\Api\GroupRepositoryInterface $groupRepository)
if($msrpShowOnGesture && $price['price']->getValue()< $product->getMsrp()) if($isSaleable) $tierPriceData
$groupRepository
_prepareEntityCollection(\Magento\Eav\Model\Entity\Collection\AbstractCollection $collection)
Definition: Product.php:864
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$config
Definition: fraud_order.php:17
$productsData
Definition: products.php:19
$storeManager
__()
Definition: __.php:13
$resource
Definition: bulk.php:12
$price
$logger
_getEntityCollection($resetCollection=false)
Definition: Product.php:756
$page
Definition: pages.php:8
$productData
filterAttributeCollection(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection $collection)
$storeName
Definition: logo.phtml:13
$table
Definition: trigger.php:14
$code
Definition: info.phtml:12