I'm pretty new to Magento, and having problems trying to set a custom shipping method programmatically. I'm converting an xml from a thrid party into an order, and everything else (that I've worked on so far) is working fine. Also I'm having problems spelling "programmatically" but I won't ask for you help with that.
I set up my custom shipping method as follows:
To activate the shipping module in
app/etc/modules/Extension_Shipping.xml
<?xml version=
"1.0"?>
<config>
<modules>
<Extension_Shipping>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Shipping/>
</depends>
</Extension_Shipping>
</modules>
</config>
then to configure it in
app/code/local/Extension/Shipping/etc/config.xml
<?xml version=
"1.0" ?>
<config>
<modules>
<Extension_Shipping>
<version>0.1.0</version>
</Extension_Shipping>
</modules>
<global>
<models>
<extension_shipping>
<class>Extension_Shipping_Model</class>
</extension_shipping>
</models>
</global>
<default>
<carriers>
<extension_myrate>
<active>1</active>
<model>extension_shipping/carrier_myrate</model>
<title>Extension Shipping</title>
<name>Default Rate</name>
</extension_myrate>
</carriers>
</default>
</config>
then to add the class in
app/code/local/Extension/Shipping/Model/Carrier/MyRate.php
<?php
class Extension_Shipping_Model_Carrier_MyRate
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
protected $_code = 'extension_myrate';
protected $_isFixed = true;
public function collectRates(Mage_Shipping_Model_Rate_Request
$request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$result = Mage::getModel('shipping/rate_result');
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('extension_myrate');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('extension_myrate');
$method->setMethodTitle($this->getConfigData('name'));
$method->setPrice(5);
$method->setCost(2);
$result->append($method);
return $result;
}
public function getAllowedMethods()
{
return array('extension_myrate' => $this->getConfigData('name'));
}
}
Basically I followed http://www.magentotricks.com/creating-a-customer-magento-shipping-method/
I thought it all worked fine, as the shipping method now shows up in the checkout screen, and can be set both by customers or in the admin "create new order." However, I'm not able to set it programmatically.
In my controller I'm trying to set the shipping method using the code
$shippingAddress = $quote->getShippingAddress()->addData($addressData);
$shippingAddress->setCollectShippingRates(true)->collectShippingRates()
->setShippingMethod('extension_myrate')
->setPaymentMethod('checkmo');
To add to my confusion, it worked once. but only once out of quite a few test orders. changing the "setShippingMethod" to "freeshipping_freeshipping" or "flatrate_flatrate" makes it update the shipping to those correctly. because of that and because I'm new and still having problems with the file structure, I'm guessing my problem is with setShippingMethod('extension_myrate') but I'm not entirely sure. Any advice would be helpful and appreciated.
Related
I have been pulling my hair out over trying to get a hole punched out for the price block on the product page. I have looked at numerous sources, including some from you good people at stackoverflow, but I have been getting a fatal error, so something is incorrect. Here are some sources that I used:
http://invisiblezero.net/magento-ee-punch-hole-in-full-page-cache/
http://www.kingletas.com/2012/09/how-does-magento-full-page-cache-works.html
Magento full page cache
Trying get dynamic content hole-punched through Magento's Full Page Cache
How to implement magento cache hole punching for shopping cart block
As you can see, I have been all over, and I have read more in addition to this but some of them conflict a litt, and I think that is where I have my issue, now let me post some code for you.
cache.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<placeholders>
<SpecialPrice>
<block>catalog/product_price</block>
<name>product.pricing</name>
<placeholder>CATALOG_PRODUCT_PRICE</placeholder>
<container>MyStore_SpecialPrice_Model_Container_Cache</container>
<cache_lifetime>8640</cache_lifetime>
</SpecialPrice>
</placeholders>
</config>
cache.php
<?php
class MyStore_SpecialPrice_Model_Container_Cache extends Enterprise_PageCache_Model_Container_Abstract
{
/**
* Get customer identifier from cookies
*
* #return string
*/
protected function _getIdentifier()
{
return $this->_getCookieValue(Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER, '');
}
/**
* Get cache identifier
*
* #return string
*/
protected function _getCacheId()
{
return 'CATALOG_PRODUCT_PRICE' . md5($this->_placeholder->getAttribute('cache_id') . $this->_getIdentifier());
}
/**
* Render block content
*
* #return string
*/
protected function _renderBlock()
{
$blockClass = $this->_placeholder->getAttribute('block');
$template = $this->_placeholder->getAttribute('template');
$block = new $blockClass;
$block->setTemplate($template);
return $block->toHtml();
}
}
congig.xml
<?xml version="1.0"?>
<config>
<modules>
<MyStore_SpecialPrice>
<version>0.1.0</version>
</MyStore_SpecialPrice>
</modules>
<frontend>
<events>
<catalog_product_get_final_price>
<observers>
<MyStore_SpecialPrice_Model_Observer>
<class>MyStore_SpecialPrice_Model_Observer</class>
<method>setSpecialPrice</method>
</MyStore_SpecialPrice_Model_Observer>
</observers>
</catalog_product_get_final_price>
</events>
</frontend>
<admin>
<routers>
<SpecialPrice>
<use>admin</use>
<args>
<module>MyStore_SpecialPrice</module>
<frontName>SpecialPrice</frontName>
</args>
</SpecialPrice>
</routers>
</admin>
<global>
<models>
<SpecialPrice>
<class>MyStore_SpecialPrice_Model</class>
</SpecialPrice>
</models>
</global>
</config>
snippet from local.xml
<reference name="right">
<block type="catalog/product_price" name="product.pricing" template="catalog/product/product-price-block.phtml" before="-" >
Let me know if there is anything that jumps out to you.
Im trying to call an Observer after the order has been created, and AFTER payment has been captured.
So far I've tried;
checkout_submit_all_after,
sales_order_payment_place_end,
sales_order_place_after,
sales_order_payment_pay,
sales_order_payment_capture,
sales_order_payment_transaction_save_after
Just to name the main ones.
I've also logged all Event Dispaches inside dispatchEvent() but found nothing that stands out and is only fired when i need it.
the issue i'm having is that the status of the order is always ether 'Payment Pending' or something that predated this; meaning that i don't know whether the order will fail or succeed.
My aim, is to fire a function only on successful orders.
thanks.
after much more testing i found the following Observer to do the trick;
checkout_onepage_controller_success_action
This returns just the order id, so;
$order_id = $observer->getData('order_ids');
$order = Mage::getModel('sales/order')->load($order_id);
and you see that the order status is 'processing' and the payment is aproved (or not).
1 ) here is custom config.xml for call observer file
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Modulename>
<version>0.1.0</version>
</Namespace_Modulename>
</modules>
<frontend>
<events>
<checkout_submit_all_after>
<observers>
<Namespace_Modulename_Customevent>
<type>singleton</type>
<class>Namespace_Modulename_Model_Observer</class>
<method>customFunction</method>
</Namespace_Modulename_Customevent>
</observers>
</checkout_submit_all_after>
</events>
</frontend>
</config>
2 ) create observer.php file inside your module/Model directory and paste this code
<?php
class Namespace_Modulename_Model_Observer
{
public function customFunction(Varien_Event_Observer $observer)
{
$order = $observer->getEvent()->getOrder();
//here you can add your custom code
}
}
please try this.. sure it will help you !
I have also tried all event but didn't get success. Then I moved to override Mage OnePageController and called my custom function. Below is the code to override onestep checkout.
app\etc\modules\Namespace_Module.xml
<Namespace_Checkout>
<active>true</active>
<codePool>local</codePool>
</Namespace_Checkout>
app\code\local\Namespace\Checkout\etc\config.xml
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Checkout>
<version>0.1.0</version>
</Namespace_Checkout>
</modules>
<frontend>
<routers>
<checkout>
<args>
<modules>
<Namespace_Checkout before="Mage_OneStepCheckout">Namespace_Checkout</Namespace_Checkout>
</modules>
</args>
</checkout>
</routers>
</frontend>
</config>
app\code\local\Namespace\Checkout\controllers\OnepageController.php
<?php
require_once 'Mage/Checkout/controllers/OnepageController.php';
class Namespace_Checkout_OnepageController extends Mage_Checkout_OnepageController{
public function successAction(){
$session = $this->getOnepage()->getCheckout();
if (!$session->getLastSuccessQuoteId()) {
$this->_redirect('checkout/cart');
return;
}
$lastQuoteId = $session->getLastQuoteId();
$lastOrderId = $session->getLastOrderId();
$lastRecurringProfiles = $session->getLastRecurringProfileIds();
if (!$lastQuoteId || (!$lastOrderId && empty($lastRecurringProfiles))) {
$this->_redirect('checkout/cart');
return;
}
$this->customFunction(); // Custom function to call
$session->clear();
$this->loadLayout();
$this->_initLayoutMessages('checkout/session');
Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
$this->renderLayout();
}
function customFunction(){
// This function is calling before clearing order session
//Here you can put all your custom code
}
}
?>
In the above controller, I have added customFunction() wher you can put your custom code.
Hope it will help you!
I'm trying to create my first Magento extension and I'm stuck at the first step already.
When adding {{block type="rick_printer/print" text="Hello world"}} to a CMS page or block, I want "Hello world" to be displayed.
Unfortunately nothing happens. Here's my code:
app\code\local\Rick\Printer\etc\config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Rick_Printer>
<version>0.0.1</version>
</Rick_Printer>
</modules>
<global>
<blocks>
<rick_printer>
<class>Rick_Printer_Block_Print</class>
</rick_printer>
</blocks>
</global>
</config>
app\etc\modules\Rick_Printer.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Rick_Printer>
<active>true</active>
<codePool>local</codePool>
</Rick_Printer>
</modules>
</config>
app\code\local\Rick\Printer\Block\Print.php
class Rick_Printer_Block_Print extends Mage_Core_Block_Abstract
{
protected function _construct()
{
$this->setTemplate('rick/printer/view.phtml');
parent::_construct();
}
public function printIt()
{
$text = $this->getText();
if (!$text) {
$msg = "Please provide a text!";
echo $msg;
return array();
}
return $text;
}
}
app\design\frontend\default\default\template\rick\printer\print.phtml
<?php
$text = $this->spinIt();
echo $text;
?>
I know the code is ugly and I'm probably doing it all wrong.
Any help is highly appreciated!
Thanks
Update: After applying the fix from Vinai's answer my app\code\local\Rick\Printer\etc\config.xml looks now like this:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Rick_Printer>
<version>0.0.1</version>
</Rick_Printer>
</modules>
<global>
<blocks>
<rick_printer>
<class>Rick_Printer_Block</class>
</rick_printer>
</blocks>
</global>
</config>
and I'm getting the following error message when accessing the CMS page (which doesn't show):
class Rick_Printer_Block_Print extends Mage_Core_Block_Abstract
{
protected function _construct()
{
$this->setTemplate('rick/printer/view.phtml');
parent::_construct();
}
public function printIt()
{
$text = $this->getText();
if (!$text) {
$msg = "Please provide a text!";
echo $msg; return array();
}
return $text;
}
}
Fatal error: Class 'Rick_Printer_Block_Print' not found in /home/www/xyz/htdocs/app/code/core/Mage/Core/Model/Layout.php on line 491
First, your block class prefix is wrong. Despite the node name being <class>, what you are actually specifying is a class prefix.
Another way to look at it is that this node declares the directory, in which the blocks for the module are located.
The correct way is
<!-- language: xml -->
<global>
<blocks>
<rick_printer>
<class>Rick_Printer_Block</class>
</rick_printer>
</blocks>
</global>
Second, in your template you are calling $this->spinIt(); instead of $this->printIt();.
Just a typo...
Otherwise the code looks okay.
UPDATE
The error message indicates a file system path to class name mismatch. Check the casing and for typos.
Also, since you want your block to render a template, you want to extend Rick_Printer_Block_Print from Mage_Core_Block_Template instead of the _Abstract block class.
I have created a module to add a discount code to the customers cart if they are either a new customer or have not ordered in the last 24 hours, it is for a company supplying lunch for their employees and they receive a subsidiary each day to use of £3.00.
So I have:
app/code/local/Brave/Subsidary/controllers/CartControlller.php
<?php
require_once Mage::getModuleDir('controllers', 'Mage_Checkout').DS.'CartController.php';
class Brave_Subsidary_CartController extends Mage_Checkout_CartController {
const DISCOUNTCODE = 'BCOMSTAFF';
public function addAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
public function indexAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
public function autoApplySubsidaryDiscount() {
$customer = Mage::getSingleton('customer/session')->getCustomer();
$orders = Mage::getResourceModel('sales/order_collection')
->addFieldToSelect('*')
->addFieldToFilter('customer_id', $customer->getId());
if(!$orders->getSize()) {
// New Customer...
$this->applyDiscountCoupon();
} else {
// Check last order date
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addFilter('customer_id', $customer->getId())
->setOrder('created_at', Varien_Data_Collection_Db::SORT_ORDER_DESC);
$newestOrder = $orderCollection->getFirstItem();
$dateToday = Mage::getModel('core/date')->timestamp(time());
$lastOrderDate = Mage::getModel('core/date')->timestamp(strtotime($newestOrder->getData('created_at')));
// only apply if last order was more than 24hrs ago..
if( $dateToday > $lastOrderDate ) {
$this->applyDiscountCoupon();
}
}
}
public function applyDiscountCoupon() {
Mage::getSingleton("checkout/session")->setData("coupon_code",self::DISCOUNTCODE);
Mage::getSingleton('checkout/cart')->getQuote()->setCouponCode(self::DISCOUNTCODE)->save();
}
}
?>
app/code/local/Brave/Subsidary/etc/config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Brave_Subsidary>
<version>0.1.0</version>
</Brave_Subsidary>
</modules>
<frontend>
<routers>
<checkout>
<use>standard</use>
<args>
<modules>
<Brave_Subsidary before="Mage_Checkout">Brave_Subsidary</Brave_Subsidary>
</modules>
</args>
</checkout>
</routers>
</frontend>
</config>
Then my module file:
app/etc/modules/Brave_Subsidary.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Brave_Subsidary>
<active>true</active>
<codePool>local</codePool>
</Brave_Subsidary>
</modules>
</config>
The problem is that I am getting a redirect loop on the cart page or from adding an item to the cart, this is probably a real simple issue but trying to Google anything related this is a real needle in a haystack!
The error FireFox tells me is:
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
The problem is:
You are calling parent:addAction() which redirects back to indexAction which is your indexAction which calles parent:addAction again...thus the redirect loop.
Bad code:
public function indexAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
You must not call addAction in your above seen custom indexAction!
Solution:
Remove
public function indexAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
Change
public function addAction() {
$this->autoApplySubsidaryDiscount();
parent::addAction();
}
Done.
But better instead rewriting the controller would be to use an observer...but thats another thread i guess :)
I have created an event observer that will send email on order completion.
I am sending email to email_address1 when a product is ordered from the category1 and sending email to email_address2 when a product is ordered from the cateogory2. Therefore I have created an observer event for this.
But when I click on the "Place Order" button nothing happens. What is the problem?
in magento/app/etc/modules/Custom_Email.xml:
<?xml version="1.0"?>
<config>
<modules>
<Custom_Email>
<codePool>local</codePool>
<active>true</active>
</Custom_Email>
</modules>
</config>
in magento/app/code/local/Custom/Email/etc/config.xml:
<?xml version="1.0"?>
<config>
<global>
<models>
<customemail>
<class>Custom_Email_Model</class>
</customemail>
</models>
<events>
<sales_order_place_after>
<observers>
<custom_email_order_observer>
<type>singleton</type>
<class>customemail/order_observer</class>
<method>sendOrder</method>
</custom_email_order_observer>
</observers>
</sales_order_place_after>
</events>
</global>
</config>
in magento/app/code/local/Custom/Email/Model/Order/Observer.php:
<?php
class Custom_Email_Model_Order_Observer
{
public function __contruct()
{
}
/**
* Exports new orders to an xml file
* #param Varien_Event_Observer $observer
* #return Feed_Sales_Model_Order_Observer
*/
public function sendOrder($observer){
$order = $observer->getEvent()->getOrder();
$cat_id = Mage::getModel('catalog/layer')->getCurrentCategory()->getId();
echo $cat_id;
//Implement logic here
...
$emailTemplate = Mage::getModel('core/email_template')
->loadDefault('rehab');
$emailTemplateVariables = array();
$emailTemplateVariables['order'] = $order;
$emailTemplate->setSenderName('Your shops name');
$emailTemplate->setSenderEmail('addres#from.com');
$emailTemplate->setTemplateSubject('Subject');
$emailTemplate->send('to#addres.com','Name', $emailTemplateVariables);
echo 'email sent';
}
}
?>
So any one know where is the problem?
The layer does not exist in the order context, nor is the category from which the product was selected available as a property of quote or order items. It's a known deficiency in Magento which unfortunately limits segmentation.