¿Cómo obtener la colección de productos de artículos agotados, al contrario de addInStockFilterToCollection ()?

9

Tengo el requisito de mostrar los productos de una categoría en dos listas: una para los artículos en stock y la otra para los artículos agotados.

Estoy usando

Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection()

para filtrar mi colección de productos para los artículos en stock, pero no parece haber un método equivalente para filtrar artículos fuera de stock: he examinado el Mage_CatalogInventory_Model_Stockmodelo, que es donde se define el método mencionado anteriormente.

He visto el siguiente ejemplo para recuperar productos agotados:

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

... pero seguramente esta no es la mejor forma de lograrlo?

BrynJ
fuente

Respuestas:

3

Digamos que esa $collectiones su colección de productos que construye así:

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

ahora haz esto a tu colección. Esto une la colección con la tabla de estado del stock.

$website = Mage::app()->getWebsite();
Mage::getModel('cataloginventory/stock_status')->addStockStatusToSelect($collection, $website);

Ahora puede filtrar los productos agotados:

$collection->getSelect()->where('stock_status.stock_status = ?', 0);
Marius
fuente
¿Funcionaría sin importar las opciones de configuración establecidas para el inventario de cada producto? (Por ejemplo, ¿es un producto que no está en stock gestionado en stock o agotado?)
BrynJ
Debería funcionar, porque la tabla de valores está indexada y tiene en cuenta todas las configuraciones posibles. Solo tiene que asegurarse de que su índice bursátil esté actualizado
Marius
Gracias por confirmar. Esto parece un buen enfoque "ligero" para obtener estos datos.
BrynJ
Usar la tabla de índice de estado de existencias en lugar de la tabla de artículos de existencias es, de hecho, la mejor solución.
Fabian Schmengler
Tuve que enviar el producto seleccionado como primer argumento a la función Mage :: getModel ('cataloginventory / stock_status') -> addStockStatusToSelect ($ colección-> getSelect (), $ sitio web);
Minlare
2

Su ejemplo no tiene en cuenta el valor de "use config".

Echemos un vistazo a cómo addInStockFilterToCollectionfunciona:

public function addInStockFilterToCollection($collection)
{
    $this->getResource()->setInStockFilterToCollection($collection);
    return $this;
}

OK, está delegando a otro 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;
}

Esto une la tabla de inventario con las siguientes condiciones:

  1. El producto no utiliza la configuración global Y tiene "administrar stock" establecido en "sí" Y está en stock

    O

  2. El producto no utiliza la configuración global Y tiene "administrar stock" establecido en "no"

    O

  3. El producto usa la configuración global Y si la configuración global es "administrar stock = sí", está en stock

Debe invertir las condiciones de la siguiente manera:

  1. El producto no utiliza la configuración global Y tiene "administrar stock" establecido en "sí" Y no está en stock

    O

  2. El producto utiliza la configuración global Y la configuración global es "administrar stock = sí" Y no está en stock

Explicación: Solo toma las condiciones en las que in_stock está realmente verificado y cambia la comparación a 0. Las condiciones en las que in_stock no está marcado ("administrar stock" = "no") significan que el producto siempre está en stock, independientemente del estado del stock , por lo que no los incluimos en nuestra consulta "agotado".

Entonces este es tu 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
fuente
Gran respuesta detallada. ¿Entonces sugeriría crear un módulo para esto, para extender el Mage_CatalogInventory_Model_Stockmodelo?
BrynJ
1
No reescribir o extender. Puede colocar este método en cualquier lugar ya que no se usa $this. También podría ser una función simple. Crearía un módulo separado y lo convertiría en un método auxiliar (o si lo necesita para otro módulo, agréguelo al auxiliar de ese módulo)
Fabian Schmengler
1

El siguiente fragmento de código le devolverá los productos de una categoría que tenga el estado 'Habilitar', Visibilidad 'catálogo, búsqueda' y Stock Disponibilidad 'Agotado'.

$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
fuente
0

Puedes probar esto.

 $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) . ')'
        );

O puedes probar esto

  $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) . ')'
        );

No estoy seguro al 100%.

Amit Bera
fuente
Gracias @AmitBera. ¿Puede proporcionar un contexto para sus respuestas y explicar las diferencias?
BrynJ