I have created some custom statuses beyond the default Magento statuses.
When I grab an order to send to production, I set the status in Magento via the API. Problem is, if the order is set to one of these custom statuses, it doesn't show the order in the My Account Order History area for the customer.
What do I need to do to show these orders in the My Account Order History area, that have my custom statuses currently set?
For question sake, this status is called "New Status" and I have assigned it to the processing state.
Short answer... merge this with app/code/core/Mage/Sales/config.xml or (better) add this to a config.xml in your own local module. Modifying core files is frowned upon (but happens).
Change new_status to your status.
<config>
<global>
<sales>
<order>
<statuses>
<new_status translate="label">
<label>New Status</label>
</new_status>
</statuses>
<states>
<new_status translate="label">
<label>New Status</label>
<statuses>
<new_status default="1"/>
</statuses>
<visible_on_front>1</visible_on_front>
</new_status>
</states>
</order>
</sales>
</global>
</config>
Long answer: See Mage_Sales_Block_Order_History specifically, the piece that grabs the order collection
$orders = Mage::getResourceModel('sales/order_collection')
->addFieldToSelect('*')
->addFieldToFilter('customer_id', Mage::getSingleton('customer/session')->getCustomer()->getId())
->addFieldToFilter('state', array('in' => Mage::getSingleton('sales/order_config')->getVisibleOnFrontStates()))
->setOrder('created_at', 'desc')
The second addFieldToFilter looks for order states within a set of "visible" states. Those set of states are pulled by Mage_Sales_Order_Config, and are set in the configuration. See above for the configuration changes. You can look in Mage_Sales_Order_Config and the function _getStates() to see how it pulls these from the configuration.
Suppose your custom order status is paymentsuccess in magento order_status table
<config>
<global>
<sales>
<order>
<statuses>
<paymentsuccess translate="label">
<label>Payment Successful</label>
</paymentsuccess>
</statuses>
<states>
<paymentsuccess translate="label">
<label>Payment Successful</label>
<statuses>
<paymentsuccess default="1"/>
</statuses>
<visible_on_front>1</visible_on_front>
</paymentsuccess>
</states>
</order>
</sales>
</global>
</config>
Related
Problem:
My new columns to Coupon grid disappear after AJAX pagination or delete calls.
My goal:
I want to extend Coupons grid in Shopping Cart Rule edit page by adding some columns.
How to:
If you create a shopping cart rule and set "Autogenerate coupons" checkbox to true and save, you will be able to go to Manage Coupons tab afterwards and generate coupons from there for this rule.
My magento store is using coupons that can be used only once, so I need to save a record on when a particular coupon has been used. As magento coupons didn't have that attribute, I added a column date_used in salesrule_coupon table using install script:
<?php
$installer = $this;
$installer->startSetup();
$installer->run("
ALTER TABLE {$this->getTable('salesrule_coupon')} ADD date_used DATE NULL after created_at;
");
$installer->endSetup();
date_used is created and I am able to see it in database. Next in order to add a new column to coupons grid I do the following:
I extend the Grid block class at code/core/Mage/Adminhtml/Block/Promo/Quote/Edit/Tab/Coupons/Grid.php and create my own code/local/Company/Coupons/Block/Adminhtml/Promo/Quote/Edit/Tab/Coupons/Grid.php
Here is the code:
<?php
class Company_Coupons_Block_Adminhtml_Promo_Quote_Edit_Tab_Coupons_Grid extends Mage_Adminhtml_Block_Promo_Quote_Edit_Tab_Coupons_Grid {
protected function _prepareColumns() {
parent::_prepareColumns();
// adding a column with date_used index
$this->addColumn('date_used', array(
'header' => Mage::helper('salesrule')->__('Date Used'),
'index' => 'date_used',
'width' => '50',
'type' => 'date',
));
return $this;
}
}
Create a layout file coupons.xml and place it in design design/adminhtml/company/default/layout/coupons.xml. In this layout I am adding my own coupongrid block as company_coupons/adminhtml_promo_quote_edit_tab_coupons_grid and removing magento's promo_quote_edit_tab_coupons_grid. As you can see, everything happens inside adminhtml_promo_quote_edit block.
Layout file:
<!-- adding own grid block and removing magento core grid from this block-->
<layout>
<adminhtml_promo_quote_edit>
<reference name="promo_quote_edit_tab_coupons">
<block type="company_coupons/adminhtml_promo_quote_edit_tab_coupons_grid" name="coupongrid" after="promo_quote_edit_tab_coupons_grid"/>
<remove name="promo_quote_edit_tab_coupons_grid"/>
</reference>
</adminhtml_promo_quote_edit>
</layout>
Finally, I register these changes in my etc/config.xml file.
Config file:
<?xml version="1.0"?>
<config>
<modules>
<Company_Coupons>
<version>0.1.2</version>
</Company_Coupons>
</modules>
<global>
<helpers>
<company_coupons>
<class>Company_Coupons_Helper</class>
</company_coupons>
</helpers>
<blocks>
<company_coupons>
<class>Company_Coupons_Block</class>
</company_coupons>
</blocks>
<models>
<company_coupons>
<class>Company_Coupons_Model</class>
</company_coupons>
</models>
<resources>
<coupons_setup>
<setup>
<module>Company_Coupons</module>
</setup>
<connection>
<use>core_setup</use>
</connection>
</coupons_setup>
<coupons_write>
<connection>
<use>core_write</use>
</connection>
</coupons_write>
<coupons_read>
<connection>
<use>core_read</use>
</connection>
</coupons_read>
</resources>
<events>
<sales_order_place_after>
<observers>
<coupons>
<class>company_coupons/observer</class>
<method>saveCouponUsageInfo</method>
</coupons>
</observers>
</sales_order_place_after>
</events>
</global>
<adminhtml>
<layout>
<updates>
<coupons>
<file>coupons.xml</file>
</coupons>
</updates>
</layout>
</adminhtml>
</config>
I also added saveCouponUsageInfo(Varien_Event_Observer $observer) method in Model/Observer.php, but I won't include that as it works just fine.
My solution works and I can clearly see the new column in my grid:
BUT! If I do ajax operations, like request the second page of grid, or mass delete, my column just disappears and grid contains its old set of columns. Of course, if I reload the entire page, date_used column comes back to grid. See below (image is cropped, 20 coupons are present on page 2):
I used the debugger in PhpStorm and noticed that coupon grid html, after mass delete, is requested by:
/index.php/admin/promo_quote/couponsGrid/id/64/key/1eccc1c40033fa8bf64007738a22dc1a?ajax=true&isAjax=true
Same request used for pagination, but adding page number into URL:
/index.php/admin/promo_quote/couponsGrid/id/64/key/1eccc1c40033fa8bf64007738a22dc1a/page/2/?ajax=true&isAjax=true
As you probably have guessed from URL, during those calls couponsGridAction() method in Mage_Adminhtml_Promo_QuoteController is triggered. The problem is that my implementation of _prepareColumns() is never called, as debugger revealed. Thus date_used column isn't included anymore.
Anyone faced this problem before? I spent an entire day on this little bug and would be extremely grateful for any hint or guidance. Thanks.
If you look at the controller action executed, i.e. Mage_Adminhtml_Promo_QuoteController::couponsGridAction() you'll see that it does the usual $this->loadLayout()->renderLayout();, which means that there is a layout defined for this AJAX action.
Open app/design/adminhtml/default/default/layout/promo.xml and at the bottom you'll see the layout defined for this particular action:
<adminhtml_promo_quote_couponsgrid>
<block type="core/text_list" name="root" output="toHtml">
<block type="adminhtml/promo_quote_edit_tab_coupons_grid" name="promo_quote_edit_tab_coupons_grid" />
</block>
</adminhtml_promo_quote_couponsgrid>
So you need to define a handle for this action in your layout coupons.xml file, something like this:
<adminhtml_promo_quote_couponsgrid>
<block type="core/text_list" name="root" output="toHtml">
<block type="company_coupons/adminhtml_promo_quote_edit_tab_coupons_grid" name="promo_quote_edit_tab_coupons_grid" />
</block>
</adminhtml_promo_quote_couponsgrid>
As you can see, I simply changed adminhtml with company_coupons in the block's type declaration and updated the path to your module's class, and it actually work (as your question was very well documented I actually could reproduce it here in local and this code is actually tested), as simple as that :)
I would like to add a textbox to the Header block located inside System>Config>Design>Header, the location in the image below.
I know this has to be done in xml, but I am not sure where. Also how would I display that in an phtml file?
In code/core/Mage/Page/etc/system.xml you will find the configuration that Magento reads to show those fields, for example the "Small Logo Image src" is a field called logo_src_small. The needed is a module that will tell Magento about:
The extra field in the admin panel under header.
<config>
<sections>
<design>
<groups>
<header>
<fields>
<new_field translate="label">
<label>New Field</label>
<frontend_type>text</frontend_type>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</new_field>
</fields>
</header>
</groups>
</design>
</section>
</config>
Rewrite the block class code/core/Mage/Page/Block/Html/Header.php so you can add the method that will expose the new field.
In the app/design/frontend/{Package}/{Theme}/template/page/html/header.phtml you can easily call $this->getNewField() where getNewField() is the method you have in the class we overridden in point 2.
A couple of links to help you start:
http://excellencemagentoblog.com/blog/2011/09/22/magento-part8-series-systemxml/
http://www.ecomdev.org/2010/10/27/custom-configuration-fields-in-magento.html
http://inchoo.net/magento/overriding-magento-blocks-models-helpers-and-controllers/
https://magento.stackexchange.com/questions/78175/add-custom-field-in-admin-system-configuration-sales
First add a field in system.xml file which is located in
app/code/core/Mage/Page/etc/system.xml,under header section
<header translate="label">
..........
<welcome_massage translate="label">
<label>Welcome Massage</label>
<frontend_type>text</frontend_type>
<sort_order>35</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</welcome_massage>
</fields>
</header>
Then add a method in header block , app/code/core/Mage/Page/Block/Html/Header.php
public function getWelcomeMassage()
{
return $this->_data['welcome_massage'] = Mage::getStoreConfig('design/header/welcome_massage') ;
}
Last call this method in header.phtml file, like that
<?php echo $this->getWelcomeMassage() ?>
Note : You see that I have code in core files. You should rewrite the
core files.
Overriding Magento blocks, models, helpers and controllers
Overwrite system.xml
In Magento Product type, I only need Simple product and Group Product. How can I hide it or remove it from Product type option when I add new product?
Thank you so much
You need to override Mage_Catalog_Model_Product_Type Model class.
In this call there is function static public function getOptionArray(). Just update this function.
Follow below instruction:
Create new file under app\etc\modules\Namespace_producttype.xml
<Namespace_Producttype>
<active>true</active>
<codePool>local</codePool>
</Namespace_Producttype>
Create new file under app\code\local\Namespace\Producttype\etc\config.xml
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Producttype>
<version>1.6.1.1</version>
</Namespace_Producttype>
</modules>
<global>
<models>
<catalog>
<rewrite>
<product_type>Namespace_Producttype_Model_Product_Type</product_type>
</rewrite>
</catalog>
</models>
</global>
</config>
Last file to override Model function.
app\code\local\Namespace\Producttype\Model\Product\Type.php
<<?php
class Namespace_Producttype_Model_Product_Type extends Mage_Catalog_Model_Product_Type
{
static public function getOptionArray()
{
$options = array();
foreach(self::getTypes() as $typeId=>$type) {
if($typeId == 'simple' || $typeId == 'grouped'):
$options[$typeId] = Mage::helper('catalog')->__($type['label']);
endif;
}
return $options;
}
}
?>
Hope this will help!
There are two ways to solve this problem.
Way 1:
Login to your admin account.
Search for option 'Module' over there.
Uninstall the module that you don't want. If you dont find over here, search for 'template' option. In that go to 'edit Template' and edit it as per your own choice.
Way 2: Go to your cpanel account.
Go to 'themes/template' folder.
Edit the template as per your own choice.
Do not remove anything from magento because you have a problem with the update.
The best solution would be for you to use only those options that you need.
You should he able to deactivate a few without any "hard" change.
Only
simples,
configurables,
grouped,
virtual products are part of the core magento catalog module, the rest are
own modules that can be deactivated completely by going into
app/etc/modules/Mage_Bundle.xml
app/etc/modules/Mage_Downloadable.xml
and setting "active" from true to false.
dont forget cleaning the cache after these changes
if you are using the enterprise version there is a
giftcard product type too
for the other product types:
since it is not possible to remove config nodes or overwrite them in the way you need it, the maybe easiest way is to go to /app/code/core/Mage/Catalog/etc/config.xml and comment the other product types like this, how ever an upgrade of magento will maybe revert these changes
<catalog>
<product>
<type>
<simple translate="label" module="catalog">
<label>Simple Product</label>
<model>catalog/product_type_simple</model>
<composite>0</composite>
<index_priority>10</index_priority>
</simple>
<grouped translate="label" module="catalog">
<label>Grouped Product</label>
<model>catalog/product_type_grouped</model>
<price_model>catalog/product_type_grouped_price</price_model>
<composite>1</composite>
<allow_product_types>
<simple/>
<virtual/>
</allow_product_types>
<index_priority>50</index_priority>
<price_indexer>catalog/product_indexer_price_grouped</price_indexer>
</grouped>
<!--
<configurable translate="label" module="catalog">
<label>Configurable Product</label>
<model>catalog/product_type_configurable</model>
<price_model>catalog/product_type_configurable_price</price_model>
<composite>1</composite>
<allow_product_types>
<simple/>
<virtual/>
</allow_product_types>
<index_priority>30</index_priority>
<price_indexer>catalog/product_indexer_price_configurable</price_indexer>
</configurable>
<virtual translate="label" module="catalog">
<label>Virtual Product</label>
<model>catalog/product_type_virtual</model>
<composite>0</composite>
<index_priority>20</index_priority>
</virtual>
-->
</type>
I am building an Magento site. Currently on the account registration form I have built it so there is drop down box which allows customers to choose their ‘Customer Group’.
If there are for example four different customer groups there are four different success emails the default Magento one, and 3 which I would create). What I need is based on which customer group is chosen the appropriate email is sent.
I have found the function which sends the new email in AccountController.php :
$customer->sendNewAccountEmail(
$isJustConfirmed ? 'confirmed' : 'registered',
'',
Mage::app()->getStore()->getId()
);
My initial thought would be to create the other email files in app/locale/en_US/template/email
But I don’t know which file/function chooses ‘account_new.html’ as the default email file so I could maybe implement some checks based of the customer group id.
I am unsure of the next steps to approach this such as how to edit this file and where to create the different success emails.
You'll likely need to overwrite the Mage_Customer_Model_Customer class to take control of the function sendNewAccountEmail(). This function is how the system decides which email to send and in theory you could override this function.
You probably know how to do an override, but just in case:
<models>
<customer>
<rewrite>
<customer>Namespace_Module_Model_Customer</customer>
</rewrite>
</customer>
</models>
Next, you'll want to create system configuration values, System.xml, you'll need to create a new entry for each "group" you have. This is no the most elegant solution as this is a static list and your groups could be dynamic. But to assign a template you'd either need a whole new module or update this file. But, now you can create transactional emails and assign it to each group in this system.xml file.
<?xml version="1.0"?>
<config>
<sections>
<yourmodule translate="label" module="yourmodule">
<class>separator-top</class>
<label>your module</label>
<tab>general</tab>
<frontend_type>text</frontend_type>
<sort_order>30</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
<groups>
<email translate="label">
<label>Email Templates</label>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<fields>
<group1_template translate="label comment">
<label>Group 1 Template</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_email_template</source_model>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</group1_template>
<group2_template translate="label comment">
<label>Group 2 Template</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_email_template</source_model>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</group2_template>
</fields>
</email>
</groups>
</yourmodule>
</sections>
</config>
Finally, the override for your sendNewAccountEmail():
class Namespace_Module_Model_Customer {
public function sendNewAccountEmail($type = 'registered', $backUrl = '', $storeId = '0')
{
$types = array(
'registered' => self::XML_PATH_REGISTER_EMAIL_TEMPLATE, // welcome email, when confirmation is disabled
'confirmed' => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE, // welcome email, when confirmation is enabled
'confirmation' => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE, // email with confirmation link
'group1' => 'yourmodule/email/group1_template',
'group2' => 'yourmodule/email/group2_template',
);
if (!isset($types[$type])) {
Mage::throwException(Mage::helper('customer')->__('Wrong transactional account email type'));
}
if (!$storeId) {
$storeId = $this->_getWebsiteStoreId($this->getSendemailStoreId());
}
$this->_sendEmailTemplate($types[$type], self::XML_PATH_REGISTER_EMAIL_IDENTITY,
array('customer' => $this, 'back_url' => $backUrl), $storeId);
return $this;
}
}
Obviously there is a lot of room for improvement, namely coming up with a way to dynamically pull customer groups and created configurations from that and additionally adding those same dynamic checks to this function, but this is a simple static solution.
I've got an issue with Magento xml layouts. I've been trying to change the page template when a customer is logged in, but only for specific pages in the layout. I've tried using the <customer_logged_in> handle in my xml but I can't get it to reference another handle specifically.
Non-working example of what I'd like it to do:
<catalog_product_view>
<customer_logged_in>
<reference name="root">
<action method="setTemplate"><template>page/3columns.html</template></action>
</reference>
</customer_logged_in>
<customer_logged_out>
<reference name="root">
<action method="setTemplate"><template>page/2columns-left.html</template></action>
</reference>
</customer_logged_out>
</catalog_product_view>
Is this possible to accomplish with the XML layout system or should I be looking at another approach?
Unfortunately with Magento layouts, there is no way to filter between two layout handles.
What I would recommend is slightly different and more complex, but I believe that it will give you the flexibility that you need.
You will need to create a module to do this. I am including all code necessary to do this.
Module Definition:
app/etc/Your_Module.xml
<config>
<modules>
<Your_Module>
<codePool>local</codePool>
<active>true</active>
</Your_Module>
</modules>
</config>
Config XML:
app/code/local/Your/Module/etc/config.xml:
<config>
<global>
<modules>
<Your_Module>
<version>1.0</version>
</Your_Module>
</modules>
</global>
<frontend>
<controller_action_layout_generate_blocks_after>
<observers>
<your_module_name>
<type>singleton</type>
<class>Your_Module/Observer</class>
<method> controllerActionLayoutGenerateBlocksAfter</method>
</your_module_name>
</observers>
</controller_action_layout_generate_blocks_after>
</frontend>
</config>
The code that makes it work
Then at this path app/code/local/Your/Module/Model/Observer.php:
<?php
class Your_Module_Model_Observer
{
public function controllerActionLayoutGenerateBlocksAfter ($observer)
{
$controller = $observer->getAction();
if ($controller->getFullActionName() == 'catalog_product_view') {
$layout = $controller->getLayout();
$rootBlock = $layout->getBlock('root');
if (Mage::getSingleton('customer/session')->isLoggedIn()) {
$rootBlock->setTemplate('page/1-column.html');
} else {
$rootBlock->setTemplate('page/2-columns.html');
}
}
}
}
(I took a few tips from: update layout programatically in magento event observer)