Como obter a coleção de produtos fora de estoque - ao contrário de addInStockFilterToCollection ()?

9

Tenho o requisito 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 os itens em estoque, mas não parece haver um método equivalente para filtrar itens fora de estoque - observei o Mage_CatalogInventory_Model_Stockmodelo, onde é definido o método mencionado acima.

Vi o exemplo a seguir 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 essa não é a única maneira de conseguir isso?

BrynJ
fonte

Respostas:

3

digamos que $collectioné sua coleção de produtos que você constrói assim:

$collection = Mage::getModel('catalog/product')->getCollection()
    ->...additional filters here...;

Agora faça isso em 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 esgotados:

$collection->getSelect()->where('stock_status.stock_status = ?', 0);
Marius
fonte
Isso funcionaria, independentemente das opções de configuração definidas para o inventário de cada produto? (Por exemplo, é um produto que não está de stock em estoque ou fora de estoque?)
BrynJ
Deve funcionar, porque a tabela de ações está indexada e leva em consideração todas as configurações possíveis. Você só precisa garantir que seu índice de ações esteja atualizado
Marius
Obrigado por confirmar. Parece uma boa abordagem "leve" para obter esses dados.
BrynJ 04/11
Usar a tabela de índice de status de estoque em vez da tabela de itens de estoque é realmente a melhor solução.
Fabian Schmengler
Eu tive que enviar o produto select como o primeiro argumento para a função Mage :: getModel ('cataloginventory / stock_status') -> addStockStatusToSelect ($ collection-> getSelect (), $ website);
Minlare 7/03
2

Seu exemplo não leva em consideração o valor de "use config".

Vamos dar uma olhada em como addInStockFilterToCollectionfunciona:

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 às seguintes condições:

  1. O produto não usa a configuração global E tem "gerenciar estoque" definido como "sim" E está em estoque

    OU

  2. O produto não usa a configuração global E "gerencia o estoque" definido como "não"

    OU

  3. O produto usa a configuração global E se a configuração global for "gerenciar estoque = sim", estiver em estoque

Você precisa inverter as condições da seguinte maneira:

  1. O produto não usa a configuração global E "gerencia o estoque" definido como "sim" E não está em estoque

    OU

  2. O produto usa a 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 marcado e altera a comparação para 0. As condições em que in_stock não está marcado ("gerenciar estoque" = "não") significa que o produto está sempre em estoque, independentemente do status do estoque , para não incluí-los em nossa consulta "fora de estoque".

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;
}
Fabian Schmengler
fonte
Ótima resposta detalhada. Então, você sugeriria criar um módulo para isso, para estender o Mage_CatalogInventory_Model_Stockmodelo?
precisa saber é o seguinte
11
Não é necessário reescrever ou estender. Você pode colocar esse método em qualquer lugar, pois ele não usa $this. Poderia muito bem ser função simples. Gostaria de criar um módulo separado e torná-lo um método auxiliar (ou se você precisa deste para outro módulo, adicioná-lo ao ajudante desse módulo)
Fabian Schmengler
1

O seguinte snippet de código retornará os produtos de uma categoria com status 'Ativar', Visibilidade 'catálogo, pesquisa' e Disponibilidade de estoque 'Fora de estoque'.

$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');
archana bahadur
fonte
0

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%.

Amit Bera
fonte
Obrigado @AmitBera. Você pode fornecer algum contexto para suas respostas e explicar as diferenças?
BrynJ