Página Criar Categoria, que exibe todos os produtos com Preços Especiais

12

Basicamente, criei uma categoria 'Produtos à venda', que gostaria de conter automaticamente todos os produtos no meu catálogo que tiveram um preço especial aplicado a eles (via Catálogo> Gerenciar produtos). Gostaria que a página retivesse os recursos de navegação e classificação em camadas que uma página padrão da categoria Magento contém.

Parece que isso é algo que seria valioso para a maioria dos usuários do Magento, e estou surpreso por não estar incluído como parte da funcionalidade principal.

Eu tentei mais de uma dúzia de respostas do Stack Exchange, postagens de blog e fóruns, e nada funcionou até agora. Alguém tem uma solução programática para isso?

=== EDIT ===

Com base na crítica do @ pspahn nos comentários abaixo, decidi seguir um método alternativo para obter funcionalidades semelhantes. Dito isto, se você estiver interessado em seguir essa linha, o @ sander-mangel descreve um método que parece totalmente viável.

rokkor
fonte
Parece-me que a exigência de "conter automaticamente todos os produtos com preços especiais" é um pouco excessiva. Suponho que o resultado final é que você deseja uma página com produtos com preços especiais e uma aparência de página de categoria. Parece que você pode criar seu próprio modelo / coleção (com base em produtos com um preço especial) e usar essa coleção em modelos com base nas páginas de exibição de categoria. Só não vejo uma categoria preenchida automaticamente como uma boa solução, por exemplo, como você evita que um usuário a modifique?
pspahn
@pspahn Obrigado pela sua resposta. Entendo sua crítica e concordo com seu raciocínio. Eu poderia utilizar o método descrito por Sander Mangel com um observador adicional category_save_after para uma boa medida, mas isso parece um exagero. Vou seguir em frente com uma solução alternativa.
Rokkor
@pspahn - Não entendo o que você quer dizer com 'como impedir que um usuário o modifique' - você pode explicar um pouco mais?
ProxiBlue
@ProxiBlue Basicamente, se você criar uma categoria e preencher automaticamente os produtos, um usuário administrador poderá simplesmente entrar nessa categoria no back-end e adicionar / remover produtos manualmente.
Psp2
@pspahn ok, com o usuário que eu entendi mal como usuário front-end.
ProxiBlue

Respostas:

8

A maneira mais fácil de fazer isso é criar uma extensão personalizada que funcione com um Observer e um Cronjob.

Crie uma categoria para os produtos de venda. Dessa forma, você pode usar as funcionalidades normais do Magento no frontend, como navegação em camadas, etc.

Para obter os produtos nessa categoria automaticamente, usaremos o observador e o cronjob. O observador observará o catalog_product_save_afterevento que é acionado quando um produto é salvo no back-end. Quando isso acontece, você pode verificar o special_price, special_price_fromdata e special_date_todata para determinar se você precisa colocar o produto na categoria de vendas ou removê-lo de lá.

O cronjob está lá para as datas especiais de e para. Todas as noites após a meia-noite, esvazie primeiro a categoria de vendas de todos os produtos. Em seguida, use uma coleção para recuperar todos os produtos que têm um preço especial e se enquadram no especial desde e até a data. Nesse caso, mova-os para esta categoria de vendas.

Sander Mangel
fonte
7

A solução oferecida pela @SanderMangel é de primeira qualidade. Posso ajudar a expandir isso com algum código, que atualmente uso no meu módulo Produtos de categoria automatizada / dinâmica - que tem a capacidade de executar regras de categoria de produtos em especial

O código ajusta uma coleção de produtos padrão para obter todos os produtos com preço especial definido, no dia em que o código é executado. Você pode usar isso no cron para preencher novamente as categorias às 00:00 e verifique se elas permanecem atualizadas.

Observe que o código é extraído de um módulo maior, portanto eu compactuei as partes relevantes aqui para você. Pode haver uma variável ou duas que não esteja representada nesse extrato, mas seria fácil deduzir ou simplesmente perguntar :)

O objeto $ category é a categoria real que deve conter os produtos. O código abaixo também permitirá que você especifique o desconto em um valor em% :)

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

Agora, observe que a coleção não retornará produtos, pois contém links para as tabelas de links de produtos do catálogo normal <->. Como você não está interessado nos produtos vinculados atuais, é necessário limpar a relação da tabela da coleção.

Eu uso o seguinte código para fazer isso:

/**
 * 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 um bônus adicional, você pode usar a mesma técnica para ajustar a coleção de produtos do catálogo e encontrar produtos que estão em modo especial devido às regras do 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);

Depois de ter a coleção de trabalho, tudo o que você precisa fazer é obter todos os IDs da coleção, inverter a matriz e usar $category->setPostedProducts($products);e $ category-> save () l; para concluir a atualização.

Para completar, eis o meu cron diário que mantém as categorias dinâmicas atualizadas. (mais uma vez, refere-se a métodos não incluídos aqui, mas tenho certeza de que o levará na direção certa

Diverta-se :)

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
fonte
5

Aqui está a coleção que deve fornecer o conjunto de resultados de todos os produtos com preços especiais em seu catálogo, que você pode exibir em uma 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;

Existem várias maneiras de fazer isso: criar um novo módulo com seu próprio controlador, bloco e modelo muito semelhante ao módulo de categoria Mage ou substituir o módulo de categoria Mage para executar apenas a coleção acima quando a categoria especial for selecionada pelo cliente. Isso pode ser facilmente configurado no sistema -> configuração do seu módulo.

Se você pode gastar alguns quid, então eu recomendaria a seguinte extensão no 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 que ajude!

Cheers S

stevensagaar
fonte
0

Criei uma extensão para o Magento 2, que exibe produtos especiais sob seu próprio controlador com navegação em camadas. Portanto, não há necessidade de categoria ou cron.

https://github.com/DominicWatts/Special

Espero que isso ajude alguém

Dominic Xigen
fonte