diff --git a/Controller/Getconfig/Index.php b/Controller/Getconfig/Index.php index 780333d..55ab0c8 100644 --- a/Controller/Getconfig/Index.php +++ b/Controller/Getconfig/Index.php @@ -109,6 +109,7 @@ public function execute() 'PRODUCT_SYNCHRONIZATION_ADDITIONAL_FIELDS_HEAVY_QUERY' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_ADDITIONAL_FIELDS_HEAVY_QUERY, $scope, $scopeID), 'PRODUCT_SYNCHRONIZATION_SALABLE_ONLY' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_SALABLE_ONLY, $scope, $scopeID), 'PRODUCT_SYNCHRONIZATION_VISIBILITY' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_VISIBILITY, $scope, $scopeID), + 'PRODUCT_SYNCHRONIZATION_EXCLUDE_DISABLED_PRODUCTS' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_EXCLUDE_DISABLED_PRODUCTS, $scope, $scopeID), 'PRODUCT_SYNCHRONIZATION_DISABLE_ORDER_SYNCHRONIZATION' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_DISABLE_ORDER_SYNCHRONIZATION, $scope, $scopeID), 'PRODUCT_SYNCHRONIZATION_ENABLE_ORDER_RETURN_SYNCHRONIZATION' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_ENABLE_ORDER_RETURN_SYNCHRONIZATION, $scope, $scopeID), 'PRODUCT_SYNCHRONIZATION_IMAGE_TYPE' => $this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_IMAGE_TYPE, $scope, $scopeID), diff --git a/Model/Adapter/Product.php b/Model/Adapter/Product.php index 19bd661..f4b4992 100644 --- a/Model/Adapter/Product.php +++ b/Model/Adapter/Product.php @@ -258,6 +258,11 @@ protected function prepareCollection($page, $limit, $orderBy, $order, $scope, $s break; } + // Filter out disabled products and their children if configuration is enabled + if ($this->scopeConfig->getValue(Config::XML_PATH_PRODUCT_SYNCHRONIZATION_EXCLUDE_DISABLED_PRODUCTS, $scope, $scopeid)) { + $this->filterDisabledProducts($collection, $scopeid); + } + $collection->setPageSize($limit)->setCurPage($page)->addOrder($orderBy, $order); $this->eventManager->dispatch('clerk_' . $this->eventPrefix . '_get_collection_after', [ @@ -274,6 +279,97 @@ protected function prepareCollection($page, $limit, $orderBy, $order, $scope, $s } } + /** + * Filter out disabled products and their children from the collection + * + * @param $collection + * @param $scopeid + * @return void + */ + protected function filterDisabledProducts($collection, $scopeid) + { + try { + // First, filter out disabled products directly + $collection->addAttributeToFilter('status', \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); + + // Get all disabled configurable products to exclude their children + $disabledConfigurableProducts = $this->collectionFactory->create() + ->addStoreFilter($scopeid) + ->addAttributeToFilter('type_id', self::PRODUCT_TYPE_CONFIGURABLE) + ->addAttributeToFilter('status', \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) + ->getAllIds(); + + if (!empty($disabledConfigurableProducts)) { + // Get all child products of disabled configurable products + $childProductIds = []; + foreach ($disabledConfigurableProducts as $parentId) { + try { + $parentProduct = $this->_productRepository->getById($parentId, false, $scopeid); + if ($parentProduct->getTypeId() === self::PRODUCT_TYPE_CONFIGURABLE) { + $childProducts = $parentProduct->getTypeInstance()->getUsedProducts($parentProduct); + foreach ($childProducts as $childProduct) { + $childProductIds[] = $childProduct->getId(); + } + } + } catch (Exception $e) { + $this->clerk_logger->error('Error getting child products for disabled parent', [ + 'parent_id' => $parentId, + 'error' => $e->getMessage() + ]); + } + } + + // Exclude child products of disabled configurable products + if (!empty($childProductIds)) { + $collection->addFieldToFilter('entity_id', ['nin' => $childProductIds]); + $this->clerk_logger->log('Excluded child products of disabled configurable products', [ + 'disabled_parent_count' => count($disabledConfigurableProducts), + 'excluded_child_count' => count($childProductIds) + ]); + } + } + + // Also handle grouped products + $disabledGroupedProducts = $this->collectionFactory->create() + ->addStoreFilter($scopeid) + ->addAttributeToFilter('type_id', self::PRODUCT_TYPE_GROUPED) + ->addAttributeToFilter('status', \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) + ->getAllIds(); + + if (!empty($disabledGroupedProducts)) { + $associatedProductIds = []; + foreach ($disabledGroupedProducts as $parentId) { + try { + $parentProduct = $this->_productRepository->getById($parentId, false, $scopeid); + if ($parentProduct->getTypeId() === self::PRODUCT_TYPE_GROUPED) { + $associatedProducts = $parentProduct->getTypeInstance()->getAssociatedProducts($parentProduct); + foreach ($associatedProducts as $associatedProduct) { + $associatedProductIds[] = $associatedProduct->getId(); + } + } + } catch (Exception $e) { + $this->clerk_logger->error('Error getting associated products for disabled grouped parent', [ + 'parent_id' => $parentId, + 'error' => $e->getMessage() + ]); + } + } + + // Exclude associated products of disabled grouped products + if (!empty($associatedProductIds)) { + $collection->addFieldToFilter('entity_id', ['nin' => $associatedProductIds]); + $this->clerk_logger->log('Excluded associated products of disabled grouped products', [ + 'disabled_parent_count' => count($disabledGroupedProducts), + 'excluded_associated_count' => count($associatedProductIds) + ]); + } + } + + } catch (Exception $e) { + $this->clerk_logger->error('Error filtering disabled products', ['error' => $e->getMessage()]); + } + } + /** * Add field handlers for products */ diff --git a/Model/Config.php b/Model/Config.php index 347a77b..0d2439b 100644 --- a/Model/Config.php +++ b/Model/Config.php @@ -25,6 +25,7 @@ class Config const XML_PATH_PRODUCT_SYNCHRONIZATION_ADDITIONAL_FIELDS_HEAVY_QUERY = 'clerk/product_synchronization/additional_fields_heavy_query'; const XML_PATH_PRODUCT_SYNCHRONIZATION_SALABLE_ONLY = 'clerk/product_synchronization/saleable_only'; const XML_PATH_PRODUCT_SYNCHRONIZATION_VISIBILITY = 'clerk/product_synchronization/visibility'; + const XML_PATH_PRODUCT_SYNCHRONIZATION_EXCLUDE_DISABLED_PRODUCTS = 'clerk/product_synchronization/exclude_disabled_products'; const XML_PATH_PRODUCT_SYNCHRONIZATION_DISABLE_ORDER_SYNCHRONIZATION = 'clerk/product_synchronization/disable_order_synchronization'; const XML_PATH_PRODUCT_SYNCHRONIZATION_IMAGE_TYPE = 'clerk/product_synchronization/image_type'; const XML_PATH_PRODUCT_SYNCHRONIZATION_ENABLE_ORDER_RETURN_SYNCHRONIZATION = 'clerk/product_synchronization/return_order_synchronization'; diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 5eac75a..9e12259 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -73,6 +73,11 @@ Clerk\Clerk\Model\Config\Source\Visibility + + + When enabled, disabled parent products and their children will not be imported to Clerk + Magento\Config\Model\Config\Source\Yesno + Magento\Config\Model\Config\Source\Yesno diff --git a/etc/config.xml b/etc/config.xml index 33efcdd..4453523 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -13,6 +13,7 @@ 1 4 + 1 0