Page Créer une catégorie qui affiche tous les produits à prix spécial

12

Fondamentalement, j'ai créé une catégorie «Produits en vente», que je voudrais automatiquement contenir tous les produits de mon catalogue auxquels un prix spécial leur a été appliqué (via Catalogue> Gérer les produits). Je voudrais que la page conserve les capacités de navigation et de tri en couches que contient une page de catégorie Magento standard.

Il semble que ce soit quelque chose qui serait précieux pour la majorité des utilisateurs de Magento, et je suis surpris qu'il ne soit pas inclus dans la fonctionnalité de base.

J'ai essayé plus d'une douzaine de réponses Stack Exchange, des articles de blog et des forums, et rien n'a fonctionné jusqu'à présent. Quelqu'un at-il une solution programmatique pour cela?

=== EDIT ===

Sur la base de la critique de @ pspahn dans les commentaires ci-dessous, j'ai décidé de poursuivre une autre méthode pour obtenir des fonctionnalités similaires. Cela dit, si vous êtes intéressé à poursuivre cette ligne, @ sander-mangel décrit une méthode qui semble tout à fait réalisable.

rokkor
la source
Il me semble que l'exigence de "contenir automatiquement tous les produits à prix spécial" est un peu excessive. Je suppose que le résultat final est que vous voulez une page avec des produits à prix spécial et que cela ressemble à une page de catégorie. Il semble que vous puissiez simplement créer votre propre modèle / collection (basé sur des produits avec un prix spécial) et utiliser cette collection dans des modèles basés sur les pages de vue de catégorie. Je ne vois tout simplement pas une catégorie qui est remplie automatiquement comme une bonne solution, par exemple, comment empêcher un utilisateur de la modifier?
pspahn
@pspahn Merci pour votre réponse. Je comprends votre critique et suis d'accord avec votre raisonnement. Je pourrais utiliser la méthode décrite par Sander Mangel avec un observateur category_save_after supplémentaire pour faire bonne mesure, mais cela semble exagéré. Je vais aller de l'avant avec une autre solution.
rokkor
@pspahn - Je ne comprends pas ce que vous voulez dire par «comment empêchez-vous un utilisateur de le modifier» - pouvez-vous expliquer un peu plus loin?
ProxiBlue
@ProxiBlue Fondamentalement, si vous créez une catégorie et que vous remplissez automatiquement de produits, un utilisateur administrateur peut simplement accéder à cette catégorie dans le backend et ajouter / supprimer des produits manuellement.
pspahn
@pspahn ok, avec l'utilisateur, j'ai mal compris en tant qu'utilisateur frontal.
ProxiBlue

Réponses:

8

La façon la plus simple de le faire est de créer une extension personnalisée qui fonctionne avec un observateur et un Cronjob.

Créez une catégorie pour les produits de vente. De cette façon, vous pouvez utiliser les fonctionnalités normales de Magento dans l'interface comme la navigation en couches, etc.

Pour obtenir automatiquement les produits de cette catégorie, nous utiliserons l'observateur et le cronjob. L'observateur observera l' catalog_product_save_afterévénement qui se déclenche lorsqu'un produit est enregistré dans le backend. Lorsque cela se produit , vous pouvez vérifier la special_price, special_price_fromdate et la special_date_todate pour déterminer si vous avez besoin de mettre le produit dans la catégorie des ventes ou le retirer de là.

Le cronjob est là pour les dates spéciales du et au. Chaque soir, après minuit, videz d'abord la catégorie de vente de tous les produits. Utilisez ensuite une collection pour récupérer tous les produits qui ont un prix spécial et qui entrent dans la promotion à partir de et jusqu'à ce jour. Si c'est le cas, déplacez-les vers cette catégorie de vente.

Sander Mangel
la source
7

La solution offerte par @SanderMangel est de premier ordre. Je peux aider à développer cela avec du code, que j'utilise actuellement dans mon module Produits de catégorie automatisés / dynamiques - qui a la capacité de faire des règles de catégorie de produits sur des produits spéciaux

Le code ajuste une collection de produits standard pour obtenir tous les produits avec un prix spécial, le jour de l'exécution du code. Vous pouvez l'utiliser dans le cron pour re-remplir les catégories à 00:00 et vous assurer qu'elles restent à jour.

Notez que le code est extrait d'un module plus grand, j'ai donc compacté les parties pertinentes ici pour vous. Il peut y avoir une ou deux variables qui ne sont pas représentées dans cet extrait, mais elles seraient faciles à déduire, ou simplement à demander :)

L'objet $ category est la catégorie réelle qui doit contenir les produits. Le code ci-dessous vous permettra également de spécifier la remise en% également :)

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

Maintenant, il est à noter que la collection ne renverra pas de produits, car elle contient des liens vers les tables de liens de produits catalogue <-> normales. Étant donné que vous n'êtes pas intéressé par les produits liés actuels, vous devez supprimer cette relation de table de la collection.

J'utilise le code suivant pour y parvenir:

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

en prime, vous pouvez utiliser la même teqnique pour ajuster la collection de produits du catalogue et trouver des produits qui sont en mode spécial en raison des règles du catalogue:

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

Une fois que vous avez la collection de travail, tout ce que vous avez à faire est d'obtenir tous les identifiants de la collection, de retourner le tableau et d'utiliser $category->setPostedProducts($products);et un $ category-> save () l; pour terminer la mise à jour.

Pour être complet, voici mon cron quotidien qui maintient les catégories dynamiques à jour. (encore une fois, cela fait référence à des méthodes non incluses ici, mais je suis sûr que cela vous mènera dans la bonne direction

S'amuser :)

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

réf: http://www.proxiblue.com.au/magento-dynamic-category-products.html

ProxiBlue
la source
5

Voici la collection qui devrait vous donner l'ensemble de résultats de tous les produits à prix spécial de votre catalogue que vous pouvez afficher sur une seule page

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

Il existe plusieurs façons de le faire, soit créer un nouveau module qui a son propre contrôleur, bloc et modèle très similaire au module de catégorie Mage ou vous remplacez le module de catégorie Mage pour exécuter uniquement la collection ci-dessus lorsque la catégorie spéciale est sélectionnée par le client. Cela peut être facilement configuré dans le système -> configuration de votre module.

Si vous pouvez dépenser peu, alors je recommanderais l'extension suivante sur Magento connect

Pour Magento 1 -:

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

Pour Magento 2 -:

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

J'espère que cela aide!

Cheers S

stevensagaar
la source
0

J'ai créé une extension pour Magento 2 qui affiche des produits spéciaux sous son propre contrôleur avec une navigation en couches. Donc pas besoin de catégorie ou de cron.

https://github.com/DominicWatts/Special

J'espère que cela aide quelqu'un

Dominic Xigen
la source