Magento "Product Status Update" event is not triggered - events

I'm working on an extension that will receive product information from Magento when saved and do custom processing on the product.
I've spent 2 days until now trying to figure out why Magento is not triggering the event "catalog_product_status_update".
Simply, I change product status by going to Catalog->Manage Products, then select one or more products and use the "Actions" field above the products grid to change product(s) status to "disabled".
When I do that, the product(s) status changes just fine, but the problem is that I don't receive the event for it.
Here's the code I use:
<?xml version="1.0"?>
<config>
<global>
<models>
<mage4ucustomredirect>
<class>Mage4u_Customredirect</class>
</mage4ucustomredirect>
</models>
<events>
<catalog_product_save_after>
<observers>
<abc>
<type>singleton</type>
<class>Mage4u_Customredirect_Model_Observer</class>
<method>on_catalog_product_save_after</method>
</abc>
</observers>
</catalog_product_save_after>
<catalog_product_status_update>
<observers>
<abc>
<type>singleton</type>
<class>Mage4u_Customredirect_Model_Observer</class>
<method>on_catalog_product_status_update</method>
</abc>
</observers>
</catalog_product_status_update>
</events>
</global>
</config>
And this is the observer:
class Mage4u_Customredirect_Model_Observer
{
public function on_catalog_product_status_update(Varien_Event_Observer $observer)
{
Mage::log( "on_catalog_product_status_update" );
}
public function on_catalog_product_save_after(Varien_Event_Observer $observer)
{
Mage::log( "on_catalog_product_save_after" );
}
}
?>
Strange enough, when I try to save a product manually, I receive the event "on_catalog_product_save_after" which tells me that my code is working fine, but it doesn't work for this "on_catalog_product_status_update" event.
Any help is appreciated!
NOTE: I'm using Magento v1.6.2.0

I believe your problem is that the update status option at the top of the grid doesn't use any models to achieve the task, it access the database directly. If you look at the updateAttributes method in Mage_Catalog_Model_Product_Action and Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Action respectively, you will see that no product or product_status model is loaded.
Unfortunately for you, at a quick glance I don't see any events that you can hook into to capture this. It might require rewriting of the model.

Your two observers have the same name "abc". This should be unique inside Magento observers list.
Try changing one of them to "abc1", refresh your cache and it should work.

This question was asked somewhere in 2012, but in more recent Magento versions, the mass action update for the product grid is processed by the catalog/product_action model its updateAttributes method:
Mage_Catalog_Model_Product_Action::updateAttributes()
An event is dispatched there:
Mage::dispatchEvent('catalog_product_attribute_update_before', array(
'attributes_data' => &$attrData,
'product_ids' => &$productIds,
'store_id' => &$storeId
));
attributes_data is a key-value list with data to be stored for product_ids in the store_id scope. In your observer for catalog_product_attribute_update_before you can check if the status attribute is being updated:
$event = $observer->getEvent();
$attributesData = $event->getData('attributes_data');
if (! isset($attributesData['status'])) {
// we are not updating the status
return;
}
// do something, for example - if the product will be disabled
if ($attributesData['status'] != Mage_Catalog_Model_Product_Status::STATUS_ENABLED) {
// api call
}
Hope this helps for anyone who tries to intercept a mass status update.

Related

Firing event on product duplication

What I want to do is to empty the custom 'EAN' field of a product that gets copied in the backend. So as soon as the user hits 'copy' on an item the new items EAN field should be empty.
I found the magento event 'product_duplicate_attributes' but I am not sure if its what I need. Is there any way to fire an event if a product gets duplicated or maybe an even simpler solution to this problem.
Thanks in advance for any ideas.
(A): The field that should become empty, (B): Trigger event on save.
I found a solution to my problem:
etc/config.xml:
<models>
<ledscom_eanremover>
<class>LedsCom_EanRemover_Model</class>
</ledscom_eanremover>
</models>
</global>
<adminhtml>
<events>
<catalog_model_product_duplicate><!-- Observe product duplication. -->
<observers>
<ledscom_eanremover>
<class>ledscom_eanremover/observer</class>
<method>removeEan</method>
</ledscom_eanremover>
</observers>
</catalog_model_product_duplicate>
</events>
</adminhtml>
Model/Observer.php
<?php
class LedsCom_EanRemover_Model_Observer{
public function removeEan($observer){
$new_product = $observer->getEvent()->getNewProduct(); // Get new product from event-observer.
$new_product->setData('ean', null); // Remove the ean of the new product.
}
}
I am listening to the 'catalog_model_product_duplicate' event and remove the ean of the duplicated product.

How do I access an eav attribute field defined and marked up in the billing step of Magento checkout?

I need to access it in an observer just before collectTotals() is run. I'm using the sales_quote_collect_totals_before observer and it seems to be doing everything else I need it to do. I want to be able to access this attribute when the event is triggered
You can use this sales_quote_address_collect_totals_before event in your module. like this:
<events>
<sales_quote_address_collect_totals_before>
<observers>
<namespace_your_modulename_custom_event>
<class>your_observer_class</class>
<method>yourObserverMethod</method>
</namespace_your_modulename_custom_event>
</observers>
</sales_quote_address_collect_totals_before>
</events>
In your observer model the method should look like this:
public function yourObserverMethod(Varien_Event_Observer $observer)
{
// code goes to here
}

how to make magento filter works like category

I would like to have the categories in magento made use of the attributes/filter.
Let say I have an attribute "CupAttr" which is a NOT used in layered navigation. Then I create a category called CupCat, and it uses the "CupAttr" to pull products to display them within the CupCat category.
is that possible? The reason why i want to do this is I want to minimize the maintenance of categorizing products.
Thanks
EDITED:
Amit's solution works perfectly, but that bring in another issue. the products showing in the list is different from the products can be filtered from the layered navigation.
I actually need to select all products for any category (because i won't add any products to any category, they are all blank), then i start filter the products for that specific category by attribute.
thanks again.
In this case,you can use magento event/observer.
Hook an observer on event catalog_block_product_list_collection.
Then using addAttributeToFilter('CupAttrAttibiteCode'); filter the collection by CupAttr.
config.xml code:
<?xml version="1.0"?>
<config>
<global>
<models>
<xyzcatalog>
<class>Xyz_Catalog_Model</class>
</xyzcatalog>
</models>
<events>
<catalog_block_product_list_collection> <!-- event -->
<observers>
<xyz_catalog_block_product_list_collection>
<type>singleton</type>
<class>Xyz_Catalog_Model_Observer</class>
<method>apply_CupAttr_filter</method>
</xyz_catalog_block_product_list_collection>
</observers>
</catalog_block_product_list_collection>
</events>
</global>
</config>
Observer code location:
Create the directory structure - app/code/local/Xyz/Catalog/Model/Observer.php
First "CupAttr" which is used in prouct listing for use this attribute to filtering
<?php
class Xyz_Catalog_Model__Observer
{
public function __construct()
{
}
public function apply_CupAttr_filter($observer){
//apply filter when category is CupCat
if(Mage::registry('current_category') &&(Mage::registry('current_category')->getId()=='CupCatCatrgoryId') ):
$collection=$observer->getEvent()->getCollection();
$collection->addAttributeToFilter('CupAttrAttibiteCode','FilterExpression');
endif;
return $this;
}
}

Disable 'General' group sales in Magento

I'm looking to disable sales on our Magento site for any customers in the 'General' customer group. We have a tiered customer group system setup, with different tax rules etc., but I can't figure out how to disable 'general' as a group that can purchase from the site. I don't want new customers signing up able to purchase without being assigned a group first.
Thanks.
Here is my idea: set up observer on controller_action_predispatch_checkout_onepage_index event, which will fire before checkout page is loaded. In observer we check if customer belongs to certain group and if so we redirect him to cart page and show error message.
Translated to Magento code, it would look like this:
Firs we hook on the event in our config.xml
<frontend>
<events>
<controller_action_predispatch_checkout_onepage_index>
<observers>
<your_module>
<class>your_module/observer</class>
<method>banCheckout</method>
</your_module>
</observers>
</controller_action_predispatch_checkout_onepage_index>
</events>
</frontend>
and in our observer:
public function banCheckout(Varien_Event_Observer $observer)
{
$customerSession = Mage::getSingleton('customer/session');
if (!$customerSession->isLoggedIn()) {
return $this;
}
$groupId = $customerSession->getCustomer()->getGroupId();
if ($groupId == 1) {
Mage::getSingleton('checkout/session')->addError(
Mage::helper('checkout')->__('Your error message.')
);
$action = $observer->getEvent()->getControllerAction();
$action->getResponse()->setRedirect(Mage::getUrl('checkout/cart'));
$action->setFlag('', Mage_Core_Controller_Varien_Action::FLAG_NO_DISPATCH, true);
}
return $this;
}
Keep in mind this is just an example, and a pretty simple one.

How to set observer for monitoring customer in magento?

I want the following things
1.If customer already exist dnt save(0)
2.If customer is new then save it save(1)
3.If customer information change then save with update status save(2)
where save is a function,
In this case what should be the events.
Need solution.
I guess
customer_register_success
customer_save_after
adminhtml_customer_save_after
etc. please help
If you check the code lines around line 332 in app/code/core/Mage/Customer/controllers/AccountController.php :
if (true === $validationResult) {
$customer->save();
Mage::dispatchEvent('customer_register_success',
array('account_controller' => $this, 'customer' => $customer)
);
You will see that customer_register_success if fired after $customer->save(), so makes no sense to observe both in this case.
If you set up your observer in config.xml in the "global" node, it will observe front- and backend, no need for the adminhtml event :
<global>
<events>
<customer_save_after>
<observers>
.... your custom code, i assume you know how to deal with it...
</observers>
</customer_save_after>
</events>
</global>

Resources