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