Página Crear categoría que muestra todos los productos de precios especiales

12

Básicamente, he creado una categoría 'Productos en oferta', que me gustaría que contenga automáticamente todos los productos en mi catálogo a los que se les haya aplicado un Precio especial (a través del Catálogo> Gestionar productos). Me gustaría que la página conserve las capacidades de clasificación y navegación por capas que contiene una página estándar de categoría de Magento.

Parece que esto es algo que sería valioso para la mayoría de los usuarios de Magento, y me sorprende que no esté incluido como parte de la funcionalidad principal.

He probado más de una docena de respuestas de Stack Exchange, publicaciones de blog y foros, y hasta ahora nada ha funcionado. ¿Alguien tiene una solución programática para esto?

=== EDITAR ===

Basado en la crítica de @ pspahn en los comentarios a continuación, he decidido seguir un método alternativo para lograr una funcionalidad similar. Dicho esto, si está interesado en seguir esta línea, @ sander-mangel describe un método que parece completamente factible.

rokkor
fuente
Me parece que el requisito de "contener automáticamente todos los productos con precios especiales" es un poco excesivo. Supongo que el resultado final es que desea una página con productos con precios especiales y que parezca una página de categoría. Parece que en su lugar podría crear su propio modelo / colección (basado en productos con un precio especial) y usar esa colección en plantillas basadas en las páginas de vista de categoría. Simplemente no veo una categoría que se complete automáticamente como una buena solución, por ejemplo, ¿cómo evita que un usuario la modifique?
pspahn
@pspahn Gracias por su respuesta. Entiendo tu crítica y estoy de acuerdo con tu razonamiento. Podría utilizar el método descrito por Sander Mangel con un observador adicional de category_save_after por si acaso, pero parece una exageración. Seguiré adelante con una solución alternativa.
rokkor
@pspahn: no entiendo a qué te refieres con "cómo evitas que un usuario lo modifique", ¿puedes explicar un poco más?
ProxiBlue
@ProxiBlue Básicamente, si crea una categoría y llena los productos automáticamente, un usuario administrador puede simplemente ingresar a esa categoría en el backend y agregar / eliminar productos manualmente.
pspahn
@pspahn ok, con el usuario entendí mal como usuario front-end.
ProxiBlue

Respuestas:

8

La forma más fácil de hacer esto es crear una extensión personalizada que funcione con un Observador y un Cronjob.

Cree una categoría para los productos de ventas. De esta manera, puede utilizar las funcionalidades normales de Magento en la interfaz como navegación en capas, etc.

Para obtener los productos en esta categoría automáticamente, utilizaremos el observador y el cronjob. El observador observará el catalog_product_save_afterevento que se desencadena cuando un producto se guarda en el back-end. Cuando esto sucede se puede comprobar la special_price, special_price_fromfecha y special_date_tofecha a determinar si es necesario poner el producto en la categoría de ventas o sacarlo de allí.

El cronjob está ahí para las fechas especiales desde y hasta. Todas las noches después de la medianoche, primero vacíe la categoría de ventas de todos los productos. Luego, use una colección para recuperar todos los productos que tienen un precio especial y que están dentro del especial desde y hasta la fecha. Si es así, muévalos a esta categoría de ventas.

Sander Mangel
fuente
7

La solución ofrecida por @SanderMangel es de primera categoría. Puedo ayudar a ampliar esto con algún código, que actualmente uso en mi módulo Productos de categoría automatizados / dinámicos, que tiene la capacidad de hacer reglas de categoría de productos en productos especiales

El código ajusta una colección de productos estándar para obtener todos los productos con un precio especial establecido, el día que se ejecuta el código. Puede usar esto en el cron para volver a llenar las categorías a las 00:00 y asegurarse de que se mantengan actualizadas.

Tenga en cuenta que el código se extrae de un módulo más grande, por lo tanto, he compactado las partes relevantes aquí para usted. Puede haber una variable o dos que no están representadas en este extracto, pero serían fáciles de deducir, o simplemente preguntar :)

El objeto $ category es la categoría real que debe contener los productos. El código a continuación también le permitirá especificar el descuento en un valor de% :)

$collection = $category->getProductCollection();

$todayDate = Mage::app()->getLocale()->date()->toString(Varien_Date::DATE_INTERNAL_FORMAT);
$collection->addAttributeToFilter(array(
    array(
        'attribute' => "special_to_date",
        'null' => true
    ),
    array(
        'attribute' => "special_to_date",
        'from' => $todayDate,
        //'to'      => $todayDate,
        'date' => true
    )
));
$collection->addAttributeToFilter(array(
    array(
        'attribute' => "special_from_date",
        'null' => true
    ),
    array(
        'attribute' => "special_from_date",
        //'from'    => $todayDate,
        'to' => $todayDate,
        'date' => true
    )
));

$collection->addAttributeToSelect('special_price','left');
$collection->addAttributeToSelect('price','left');
$select = $collection->getSelect();

if (strpos($value, '%') > 0) {
    $value = str_replace('%', '', $value);
    $select->where('( 100 - (( at_special_price.value * 100 ) / at_price.value ) )  ' . $operator . ' ' . $value);
} else {
    $select->where('((at_price.value - at_special_price.value)) ' . $operator . ' ' . $value);
}

Ahora, hay que tener en cuenta que la colección no devolverá productos, ya que contiene enlaces a las tablas normales de enlaces de productos del catálogo <->. Como no está interesado en los productos vinculados actuales, debe borrar esa relación de tabla de la colección.

Yo uso el siguiente código para hacerlo:

/**
 * Remove Catalog Product Link elements from collection
 * 
 * @param type $collection
 * @return type
 */
public function removeCatProPart($collection)
{
    $select = $collection->getSelect();
    $fromPart = $select->getPart(Zend_Db_Select::FROM);
    $select->reset(Zend_Db_Select::FROM);

    if (array_key_exists('cat_pro', $fromPart)) {
        unset($fromPart['cat_pro']);
        // also remove any reference to the table in the rest of the query
        $columns = $select->getPart(Zend_Db_Select::COLUMNS);
        $columnRemoved = false;
        foreach ($columns as $columnKey => $column) {
            if ($column[0] == 'cat_pro') {
                unset($columns[$columnKey]);
                $columnRemoved = true;
            }
        }

        if ($columnRemoved) {
            $select->setPart(Zend_Db_Select::COLUMNS, $columns);
        }

        $orderPart = $select->getPart(Zend_Db_Select::ORDER);
        $orderRemoved = false;
        foreach ($orderPart as $orderKey => $order) {
            if ($order[0] == 'cat_pro') {
                unset($orderPart[$orderKey]);
                $orderRemoved = true;
            }
        }

        if ($orderRemoved) {
            $select->setPart(Zend_Db_Select::ORDER, $orderPart);
        }
    }
    $select->setPart(Zend_Db_Select::FROM, $fromPart);
    return $collection;
}

Como beneficio adicional, puede usar la misma técnica para ajustar la colección de productos del catálogo y encontrar productos que están en modo especial debido a las reglas del catálogo:

$storeDate = Mage::app()->getLocale()->storeTimeStamp($this->getStoreId());
$value = $this->getValue();
$conditions = 'price_rule.product_id = e.entity_id AND ';
$conditions .= "(from_time = 0
    OR from_time <= " . $storeDate . ")
    AND (to_time = 0
    OR to_time >= " . $storeDate . ") AND ";
$conditions .= "price_rule.rule_id IN (" . $value . ")";
$collection->getSelect()->joinInner(
        array('price_rule' => $collection->getTable('catalogrule/rule_product')), $conditions);
$collection->setFlag('applied_catalog_rule_id', true);
$collection->setFlag('applied_rule', true);

Una vez que tenga la colección de trabajo, todo lo que necesita hacer es obtener todos los identificadores de la colección, voltear la matriz y usar $category->setPostedProducts($products);y una $ category-> save () l; para completar la actualización.

Para completar, aquí está mi cron diario que mantiene las categorías dinámicas actualizadas. (de nuevo, se refiere a métodos no incluidos aquí, pero estoy seguro de que lo llevará en la dirección correcta

Que te diviertas :)

public static function rebuildAllDynamic($schedule)
{
    try {
        $tempDir = sys_get_temp_dir() . "/";
        $fp = fopen($tempDir . "dyncatprod_rebuild.lock", "w+");
        if (flock($fp, LOCK_EX | LOCK_NB)) {
            if (Mage::getStoreConfig('dyncatprod/debug/enabled')) {
                   mage::log("DynCatProd - rebuildAllDynamic");
            }
            if (!Mage::getStoreConfig('dyncatprod/rebuild/max_exec')) {
                ini_set('max_execution_time', 3600); // 1 hour
            }
            $categories = Mage::getModel('catalog/category')
                ->getCollection()
                ->addAttributeToSelect('*')
                ->addIsActiveFilter()
                ->addAttributeToFilter('dynamic_attributes', array('notnull' => true));

            foreach ($categories as $category) {
                $products = Mage::helper('dyncatprod')->getDynamicProductIds($category);
                if (is_array($products)) {
                    if (Mage::getStoreConfig('dyncatprod/debug/enabled')) {
                        mage::log("rebuilding :" . $category->getName() . ' ' . $category->getPath() );
                    }
                    $products = array_flip($products);
                    $category->setPostedProducts($products);
                    $category->setIsDynamic(true);
                    $category->save();
                }
            }
            flock($fp, LOCK_UN); 
            unlink($tempDir . "dyncatprod_rebuild.lock");
        } else {
            mage::log('Could not execute cron for rebuildAllDynamic -file lock is in place, job may be running');
        }
    } catch (Exception $e) {
        flock($fp, LOCK_UN); 
        unlink($tempDir . "dyncatprod_rebuild.lock");
        mage::logException($e);
        return $e->getMessage();
    }
}

ref: http://www.proxiblue.com.au/magento-dynamic-category-products.html

ProxiBlue
fuente
5

Aquí está la colección que debe proporcionarle el conjunto de resultados de todos los productos con precios especiales en su catálogo que puede mostrar en una página

$collection = Mage::getResourceModel('catalog/product_collection')
    ->addAttributeToSelect('price')
    ->setStoreId($this->getStoreId());

$date = strtotime(date('Y-m-d')); $current_date = date("Y-m-d hh:mm:ss",$date);

$collection = $collection
    ->addAttributeToFilter('price',
        array('gt'=>0))
    ->addAttributeToFilter('visibility',
        array('neq'=>Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE));

if (Mage::getStoreConfigFlag(Mage_Catalog_Helper_Product_Flat::XML_PATH_USE_PRODUCT_FLAT, $this->getStoreId())){
    $collection = $collection->addAttributeToFilter('special_price',array('lt'=>new Zend_Db_Expr('e.price')));
}
else{
    $collection = $collection->addAttributeToFilter(array(
        array('attribute'=>'special_price','lt'=>new Zend_Db_Expr('at_price.value'))
    ));
}

$collection = $collection->addAttributeToFilter(array(
        array('attribute'=>'special_from_date','lteq'=>$current_date),
        array('attribute'=>'special_from_date','eq'=>''),
        array('attribute'=>'special_from_date','null'=>true)
    ),'','left')
    ->addAttributeToFilter(array(
        array('attribute'=>'special_to_date','gteq'=>$current_date),
        array('attribute'=>'special_to_date','eq'=>''),
        array('attribute'=>'special_to_date','null'=>true)
            ),'','left');

$collection->getSelect()->group('e.entity_id');

return $collection;

Puede hacer esto de varias maneras, ya sea creando un nuevo módulo que tenga su propio controlador, bloque y modelo muy similar al módulo de categoría Mage o anule el módulo de categoría Mage para ejecutar solo la colección anterior cuando el cliente selecciona una categoría especial. Esto se puede configurar fácilmente en el sistema -> configuración de su módulo.

Si puede gastar poco, entonces recomendaría la siguiente extensión en Magento connect

Para Magento 1 -:

http://www.magentocommerce.com/magento-connect/dynamic-sale-category.html ( http://www.scommerce-mage.co.uk/magento-dynamic-sale-category.html )

Para Magento 2 -:

https://www.scommerce-mage.com/magento2-dynamic-sale-category.html

¡Espero eso ayude!

Saludos S

stevensagaar
fuente
0

Creé una extensión para Magento 2 que muestra productos en especial bajo su propio controlador con navegación por capas. Entonces no hay necesidad de categoría o cron.

https://github.com/DominicWatts/Special

Espero que esto ayude a alguien

Dominic Xigen
fuente