diff --git a/ImportExport/Processor/ProductVariantProcessor.php b/ImportExport/Processor/ProductVariantProcessor.php index cb3b173d..2bfb2f4b 100644 --- a/ImportExport/Processor/ProductVariantProcessor.php +++ b/ImportExport/Processor/ProductVariantProcessor.php @@ -89,7 +89,7 @@ function ($variantSku) { $variantSkus ); - $variantSkusUppercase = array_combine($variantSkusUppercase, $variantSkusUppercase); + $variantSkusUppercase = array_combine($variantSkusUppercase, $items); foreach ($parentProduct->getVariantLinks() as $variantLink) { $variantProduct = $variantLink->getProduct(); if (!$variantSkusUppercase) { @@ -110,12 +110,14 @@ function ($variantSku) { continue; } - $variantProduct->setStatus(Product::STATUS_ENABLED); + $variantItem = $variantSkusUppercase[$variantProduct->getSkuUppercase()]; + $status = empty($variantItem['enabled']) ? Product::STATUS_DISABLED : Product::STATUS_ENABLED; + $variantProduct->setStatus($status); unset($variantSkusUppercase[$variantProduct->getSkuUppercase()]); } - foreach ($variantSkusUppercase as $variantSku) { + foreach ($variantSkusUppercase as $variantSku => $variantItem) { $variantProduct = $productRepository->findOneBySku($variantSku); if (!$variantProduct instanceof Product) { $context->incrementErrorEntriesCount(); @@ -139,7 +141,8 @@ function ($variantSku) { $variantProduct->addParentVariantLink($variantLink); $parentProduct->addVariantLink($variantLink); - $variantProduct->setStatus(Product::STATUS_ENABLED); + $status = empty($variantItem['enabled']) ? Product::STATUS_DISABLED : Product::STATUS_ENABLED; + $variantProduct->setStatus($status); $context->incrementAddCount(); diff --git a/ImportExport/Writer/ConfigurableAsyncWriter.php b/ImportExport/Writer/ConfigurableAsyncWriter.php index 25aef5d4..26bc3eae 100644 --- a/ImportExport/Writer/ConfigurableAsyncWriter.php +++ b/ImportExport/Writer/ConfigurableAsyncWriter.php @@ -41,6 +41,10 @@ class ConfigurableAsyncWriter implements private $variants = []; + private $origins = []; + + private $models = []; + public function __construct( MessageProducerInterface $messageProducer, DoctrineHelper $doctrineHelper, @@ -56,6 +60,8 @@ public function __construct( public function initialize() { $this->variants = []; + $this->origins = []; + $this->models = []; $this->additionalOptionalListenerManager->disableListeners(); $this->optionalListenerManager->disableListeners($this->optionalListenerManager->getListeners()); @@ -64,32 +70,41 @@ public function initialize() public function write(array $items) { foreach ($items as $item) { + $origin = $item['origin']; $sku = $item['sku']; - if (!empty($item['family_variant'])) { - if (isset($item['parent'], $this->variants[$sku])) { - $parent = $item['parent']; - foreach (array_keys($this->variants[$sku]) as $sku) { - $this->variants[$parent][$sku] = ['parent' => $parent, 'variant' => $sku]; - } + if (isset($item['family_variant'])) { + $this->origins[$origin] = $sku; + + if (isset($item['parent'])) { + $this->models[$origin] = $item['parent']; } continue; } - if (empty($item['parent'])) { + if (!isset($item['parent'])) { continue; } $parent = $item['parent']; + if (!array_key_exists($parent, $this->origins)) { + continue; + } - $this->variants[$parent][$sku] = ['parent' => $parent, 'variant' => $sku]; + $this->variants[$parent][$origin] = [ + 'parent' => $this->origins[$parent] ?? $parent, + 'variant' => $sku, + 'enabled' => $item['enabled'] ?? false, + ]; } } public function close() { $this->variants = []; + $this->origins = []; + $this->models = []; $this->optionalListenerManager->enableListeners($this->optionalListenerManager->getListeners()); $this->additionalOptionalListenerManager->enableListeners(); @@ -97,6 +112,15 @@ public function close() public function flush() { + foreach ($this->models as $levelTwo => $levelOne) { + if (array_key_exists($levelTwo, $this->variants)) { + foreach ($this->variants[$levelTwo] as $sku => $item) { + $item['parent'] = $this->origins[$levelOne] ?? $levelOne; + $this->variants[$levelOne][$sku] = $item; + } + } + } + $channelId = $this->stepExecution->getJobExecution()->getExecutionContext()->get('channel'); $chunks = array_chunk($this->variants, self::VARIANTS_BATCH_SIZE, true); diff --git a/Integration/AkeneoSearchBuilder.php b/Integration/AkeneoSearchBuilder.php index 84389c4d..e65ae466 100644 --- a/Integration/AkeneoSearchBuilder.php +++ b/Integration/AkeneoSearchBuilder.php @@ -35,9 +35,9 @@ public function getFilters(string $json = null): array $option['operator'], $option['value'], array_merge( - (isset($option['scope']) ? ['scope' => $option['scope']] : []), - (isset($option['locale']) ? ['locale' => $option['locale']] : []), - (isset($option['locales']) ? ['locales' => $option['locales']] : []) + isset($option['scope']) ? ['scope' => $option['scope']] : [], + isset($option['locale']) ? ['locale' => $option['locale']] : [], + isset($option['locales']) ? ['locales' => $option['locales']] : [] ) ); } diff --git a/Integration/AkeneoTransport.php b/Integration/AkeneoTransport.php index 0d2f5057..f1afa429 100644 --- a/Integration/AkeneoTransport.php +++ b/Integration/AkeneoTransport.php @@ -238,14 +238,17 @@ public function getProducts(int $pageSize) ); } - public function getProductsList(int $pageSize): iterable + public function getProductsList(int $pageSize, ?string $family = null): iterable { - $this->initAttributesList(); - + $attributeMapping = $this->getAttributeMapping(); $queryParams = [ 'scope' => $this->transportEntity->getAkeneoActiveChannel(), - 'search' => $this->akeneoSearchBuilder->getFilters($this->transportEntity->getProductFilter()), - 'attributes' => key($this->attributes), + 'search' => $this->akeneoSearchBuilder->getFilters( + $family ? + json_encode(['family' => [['operator' => 'IN', 'value' => [$family]]]]) : + $this->transportEntity->getProductFilter() + ), + 'attributes' => $attributeMapping['sku'] ?? reset($attributeMapping), ]; if ($this->transportEntity->getSyncProducts() === SyncProductsDataProvider::PUBLISHED) { @@ -253,7 +256,7 @@ public function getProductsList(int $pageSize): iterable $this->client->getPublishedProductApi()->all($pageSize, $queryParams), $this->client, $this->logger, - $this->getAttributeMapping() + $attributeMapping ); } @@ -261,7 +264,7 @@ public function getProductsList(int $pageSize): iterable $this->client->getProductApi()->all($pageSize, $queryParams), $this->client, $this->logger, - $this->getAttributeMapping() + $attributeMapping ); } @@ -292,19 +295,18 @@ public function getProductModels(int $pageSize) public function getProductModelsList(int $pageSize): iterable { - $this->initAttributesList(); - + $attributeMapping = $this->getAttributeMapping(); $queryParams = [ 'scope' => $this->transportEntity->getAkeneoActiveChannel(), 'search' => $this->akeneoSearchBuilder->getFilters($this->transportEntity->getConfigurableProductFilter()), - 'attributes' => key($this->attributes), + 'attributes' => $attributeMapping['sku'] ?? reset($attributeMapping), ]; return new ConfigurableProductIterator( $this->client->getProductModelApi()->all($pageSize, $queryParams), $this->client, $this->logger, - $this->getAttributeMapping() + $attributeMapping ); } diff --git a/Integration/AkeneoTransportInterface.php b/Integration/AkeneoTransportInterface.php index 2f26b9b9..efee9c45 100644 --- a/Integration/AkeneoTransportInterface.php +++ b/Integration/AkeneoTransportInterface.php @@ -51,7 +51,7 @@ public function getProducts(int $pageSize); */ public function getProductModels(int $pageSize); - public function getProductsList(int $pageSize): iterable; + public function getProductsList(int $pageSize, ?string $family = null): iterable; public function getProductModelsList(int $pageSize): iterable; diff --git a/Integration/Connector/ConfigurableProductConnector.php b/Integration/Connector/ConfigurableProductConnector.php index ecb0ce15..90f4e382 100644 --- a/Integration/Connector/ConfigurableProductConnector.php +++ b/Integration/Connector/ConfigurableProductConnector.php @@ -64,9 +64,20 @@ protected function getConnectorSource() } $iterator = new \AppendIterator(); - $iterator->append($this->transport->getProductsList(self::PAGE_SIZE)); $iterator->append($this->transport->getProductModelsList(self::PAGE_SIZE)); - return $iterator; + $processed = []; + + return new \CallbackFilterIterator( + $iterator, + function ($current, $key, $iterator) use (&$processed) { + if (isset($current['family_variant'], $current['family']) && empty($processed[$current['family']])) { + $iterator->append($this->transport->getProductsList(self::PAGE_SIZE, $current['family'])); + $processed[$current['family']] = true; + } + + return true; + } + ); } } diff --git a/Integration/Iterator/ConfigurableProductIterator.php b/Integration/Iterator/ConfigurableProductIterator.php index 4a533506..7c214e43 100644 --- a/Integration/Iterator/ConfigurableProductIterator.php +++ b/Integration/Iterator/ConfigurableProductIterator.php @@ -33,6 +33,13 @@ public function doCurrent() } } - return ['sku' => (string)$sku, 'parent' => $item['parent'] ?? null, 'family_variant' => $item['family_variant'] ?? null]; + return [ + 'sku' => (string)$sku, + 'origin' => $item['identifier'] ?? $item['code'], + 'parent' => $item['parent'] ?? null, + 'family_variant' => $item['family_variant'] ?? null, + 'family' => $item['family'] ?? null, + 'enabled' => $item['enabled'] ?? false, + ]; } } diff --git a/Resources/translations/messages.en.yml b/Resources/translations/messages.en.yml index 26bd0041..b4e93621 100644 --- a/Resources/translations/messages.en.yml +++ b/Resources/translations/messages.en.yml @@ -88,7 +88,7 @@ oro: product: label: Product connector configurable_product: - label: Configurable product connector + label: Product Variants connector attribute_family: label: Attribute family connector attribute: