I've added one step after the shipping method in Magento OPC.
I need to double and save the shipping amount if the customer chooses Express shipping. How to achieve this?
What I tried:
1. $quote = $this->getQuote();
$quote->setShippingAmount($price);
$quote->setBaseShippingAmount($price);
$quote->getShippingAddress()->collectShippingRates();
$quote->getShippingAddress()->collectTotals();
$quote->save();
Which doesn't work.
2.$address = $this->getQuote()->getShippingAddress();
$method = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingMethod();
if ($method) {
foreach ($address->getAllShippingRates() as $rate) {
if ($rate->getCode()==$method) {
$amountPrice = $address->getQuote()->getStore()->convertPrice($rate->getPrice(), false);
$method->setPrice('20');
$method->setCost('20');
$shippingDescription = $rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle();
$address->setShippingDescription(trim($shippingDescription, ' -'));
break;
}
}
}
As you didn't mention about observer. so you need to create one observer to handle this things
here is very good documentation to achive your goal
just go throw this link and try to understand what they are doing. also if you want to change rate you can also it to your custom code.
hope this will sure help you.
Related
I've create my custom payment module, it works on payment gateway, everything is working fine but I would like to set the order as paid when the return url give back a succes code. So far I've understand that I have to create an invoice for the order to be able to ave it set as paid into Magento panel.
So first of all please tell me if I'm wron until here.
Then I'm trying to create invoice on success.phtml with some codes like:
$invoice = Mage::getModel('sales/service_order', $order->prepareInvoice());
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
$invoice->register();
$invoice->getOrder()->setCustomerNoteNotify(true);
$invoice->getOrder()->setIsInProcess(true);
$order->addStatusHistoryComment('Automatically INVOICED by Rico.', false);
$transactionSave = Mage::getModel('core/resource_transaction')
->addObject($invoice)
->addObject($invoice->getOrder());
$transactionSave->save();
But it gives me back always a magento error, so probably is not a good idea.
Any help will be appreciated
EDIT
From this http://blog.chapagain.com.np/magento-quick-way-to-create-order-invoice-programmatically/
I've used
$invoiceId = Mage::getModel('sales/order_invoice_api')
->create($_order->getIncrementId(), array());
instead the code above and it seems that the order is paid. But I'm not sure, if is enough.
I suggest you when customer is returning to your site from payment gateway and then it must goes to a magento controller and it an action you need to add your code at there
$order=Mage::getModel('sales/order')->load($orderID);
if($order->canInvoice() and $order->getIncrementId())
{
$items = array();
foreach ($order->getAllItems() as $item) {
$items[$item->getId()] = $item->getQtyOrdered();
}
$invoiceId=Mage::getModel('sales/order_invoice_api')->create($order->getIncrementId(),$items,null,false,true);
Mage::getModel('sales/order_invoice_api')->capture($invoiceId)};
}
See http://www.amitbera.com/programmatically-create-invoice-of-a-new-order-in-magento/
hello based on this thread: add tracking number automatically
i have managed to add tracking numbers to orders when button 'ship' is pressed
but the question is can i make somehow check before adding tracking number? cause i want to add tracking number only to specific shipping method (carrier)
how can i do that?
i have tried to add if statement before adding tracking number like this:
public function salesOrderShipmentSaveBefore($observer)
{
$rate = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingRatesCollection();
$method = $rate->getCarrier();
if ($method == 'mycompany_mycarrier'){
$trackNumber='123456789';
$shipment = $observer->getEvent()->getShipment();
$track = Mage::getModel('sales/order_shipment_track')
->setNumber($trackNumber)
->setCarrierCode('mycompany_mycarrier')
->setTitle('My Carrier');
$shipment->addTrack($track);
}
but when i press ship button error says that i am calling undefined method - Mage_Sales_Model_Resource_Quote_Address_Rate_Collection::getCarrier()
maybe there is other way how can i check that it is my carrier and then add tracking number; cause this code adds tracking number but to all orders, all i want is that it add tracking number to my own created shipping method
any help would be great
// After Order Place event
$iOrderId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
$oOrder = Mage::getModel('sales/order')->loadByIncrementId($iOrderId);
$oOrder->getShippingDescription();
Does the method even exist?
It tells you that you are missing a piece of code.
solved my problem, the Observer.php:
public function salesOrderShipmentSaveBefore($observer)
{
$trackNumber='987654321';
$shipment = $observer->getEvent()->getShipment();
$order = $shipment->getOrder();
$orderIncrementId=$order->getIncrementId();
$oOrder = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
$shipping = $oOrder->getShippingDescription();
if($shipping =='My Carrier - My Method')
{
$track = Mage::getModel('sales/order_shipment_track')
->setNumber($trackNumber)
->setCarrierCode('mycompnay_mycarrier')
->setTitle('My Carrier');
$shipment->addTrack($track);
}
}
now everything works just like i wanted, the tracking number is added to my shipping carrier only.
Thank you Kingshuk Deb, you were right since the begining, i just didnt understood that.
I have been working with magento cart pro extension. For ajax add to cart functionality, i have followed this following link Excellance Magento Blog
Its working Fine.But i have searched a lot regarding ajax delete item from cart, But google returns me always with 3rd party extension. I can't find tutorial for delete product from cart. So i thought, to take a referrance from one of free 3rd party extension which have an both add to cart and delete from cart functionality. I found this following extension which have above both function and also working rock. Ajax cart pro .
I have checked this extension coding part. But I'm really confused, I can't find which code doing delete functionality. They have overwrite only deleteAction in controller file only, I think.I can't understand even what i'm doing.I just need the guidance to add ajax delete functionality.
If anybody have an idea or found any tutorial of this, please share with me your thoughts friends.
Diving into an Ajaxcart extension, in the controller's action, we could find (yeah, you were right!), the following line is actually removing an item:
$this->_getCart()->removeItem($id)->save();
public function deleteAction() {
$id = (int) $this->getRequest()->getParam('id');
if ($id) {
try {
$this->_getCart()->removeItem($id)
->save();
} catch (Exception $e) {
$_response = Mage::getModel('ajaxcart/response');
$_response->setError(true);
$_response->setMessage($this->__('Cannot remove the item.'));
$_response->send();
Mage::logException($e);
}
}
$_response = Mage::getModel('ajaxcart/response');
$_response->setMessage($this->__('Item was removed.'));
//append updated blocks
$this->getLayout()->getUpdate()->addHandle('ajaxcart');
$this->loadLayout();
$_response->addUpdatedBlocks($_response);
$_response->send();
}
So answering you question "which code doing the delete", it's definitely therein;)
And to understand a whole process, you should have in mind these points:
ajaxcart.js - they're overriding Magento's setLocation function and then doing a ajax call(in ajaxCartSubmit method):
var oldSetLocation = setLocation;
var setLocation = (function() {
return function(url){
if( url.search('checkout/cart/add') != -1 ) {
//its simple/group/downloadable product
ajaxcart.ajaxCartSubmit(url);
to render a button use url helper, like this:
<button type="button" title="Add to Cart" class="button btn-cart"
onclick="setLocation('<?php echo $this->helper('checkout/cart')->getAddUrl($_product, $additional = array('qty' => 1));?>')">
+
</button>
updateBlocks. There are an Observer and Response Models that grabs a list of blocks to update/replace on frontend, renders their contents and put em to json reponse.
$updated_blocks = unserialize(Mage::getStoreConfig('ajaxcart/general/update_blocks'));
// ... for each do a $layout->getBlock('<blockName>')->toHtml() and add to json responce
A blocks definitions taken from a core layout and from additional ajaxcart handle (layout/ajaxcart.xml). (cart_sidebar, top.links & etc.)
you can refer the following code
<?php
$id = '100'; // replace product id with your id
$cartHelper = Mage::helper('checkout/cart');
$items = $cartHelper->getCart()->getItems();
foreach($items as $item):
if($item->getProduct()->getId() == $id):
$itemId = $item->getItemId();
$cartHelper->getCart()->removeItem($itemId)->save();
break;
endif;
endforeach;
?>
Whenever you load the cart page in Magento, the following code is run
$cart->init();
$cart->save();
One side effect of this is that the prices for any items in the cart are updated if the price of the product has been updated. This actually updates the entry in sales_flat_quote_item. I'm trying to track down where in code the price is updated on each quote item, and where each quote item is saved.
I know the myrid locations it could be set. I'm hoping someone knows where it actually is set. Magento 1.7x branch specifically, although info from all versions is welcome.
Dug this one up myself. So there's this
#File: app/code/core/Mage/Sales/Model/Quote.php
foreach ($this->getAllAddresses() as $address) {
...
$address->collectTotals();
...
}
which leads to this
#File: app/code/core/Mage/Sales/Model/Quote/Address.php
public function collectTotals()
{
Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_before', array($this->_eventObject => $this));
foreach ($this->getTotalCollector()->getCollectors() as $model) {
$model->collect($this);
}
Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_after', array($this->_eventObject => $this));
return $this;
}
The getTotalCollector object returns a sales/quote_address_total_collector object, which loads a series of collector models from global/sales/quote/totals and calls collect on them. The sub-total collector's collect method ultimately calls this
#File: app/code/core/Mage/Sales/Model/Quote/Address/Total/Subtotal.php
protected function _initItem($address, $item)
{
//...
if ($quoteItem->getParentItem() && $quoteItem->isChildrenCalculated()) {
$finalPrice = $quoteItem->getParentItem()->getProduct()->getPriceModel()->getChildFinalPrice(
$quoteItem->getParentItem()->getProduct(),
$quoteItem->getParentItem()->getQty(),
$quoteItem->getProduct(),
$quoteItem->getQty()
);
$item->setPrice($finalPrice)
->setBaseOriginalPrice($finalPrice);
$item->calcRowTotal();
} else if (!$quoteItem->getParentItem()) {
$finalPrice = $product->getFinalPrice($quoteItem->getQty());
$item->setPrice($finalPrice)
->setBaseOriginalPrice($finalPrice);
$item->calcRowTotal();
$this->_addAmount($item->getRowTotal());
$this->_addBaseAmount($item->getBaseRowTotal());
$address->setTotalQty($address->getTotalQty() + $item->getQty());
}
//...
}
and this is where the quote item gets it's price set/rest.
From a high level, the code that starts the whole process are lines 464 and 465 of Mage_Checkout_Model_Cart :
$this->getQuote()->collectTotals();
$this->getQuote()->save();
The new product price is being set against the quote in Mage_Sales_Model_Quote_Address_Total_Subtotal in the _initItem method. You will see $item->setPrice in the the if / else statement starting at line 104
If you are trying to do custom price changes on products in the cart, rather than extend and modify core classes, I use an observer sales_quote_save_before. It works great if you are trying to customize pricing (especially when I have products that can be custom length).
I'm trying to mark a "Processing" order as Complete when I get a certain response back from a third party service. I've got everything set up for this, but the only problem is that orders are staying in the Processing state.
I'm generating an invoice (I don't think I need this though, as each item is marked as "invoiced" in the Magento backend) and a shipment like so:
$order = Mage::getModel('sales/order')... (etc)
$shipment = $order->prepareShipment($quantities);
$shipment->register();
$shipment->setOrder($order);
$shipment->save();
$invoice = $order->prepareInvoice($quantities);
$invoice->register();
$invoice->setOrder($order);
$invoice->save();
This doesn't seem to be doing it though - I get no errors back from this code, but the order remains as processing. In the backend I can still see the "Ship" button at the top of the order, and each item is in the "invoiced" state.
Any tips would be greatly appreciated.
Try
$order->setStateUnprotected('complete',
'complete',
'Order marked as complete automatically',
false);
This method is in app/code/local/Mage/Sales/Model/Order.php (in v1.6.1)
938: public function setStateUnprotected($state, $status = false, $comment = '', $isCustomerNotified = null)
In Magento 1.7.0.0 this method has been removed. Try this instead:
$order->setData('state', "complete");
$order->setStatus("complete");
$history = $order->addStatusHistoryComment('Order marked as complete automatically.', false);
$history->setIsCustomerNotified(false);
$order->save();
You can take a look at this article (in Russian).
Here is the code from the article:
$order = $observer->getEvent()->getOrder();
if (!$order->getId()) {
return false;
}
if (!$order->canInvoice()) {
return false;
}
$savedQtys = array();
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice($savedQtys);
if (!$invoice->getTotalQty()) {
return false;
}
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
$invoice->register();
$invoice->getOrder()->setCustomerNoteNotify(false);
$invoice->getOrder()->setIsInProcess(true);
$transactionSave = Mage::getModel('core/resource_transaction')
->addObject($invoice)
->addObject($invoice->getOrder());
$transactionSave->save();
I'm doing this that way:
$order->setState('complete', true, $this->__('Your Order History Message Here.'))
->save();
Code for processing order programmatically.
Can be put on success event or cron
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
$order->setData('state', Mage_Sales_Model_Order::STATE_COMPLETE);
$order->setStatus(Mage_Sales_Model_Order::STATE_COMPLETE);
$history = $order->addStatusHistoryComment('Order is complete', false);
$history->setIsCustomerNotified(false);
$order->save();
Magento will automatically mark an order as complete if:
Payment has been made.
An invoice exists.
A shipment exists.
If you cannot do that, try to create a custom 'state' and set that. In the meantime, to set the order to processing, try this:
$order = Mage::getModel('sales/order')->load($id);
$order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true)->save();
Should work without errors. Tested in Magento 1.7.0.2
In my case, I needed the end users to see completed in the order grid, but the order state really made no difference. So I did just went to
System->Order Status
Create a new Status called Completed (note the d so it's easy to differentiate)
Assign that status to the state Processing/pending, whatever.
This worked for our client -- but wouldn't work if you heavily depend on order state (Different than order status).