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?

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);

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;
}

Ó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');

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


Obrigado @AmitBera. Você pode fornecer algum contexto para suas respostas e explicar as diferenças?
— BrynJ
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.