Using Magento CE 1.8.x and I'm trying to get a custom product attribute to pass to order items to use behind the scenes. I've created the custom product attribute, qb_product_id in catalog > attributes > manage attributes
And then I created the following module:
config.xml
<?xml version="1.0"?>
<config>
<modules>
<Nellys_QBProductID>
<version>0.1.0</version>
</Nellys_QBProductID>
</modules>
<global>
<fieldsets>
<sales_convert_quote_item>
<qb_product_id>
<to_order_item>*</to_order_item>
</qb_product_id>
</sales_convert_quote_item>
<sales_convert_order_item>
<qb_product_id>
<to_quote_item>*</to_quote_item>
</qb_product_id>
</sales_convert_order_item>
</fieldsets>
<sales>
<quote>
<item>
<product_attributes>
<qb_product_id />
</product_attributes>
</item>
</quote>
</sales>
<events>
<sales_quote_item_set_product>
<observers>
<Nellys_QBProductID>
<class>Nellys_QBProductID_Model_Observer</class>
<method>setQbProductId</method>
</Nellys_QBProductID>
</observers>
</sales_quote_item_set_product>
</events>
</global>
</config>
Observer.php
<?php
class Nellys_QBProductID_Model_Observer extends Varien_Event_Observer
{
public function setQbProductId(Varien_Event_Observer $observer) {
$item = $observer->getQuoteItem();
$product = $observer->getProduct();
$item->setQbProductId($product->getQbProductId());
return $this;
}
}
?>
It doesn't seem to be outputting qb_invoice_id when I dump the order items information. Any idea where I went wrong? I've cleared my var/cache folder and reindexed everything, but still not showing up on the order items.
Possibly need to install the attribute on the sales_order_table?
Adding custom attribute to order in Magento is same as we do for customer and category. The difference is we will use different setup class AND we will not need attribute set, group and attribute input type now. We will create a quick module which will do exactly what we want and nothing more than that. So yo need to create module for that. Please visit below URLs.
http://ka.lpe.sh/2013/05/10/magento-add-attribute-to-order/
https://www.atwix.com/magento/custom-product-attribute-quote-order-item/
Related
I am trying to create a custom payment module in magento. I found a lot of tutorials for this, but only ones that just add the order. My question is: How can i set the order to paid when the user clicks on checkout.
This is the relevant code i have so far:
Config.xml
<?xml version="1.0"?>
<config>
<modules>
<My_Module>
<version>1.0.0.0</version>
</My_Module>
</modules>
<global>
<models>
<My_Module>
<class>My_Module_Model</class>
</My_Module>
</models>
</global>
<default>
<payment>
<mypayment>
<active>1</active>
<model>My_Module/Payment</model>
<order_status>processing</order_status>
<title>Testing</title>
</mypayment>
</payment>
</default>
</config>
Model/payment.php
<?php
class My_Module_Model_Payment extends Mage_Payment_model_Method_Abstract{
protected $_code = 'mypayment';
protected $_isInitializeNeeded = false;
protected $_canUseInternal = true;
protected $_canUseForMultishipping = true;
}
I also find it very hard to find documentation. For example, i am looking for a list of events, and a documentation for the payment method, but i do not seem to find anything. Does Magento not offer any of these?
I think you need to utilize the Varien_Object and Sales_Quote to do any custom payment of any sorts with Magento (not sure on this), and not just the abstract payment method.
Check this (the answer has a link to an actual working example of a custom payment module).
Magento custom payment method
I am trying to implement the card only payment option for specific products (configurable products) in this magento (1.9.1) store. The problem i am having with the code that i am using is that i need to go to each simple product and update the attribute value to take effect. What I would like to know if i can make changes to the code so instead of using the value of the simple product can the value of the parent product be used, regardless of what value the simple product is using. So i would just have to update the configurable product to say if this product is Card Only.
My Observer.php for this module
<?php
class JMAWD_CardOnly_Model_Observer
{
public function cardOnly(Varien_Event_Observer $observer)
{
$event = $observer->getEvent();
$method = $event->getMethodInstance();
$result = $event->getResult();
$cardonly = false;
foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems() as $item)
{
if($item->getProduct()->getCardOnly()){
$cardonly = true;
}
}
if($method->getCode() == "cashondelivery" && $cardonly){
$result->isAvailable = false;
}
}
}
My config.xml for this module
<?xml version="1.0"?>
<config>
<modules>
<JMAWD_CardOnly>
<version>0.1.0</version>
</JMAWD_CardOnly>
</modules>
<global>
<events>
<payment_method_is_active>
<observers>
<card_only>
<type>singleton</type>
<class>cardonly/observer</class>
<method>cardOnly</method>
</card_only>
</observers>
</payment_method_is_active>
</events>
<models>
<cardonly>
<class>JMAWD_CardOnly_Model</class>
<resourceModel>cardonly_mysql4</resourceModel>
</cardonly>
</models>
<sales>
<quote>
<item>
<product_attributes>
<card_only/>
</product_attributes>
</item>
</quote>
</sales>
</global>
</config>
Help & advice appreciated. Thanks
If you have configurable childrens in your quote you can get the configurable parents and check for the card_only attribute. This way you don't need to care about the simple childs.
Something like this:
$quoteItemsCollection = Mage::getSingleton('checkout/cart')->getQuote()->getItemsCollection();
foreach ($quoteItemsCollection as $quoteItem) {
$productType = $quoteItem->getProductType();
// if productType is config and getCardOnly(), then $cardonly = true;
This should not happen with getAllVisibleItems(). As explained in this answer:
Loads the item collection, then returns an array of all items which are not marked as deleted AND do not have a parent (i.e. you get items for bundled and configurable products but not their associated children). Each array item corresponds to a displayed row in the cart page.
I suspect that you are using an extension like Simple Configurable Products or Better Configurable Products, which change the configurable product type such that the attributes of the simple products are displayed and used (especially the prices), and the product in the cart is actually just the simple product without a parent.
If this is the case, you have to inspect the code of the extension to find out where and how it stores the information about the configurable product. You can also look at the sales_flat_quote_item_option table because that's usually where all additional information about quote items is stored.
Still learning magento coding. I wonder is there a way I can print out all the values in the collections on any page I load on magento? This would be assuming I don't know the names of the collections being used.
This would be very helpful if it is possible.
First, a word of warning - if you are var_dump'ing collections, let alone every collection loaded for a given request, then you are most likely going to run in to problems - collections contain huge amounts of data.
What is it exactly that you require from each collection that you would need to do this?
Anyway, the only way to get this data that comes to mind would be to use an observer subscribed to:
core_collection_abstract_load_after
So as a head start...
Your config.xml would look similar to this...
<?xml version="1.0"?>
<config>
<modules>
<YourCompany_YourModule>
<version>1.0.0</version>
</YourCompany_YourModule>
</modules>
<frontend>
<events>
<core_collection_abstract_load_after>
<observers>
<yourmodule>
<class>YourCompany_YourModule_Model_Observer</class>
<method>core_collection_abstract_load_after</method>
</yourmodule>
</observers>
</core_collection_abstract_load_after>
</events>
</frontend>
<global>
<models>
<yourmodule>
<class>YourCompany_YourModule_Model</class>
</yourmodule>
</models>
</global>
</config>
Your observer would look like this...
<?php
class YourCompany_YourModule_Model_Observer
{
public function core_collection_abstract_load_after(Varien_Event_Observer $observer)
{
$collection = $observer->getEvent()->getCollection();
//Do what you want with each collection here
}
}
A much simpler approach and be it your new to Magento I would suggest using this:
https://github.com/madalinoprea/magneto-debug
As it will offer other insight into the internal workings as well as collection and SQL info about the actual collection.
A view in action:
http://www.youtube.com/watch?v=aqvgrmebcu4
I would like to make a portion of a page available for getting via AJAX. I have in mind to use a URL parameter, bare, that would tell Magento to present a page with a different template applied to the root block. The bare template looks like this:
<?php echo $this->getChildHtml('content'); ?>
That's it! The idea is that a JavaScript method could grab just the content of another page and insert it into the DOM where appropriate. (I don't want this to be possible with just any page – only pages that have been marked to do so in layout xml.)
I've read elsewhere that I should avoid conditional layout xml. The only other approach I can think of is to override the Page/Html block itself, creating a modified setTemplate method, like below. Instinctively, I'm concerned about overriding such a core part of Magento.
public function setTemplate($template, $bareTemplate='')
{
$bareMode = Mage::app()->getRequest()->getParam('bare');
$targetTemplate = (!empty($bareTemplate) && $bareMode === '1') ? $bareTemplate : $template;
return parent::setTemplate($targetTemplate);
}
What better approaches haven't I thought of?
The key to getting what you want is removing root as an output block, replacing it with content. Output blocks are just entry points for renderLayout();
To do this in Magento without include-path-hacking Mage_Core_Controller_Varien_Action, observe the controller_action_layout_render_before_$this->getFullActionName() scoped events which are fired in the base action controller class (ref Mage_Core_Controller_Varien_Action::renderLayout() method).
First configure your model class group and frontend event observer. You'll need to determine the full action name of any route that needs this logic. See Mage_Core_Controller_Varien_Action::renderLayout(). Example config below.
<?xml version="1.0"?>
<config>
<global>
<models>
<your_classgroup>
<class>Your_Classgroup_Model</class>
</your_classgroup>
</models>
</global>
<frontend>
<events>
<controller_action_layout_render_before_FULL_ACTION_NAME...>
<observers>
<your_observer_config>
<type>model</type>
<class>your_classgroup/observer</class>
<method>makeContentBlockTheOutputBlock</method>
</your_observer_config>
</observers>
</controller_action_layout_render_before_FULL_ACTION_NAME...>
</events>
</frontend>
</config>
The event observer logic is easy. Do this:
public function makeContentBlockTheOutputBlock($observer)
{
//Edit: action not passed in to this event; passed in generic generate_blocks event
if( Mage::app()->getRequest()->getParam('bare') )
{
Mage::app()->getLayout()->removeOutputBlock('root')->addOutputBlock('content');
}
}
HTH.
Greetings, in Magento I want to trigger an event, once an order has been set to processing (by gateway confirmation or manually) that, example: If a general customer (id 1) spends over 100$ and the payment has been confirmed, set his group id to 4 (silver VIP, which by promotion rule gets 2% discount globally)
I would give a bounty to this, but I'd like the answer before 2 days O_o
EDIT: the answer I received so far is only a partial answer, also I find the links very confusing, I'm not clear on what is the minimal setup, what do i have to configure create etc... Also I'm trying to find out how to get the paying customers id/model.
You should start by creating your own module in app/code/local.
Create for example the directories Moak/Vip. It will be the root of your module.
In order for Magento to know it exists, create a file named Moak_Vip.xml in etc/modules, with the following content :
<?xml version="1.0"?>
<config>
<modules>
<Moak_Vip>
<active>true</active>
<codePool>local</codePool>
<self_name>Moak VIP module</self_name>
</Moak_Vip >
</modules>
</config>
Then, in your module directory, you need the following structure and files :
etc/config.xml
Model/Observer.php
The config.xml defines your module and declares your event listener for a given event (checkout_onepage_controller_success_action is sent when onepage checkout process is complete, sales_order_payment_pay is sent when the payment has been confirmed).
You don't need any DB setup since you will not save any new entity.
So your config file should look something like the following :
<?xml version="1.0"?>
<config>
<modules>
<Moak_Vip>
<version>0.1.0</version>
</Moak_Vip>
</modules>
<global>
<models>
<moak>
<class>Moak_Vip_Model</class>
</moak>
</models>
<events>
<sales_order_payment_pay>
<observers>
<moak_observer>
<type>singleton</type>
<class>moak/observer</class>
<method>checkVipCustomer</method>
</moak_observer>
</observers>
</sales_order_payment_pay >
</events>
</global>
</config>
Now, your Observer method checkVipCustomer should receive an event object from which you can retrieve all information about the order, the customer... and perform the modifications you like.
Have a look at Magento model classes in app/code/core/Mage/.../Model/...
to see how to navigate through those objects.
Example :
<?php
class Moak_Vip_Model_Observer
{
public function checkVipCustomer($event)
{
$order = $event->getInvoice()->getOrder(); // Mage_Sales_Model_Order
/*
- Check order amount
- Get customer object
- Set Group id
- $customer->save();
*/
return $this;
}
}
Note I've not tested any of the code I wrote here, so handle with care !
Hope it helped, Magento has a hard learning curve...
Good luck !
You can create an observer for the "sales_order_payment_pay" event. Here is a cheatsheet of the events in magento 1.3.
And an explanation of how to create observer methods. Links courtesy of the excellent activecodeline and inchoo sites.