Magento - catalog_product_save_after: Check if product has been saved - magento

I am currently trying to save a product with attributes that I have built, and it's working fine. I have also set up my code to call the catalog_product_save_after function on my observer, as shown below:
class Package_MyModule_Model_Observer
{
public function catalog_product_save_after($observer)
{
$product = $observer->getProduct();
//Do stuff here
}
}
In this line of code here, is there a way to detect whether the product has already been saved (i.e. no error messages were shown)? Because I need to update some values in the database when the product is saved successfully.

Mostly this gets called after product is saved successfully, but to be sure you can hook into
catalog_product_save_commit_after

Related

magento target rule not applying to a specific product

A simple product is in specific category other products have that rule applied.This is happening on magento enterprise 1.13.0.1 version.
A rule is applicable to that category but when I look in catalogrule_product table then there is no entry for that product. This means no rule applies to that product.
http://www.solvingmagento.com/quick-tip-magento-catalog-price-rules-dont-work/ is the link I refered.
I want to know if for some reason a product has no target rules applied then:
1. Is there no cron job that will handle this and populate catalogrule_product table.
If yes then which cron job does this.
Also when we saved product its expected that catalog_product_save_after event should get fired resulting in Mage_CatalogRule module’s observer method applyAllRulesOnProduct getting executed but still no luck.
When I click via admin apply rule then it works.
I want to know is has magento not provided any cron job/indexer to handle this.
Thanks in Advance.
If you are creating products outside of the magento backend (using php, or soap) you may have to use the following code after you have called the $product->save() method...
public function applyActiveRulesToProduct($productId)
{
try {
$product = Mage::getModel('catalog/product') -> load($productId);
$rules = Mage::getModel('catalogrule/rule')->getCollection()->addFieldToFilter('is_active', 1);
foreach ($rules as $rule) {
$rule->applyAllRulesToProduct($product);
}
return "Applied rules to " . $productId;
} catch (Exception $e) {
return $e->getMessage();
}
}
It is code that i wrote for my own soap api extension. I could not get the rules to apply using applyToProduct(product, websiteIds) but using applyAllRulesToProduct with filters on the rules array seems to do the trick.
FYI, this code is buried inside of the CatalogRule.Rule.php core code as well, but it cannot be called directly using the rule model or product model. Who knows why they did that.

Can't able to set the product attribute programmatically in magento through observer

I want to update the products description attribute after the product save.so for this i am using the observer called catalog_product_save_after and depending on some condition i create the description for the product and i will save the description of the products by following code
product->setDescription();
product->save();
the problem is when i am calling the product->save(); the site is loading and loading later i found that product->save(); this function is again calling the catalog_product_save_after. that's why it is going into the infinite loop.
Please help me to set the description for the product.
Option 1:
You can use catalog_product_save_before and just use $product->setDescription('something') (without the save).
Option 2
Make your observer run only once.
function doSomething($observer) {
//some code here
$id = $product->getId();
if (!Mage::registry('observer_already_executed_'.$id)) {
//do your magic here
Mage::register('observer_already_executed_'.$id, 1);
}
}

How to override save() method in a component

Where and how I am overriding the save method in Joomla 3.0 custom component ?
Current situation:
Custom administrator component.
I have a list view that displays all people stored in table.
Clicking on one entry I get to the detailed view where a form is loaded and it's fields can be edited.
On save, the values are stored in the database. This all works fine.However, ....
When hitting save I wish to modify a field before storing it into the database. How do I override the save function and where? I have been searching this forum and googled quiet a bit to find ways to implement this. Anyone who give me a simple example or point me into the right direction ?
Thanks.
Just adding this for anyone who wants to know the answer to the question itself - this works if you explicitly wish to override the save function. However, look at the actual solution of how to manipulate values!
You override it in the controller, like this:
/**
* save a record (and redirect to main page)
* #return void
*/
function save()
{
$model = $this->getModel('hello');
if ($model->store()) {
$msg = JText::_( 'Greeting Saved!' );
} else {
$msg = JText::_( 'Error Saving Greeting' );
}
// Check the table in so it can be edited.... we are done with it anyway
$link = 'index.php?option=com_hello';
$this->setRedirect($link, $msg);
}
More details here: Joomla Docs - Adding Backend Actions
The prepareTable in the model (as mentioned above) is intended for that (prepare and sanitise the table prior to saving). In case you want to us the ID, though, you should consider using the postSaveHook in the controller:
protected function postSaveHook($model, $validData) {
$item = $model->getItem();
$itemid = $item->get('id');
}
The postSaveHook is called after save is done, thus allowing for newly inserted ID's to be used.
You can use the prepareTable function in the model file (administrator/components/yourComponent/models/yourComponent.php)
protected function prepareTable($table)
{
$table->fieldname = newvalue;
}

How do order statuses/states work in Magento 1.4.x

As far as I understand Magento have various order statuses under global/sales/order/statuses which can be altered by either copying app/code/core/Mage/Sales/etc/config.xml to local scope or overriding it with your custom module.
There are also global/sales/order/states defined in the same file and as far as I understand states are something like statuses groups. Only states (not statuses) can be set at the order status in magento and statuses are something like states subdivisions. So in administrator interface you can change statuses of a placed order but you can't change state from the order status drop-down (you can change it by either invoicing the client or canceling the order).
As far as I understand you can easily add a new status to your Magento but can't add new state as states are somehow hardcoded with the rest or Magento order processing logic. I really hope that I'm wrong.
Please correct me if I'm wrong in any point as these are just my thoughts and it might be quite far from real Magento 1.4.x flow.
I'm quite sure that 'state' is free data, it can be set to ANY value using the setData option on an order instance. So if you write a custom module that can load an order, set data to one of your new 'states' and test with what ever custom logic you require.
$order = Mage::getModel('sales/order')->load(1);
$order->setData('state','myCustomState');
$order->setData('status','onCustomState');
echo $order->getState()
// Returns myCustomState
its worth bearing in mine that CLOSED/CANCELLED are protected states, so trying to use $order->setState('my_state') will fail on those order, but shouldn't fail on setData so you can overwrite a closed or cancelled order with this method.
if you were to overwrite the order model with a custom one you could add your own logic such as isOnCustomState() and allow the order to be handled in any way just by loading by id.
To add 'custom logic' to your order you could do something copy app\code\core\Mage\Sales\Model\Order.php into your local folder, then you can add functions into that model,
public function isActive(){ if($this->getState() == 'active'){ return true; } else { return false; }
public function isInActive(){ if($this->getState() == 'deactivated'){ return true; } else { return false; }
public function activate(){
if(!$this->isActive()){
$this->setData('state','active');
$this->setData('status','Active Subscription');
// some custom code to start a recuring payment
return $this;
}
}
public function deactiveate(){
if(!$this->isInActive()){
$this->setData('state','deactivated');
$this->sendOrderUpdateEmail(true,'Your subscription has been deactivated.');
// some custom code to stop a recuring payment
return $this;
}
}
now you can load an order and set activate or deactivate on that order to fire your custom code,
$order = Mage::getModel('sales/order')->load(1)->activate();
this code is all untested and just an example of somethings you could try, please don't just dump this code in your model and expect it to work perfectly. in code\core\Mage\Sales\etc\config.xml in the nodes sales/order/states add
<activated translate="label">
<label>Active Subscription</label>
<statuses>
<pending default="1"/>
</statuses>
<visible_on_front/>
</activated>
Magento Order is a finite state machine.
Therefore when you define status it would automatically try to define its state. Altering state directly is not recommended.
When you define status it checks various flags for shipment and invoices and depending in all those it would get the right state. Once order is in approved state however you can easily change status regardless of if there is invoice or any flag etc.

Help with Magento and related products

I have a customer product page that literally lives beside the catalog/product/view.phtml page. It's basically identical to that page with a few small exceptions. It's basically a 'product of the day' type page so I can't combine it with the regular product page since I have to fetch the data from the DB and perform a load to get the product information
$_product = Mage::getModel('catalog/product')->load($row['productid']);
To make a long story short, everything works (including all children html blocks) with the singular exception of the related products.
After the load I save the product into the registry with
Mage::register('product', $_product);
and then attempt to load the related products with:
echo $this->getLayout()->createBlock('catalog/product_view')->setTemplate('catalog/product/list/related.phtml')->toHtml();`
All of which give back the error:
Fatal error: Call to a member function getSize() on a non-object in catalog/product/list/related.phtml on line 29`,
and line 29 is
<?php if($this->getItems()->getSize()): ?>`.
Any help getting the relateds to load would be appreicated.
I didn't quite follow what you're trying to do, but I know why you're getting your errors. You're creating a block whose class-alias/class is
catalog/product_view
Mage_Catalog_Block_Product_View
but you're setting this block's template as
catalog/product/list/related.phtml
The stock catalog/product/list/related.phtml template was built to be used with a catalog/product_list_related Block only, and not a catalog/product_view Block.
If you take a look at the class definition for a catalog/product_list_related Block (which is a Mage_Catalog_Block_Product_List_Related), you can see that there's a getItems() method.
public function getItems()
{
return $this->_itemCollection;
}
which returns a collection. The collection is set in the _prepareData method
protected function _prepareData()
{
$product = Mage::registry('product');
/* #var $product Mage_Catalog_Model_Product */
$this->_itemCollection = $product->getRelatedProductCollection()
...
This collection is never set with a catalog/product_view Block, which is why you're getting your errors.
In your code above, if you switch to creating a catalog/product_list_related block, your errors should go away.
public function relatedproductsAction(){
$this->loadLayout();
$relatedBlock = "";
$rec_prod_id = Mage::getSingleton('checkout/session')->getLastAddedProductId(true);
$_product = Mage::getModel('catalog/product')->load($rec_prod_id);
Mage::register('product', $_product);
$relatedBlock = $this->getLayout()->createBlock('catalog/product_list_related')->setTemplate('catalog/product/related.phtml')->toHtml();
echo $relatedBlock;
exit;
}
Getting html of related block through ajax call, right after when product is added to cart. might be relatively helpful.

Resources