Como obter a coleção de produtos fora de estoque - o oposto de addInStockFilterToCollection ()?
-
13-12-2019 - |
Pergunta
Tenho a necessidade de exibir os produtos de uma categoria em duas listas - uma para itens em estoque e outra para itens fora de estoque.
estou a usar
Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection()
para filtrar minha coleção de produtos para itens em estoque, mas não parece haver um método equivalente para filtrar itens fora de estoque - eu olhei para o Mage_CatalogInventory_Model_Stock
modelo, que é onde o método acima mencionado é definido.
Vi o seguinte exemplo para recuperar produtos fora de estoque:
$collection->joinField(
'is_in_stock',
'cataloginventory/stock_item',
'is_in_stock',
'product_id=entity_id',
'{{table}}.stock_id=1',
'left'
)
->addAttributeToFilter('is_in_stock', array('eq' => 0));
...mas certamente esta não é a única ou a melhor maneira de conseguir isso?
Solução
digamos que $collection
é a sua coleção de produtos que você constrói assim:
$collection = Mage::getModel('catalog/product')->getCollection()
->...additional filters here...;
agora faça isso com sua coleção.Isso une a coleção à tabela de status do estoque.
$website = Mage::app()->getWebsite();
Mage::getModel('cataloginventory/stock_status')->addStockStatusToSelect($collection, $website);
Agora você pode filtrar os produtos fora de estoque:
$collection->getSelect()->where('stock_status.stock_status = ?', 0);
Outras dicas
Seu exemplo não leva em consideração o valor de "use config".
Vamos dar uma olhada em como addInStockFilterToCollection
funciona:
public function addInStockFilterToCollection($collection)
{
$this->getResource()->setInStockFilterToCollection($collection);
return $this;
}
OK, está delegando para outro método:
public function setInStockFilterToCollection($collection)
{
$manageStock = Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK);
$cond = array(
'{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=1 AND {{table}}.is_in_stock=1',
'{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=0',
);
if ($manageStock) {
$cond[] = '{{table}}.use_config_manage_stock = 1 AND {{table}}.is_in_stock=1';
} else {
$cond[] = '{{table}}.use_config_manage_stock = 1';
}
$collection->joinField(
'inventory_in_stock',
'cataloginventory/stock_item',
'is_in_stock',
'product_id=entity_id',
'(' . join(') OR (', $cond) . ')'
);
return $this;
}
Isso une a tabela de inventário com as seguintes condições:
O produto não usa configuração global E tem "gerenciar estoque" definido como "sim" E está em estoque
OU
O produto não usa configuração global E tem "gerenciar estoque" definido como "não"
OU
- O produto usa configuração global E se a configuração global for "gerenciar estoque = sim", está em estoque
Você precisa inverter as condições da seguinte forma:
O produto não usa configuração global E tem "gerenciar estoque" definido como "sim" E não está em estoque
OU
O produto usa configuração global E a configuração global é "gerenciar estoque = sim" E não está em estoque
Explicação:Você pega apenas as condições em que in_stock está realmente verificado e altera a comparação para 0.As condições onde in_stock não está marcado ("gerenciar estoque" = "não") significam que o produto está sempre em estoque, independente do status do estoque, por isso não os incluímos em nossa consulta "esgotado".
Então este é o seu código:
public function setOutOfStockFilterToCollection($collection)
{
$manageStock = Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK);
$cond = array(
'{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=1 AND {{table}}.is_in_stock=0'
);
if ($manageStock) {
$cond[] = '{{table}}.use_config_manage_stock = 1 AND {{table}}.is_in_stock=0';
}
$collection->joinField(
'inventory_in_stock',
'cataloginventory/stock_item',
'is_in_stock',
'product_id=entity_id',
'(' . join(') OR (', $cond) . ')'
);
return $this;
}
Você pode tentar isso.
$manageStock = Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK); $cond = array( '{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=1 AND {{table}}.is_in_stock=0', '{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=0', ); if ($manageStock) { $cond[] = '{{table}}.use_config_manage_stock = 1 AND {{table}}.is_in_stock=0'; } else { $cond[] = '{{table}}.use_config_manage_stock = 1'; } $collection->joinField( 'inventory_in_stock', 'cataloginventory/stock_item', 'is_in_stock', 'product_id=entity_id', '(' . join(') OR (', $cond) . ')' );
Ou você pode tentar isso
$manageStock = Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK); $cond = array( '{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=1 AND {{table}}.is_in_stock=0', '{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=0', ); if ($manageStock) { $cond[] = '{{table}}.is_in_stock=0'; $collection->joinField( 'inventory_in_stock', 'cataloginventory/stock_item', 'is_in_stock', 'product_id=entity_id', '(' . join(') OR (', $cond) . ')' );
Não tenho certeza 100%.
O trecho de código a seguir retornará os produtos de uma categoria com status 'Ativar', Visibilidade 'catálogo, pesquisa' e Disponibilidade de estoque 'Esgotado'.
$productDetails = Mage::getModel('catalog/category')->load($cat_id)
->getProductCollection()
->addAttributeToSelect('*');
$productDetails->addAttributeToFilter('visibility', 4);
$productDetails->addAttributeToFilter('status', 1);
$productDetails->joinField('is_in_stock',
'cataloginventory/stock_item',
'is_in_stock',
'product_id=entity_id',
'is_in_stock=0',
'{{table}}.stock_id=1',
'left');