I am trying to get the subtotal amount on checkout success page. It works good for registred users:
$_order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
$amount = $_order->getData('subtotal');
$total = number_format($amount, 2);
But when the order is processed by a guest, $total is empty.
What can be done?
P.S.: I am using Magento 1.6.1 CE
Taken from Magento's app/code/core/Mage/Checkout/Block/Onepage.php:
if (!$this->isCustomerLoggedIn()) {
return $this->getQuote()->getShippingAddress();
} else {
return Mage::getModel('sales/quote_address');
}
I am 99% sure you can do exactly the same with getOrder() and with Mage_Checkout_Block_Success =)
Note: the isCustomerLoggedIn() method is defined at Mage_Checkout_Block_Onepage_Abstract which is not inherited by Mage_Checkout_Block_Success. So, you could simply use its implementation:
public function isCustomerLoggedIn()
{
return Mage::getSingleton('customer/session')->isLoggedIn();
}
E.g. your code now shall look like this:
if (!Mage::getSingleton('customer/session')->isLoggedIn()) {
$order = Mage::getSingleton('checkout/session')->getOrder();
} else {
$order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
}
Sorry for saying non-sense things before...
Related
I just started studying OpenCart, downloaded latest version of opencart and reading the documentation about where to find the function definition of tax calculate function.
In the non admin side, opening any Products shows data with tax calculation. Here is code it uses it.
$this->tax->calculate($product_info['price'], $product_info['tax_class_id'], $this->config->get('config_tax'))
Is there any link to check the location of tax class for checking the calculate function definition?
Not quite sure what exactly do you want to achieve. But the calculate function you can find in system/library/cart/tax.php.
public function calculate($value, $tax_class_id, $calculate = true) {
if ($tax_class_id && $calculate) {
$amount = 0;
$tax_rates = $this->getRates($value, $tax_class_id);
foreach ($tax_rates as $tax_rate) {
if ($calculate != 'P' && $calculate != 'F') {
$amount += $tax_rate['amount'];
} elseif ($tax_rate['type'] == $calculate) {
$amount += $tax_rate['amount'];
}
}
return $value + $amount;
} else {
return $value;
}
}
Although in this file you will find a lot of interesting connected with tax processing in OpenCart.
If this information not enough - please, describe the desired result with more details and I will try to help.
I'm trying to make magento modification when user enter vat number on checkout remove tax from order.
I found a code on stackoverflow which support on magento older version but it not work with new version 1.9,
I made few modifications for work the condition and return 0,even it return 0 checkout still shows tax.
here is my code which is on file
/app/code/core/Mage/Tax/Model/Calculation.php line number 268
public function getRate($request)
{
if (!$request->getCountryId() || !$request->getCustomerClassId() || !$request->getProductClassId()) {
return 0;
}
//my code
$ctax= Mage::getSingleton('checkout/session')->getQuote()->getCustomerTaxvat();
if ($this->getCustomer() && $ctax !='') {
//echo 'test';
return 0;
}
//end my code
$cacheKey = $this->_getRequestCacheKey($request);
if (!isset($this->_rateCache[$cacheKey])) {
$this->unsRateValue();
$this->unsCalculationProcess();
$this->unsEventModuleId();
Mage::dispatchEvent('tax_rate_data_fetch', array(
'request' => $request));
if (!$this->hasRateValue()) {
$rateInfo = $this->_getResource()->getRateInfo($request);
$this->setCalculationProcess($rateInfo['process']);
$this->setRateValue($rateInfo['value']);
} else {
$this->setCalculationProcess($this->_formCalculationProcess());
}
$this->_rateCache[$cacheKey] = $this->getRateValue();
$this->_rateCalculationProcess[$cacheKey] = $this->getCalculationProcess();
}
return $this->_rateCache[$cacheKey];
}
Anyone can help me to make tax 0 when user enters vat number on checkout, Thanks a lot
I've managed to solve my problem by following this thread : Modify tax rate on cart quote items and recalculate
I have added an Observer to the event sales_quote_collect_totals_before.
And here is the content of my observer, very simple :
public function removetax($observer)
{
$customer_id = Mage::getSingleton('customer/session')->getId();
$customer = Mage::getModel("customer/customer")->load($customer_id);
if($customer->getIsTaxExempt() == 1)
{
$items = $observer->getEvent()->getQuote()->getAllVisibleItems();
foreach($items as $item)
$item->getProduct()->setTaxClassId(0);
}
}
If customer is tax exempt, I grab the current cart content and for each item, I set the product tax class to 0. It is mandatory to not save the product or the item. The aim here is to set a value for the following calculation, not to save it in the database. Tax classes need to stay to the initial value in the db.
You can use sales_quote_collect_totals_before event.
then you have to define logic for remove tax on checkout page.
This link you can refer.
Go to Calculation.php and find the calcTaxAmount() and add billing condditions
public function calcTaxAmount($price, $taxRate, $priceIncludeTax = false, $round = true)
{
$billing = Mage::getModel('checkout/session')->getQuote()->getCustomerTaxvat();
if($billing !="")
{
return 0;
}
}
I am using the code below as part of a script to create Magento Orders programatically. The script works fine when I use
freeshipping_freeshipping
as the shipping method. However, when I choose any other shipping method such as a custom shipping method,flatrate_flatrate or usps_1 e.t.c, it gives me the error:
"Please Specify a shipping method"
I have searched everywhere but was unable to find a solution. Any help would be highly appreciated, thanks.
$shippingAddress->setCollectShippingRates(true)->collectShippingRates()
->setShippingMethod($shipping_method);
Edit:
I got it to work with flatrate for non US orders and an extension freeadminshipping on both US and non US orders. However, still unable to use any of the UPS or USPS shipping methods.
This method create Order and I have use this in my project it working. In your code please remove shipping method set code and try I hope that work fine for you. otherwise you can use below my code.
public function createOrderAction($paymentMethod) {
try {
$checkout_session = Mage::getSingleton('checkout/session');
$cq = $checkout_session->getQuote();
$cq->assignCustomer(Mage::getSingleton('customer/session')->getCustomer());
$quoteObj = Mage::getModel('sales/quote')->load($checkout_session->getQuoteId()); // Mage_Sales_Model_Quote
//Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()
$items = $quoteObj->getAllItems();
$quoteObj->reserveOrderId();
// set payment method
$quotePaymentObj = $quoteObj->getPayment(); // Mage_Sales_Model_Quote_Payment
$quotePaymentObj->setMethod($paymentMethod);
$quoteObj->setPayment($quotePaymentObj);
// convert quote to order
$convertQuoteObj = Mage::getSingleton('sales/convert_quote');
$quoteObj->setShippingAddress($cq->getShippingAddress());
$quoteObj->setBillingAddress($cq->getBillingAddress());
$orderObj = $convertQuoteObj->addressToOrder($quoteObj->getShippingAddress());
$orderPaymentObj = $convertQuoteObj->paymentToOrderPayment($quotePaymentObj);
// convert quote addresses
$orderObj->setBillingAddress($convertQuoteObj->addressToOrderAddress($quoteObj->getBillingAddress()));
$orderObj->setShippingAddress($convertQuoteObj->addressToOrderAddress($quoteObj->getShippingAddress()));
// set payment options
$orderObj->setPayment($convertQuoteObj->paymentToOrderPayment($quoteObj->getPayment()));
// convert quote items
foreach ($items as $item) {
// #var $item Mage_Sales_Model_Quote_Item
$orderItem = $convertQuoteObj->itemToOrderItem($item);
$orderItem->setWholesaler($item->getWholesaler());
$orderItem->setComment($item->getComment());
$options = array();
if ($productOptions = $item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct())) {
$options = $productOptions;
}
if ($addOptions = $item->getOptionByCode('additional_options')) {
$options['additional_options'] = unserialize($addOptions->getValue());
}
if ($options) {
$orderItem->setProductOptions($options);
}
if ($item->getParentItem()) {
$orderItem->setParentItem($orderObj->getItemByQuoteItemId($item->getParentItem()->getId()));
}
$orderObj->addItem($orderItem);
}
$orderObj->setCanShipPartiallyItem(false);
$orderObj->place();
$quoteObj->setIsActive(0)->save();
$orderObj->save();
$orderObj->sendNewOrderEmail();
return $orderObj->getId();
} catch (Exception $e){
Mage::log($e->getMessage());
Mage::log($e->getTraceAsString());
}
}
My question is quite simple. I need to change the shipping rate cost in one page checkout to "0" once the user select COD as payment method in one page checkout. I think I can do this easely with an observer. Could you please helpme to know what event should I observe?.
Can I use checkout_controller_onepage_save_shipping_method ?. Any kind of help will be highly appreciated!!
Details Posted By OP as answer
I override the Mage_Checkout_Model_Type_Onepage class and modify the savePayment method. Then I did this:
1.- A first try:
public function savePayment($data)
{
.....
....
$payment = $quote->getPayment();
$payment->importData($data);
$quote->save();
//My custom code
if($data['method']=='cashondelivery'){
$shipping = $quote->getShippingAddress();
$address = $quote->getBillingAddress();
$shipping->addData($address)->setShippingMethod('flatrate_flatrate');
}
Where my flatrate_flatrate is 0. Unfortunately it doesn't work well. This snippet set to 0 my Grant Total.
My second try was:
public function savePayment($data)
{
.....
....
$payment = $quote->getPayment();
$payment->importData($data);
$quote->save();
//My custom code
if($data['method']=='cashondelivery'){
$this->getQuote()->getShippingAddress()->setShippingAmount(0);
$this->getQuote()->getShippingAddress()->setBaseShippingAmount(0);
}
This code works but only a few times, I don't understand why ??.. Could somebody helpme to fix this please?. Any kind of help will be highly appreciated.
Kind regards!
Ok. Now I have this and it works but it doesn't update the grand total amount. Even the order is processed with the normal shipping cost. I mean, finally it doesn't update anything. Could somebody in someway give me a hand on this please?.
if($data['method']=='cashondelivery'){
$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate');
$quote->getShippingAddress()->setShippingAmount(0);
$quote->getShippingAddress()->setBaseShippingAmount(0);
$quote->getShippingAddress()->setShippingInclTax(0);
$quote->getShippingAddress()->setBaseShippingInclTax(0);
$quote->collectTotals();
$quote->save();
}
Warming regards!
Ok, I did something crazy but it seems it works (at least partially). I override Mage_Checkout_OnepageController too and add it a new method call actualizaShippingMethodAction.
It looks like this:
public function actualizaShippingMethodAction()
{
if ($this->_expireAjax()) {
return;
}
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost('shipping_method', '');
$result = $this->getOnepage()->saveShippingMethod($data);
// $result will contain error data if shipping method is empty
if (!$result) {
$this->getOnepage()->getQuote()->collectTotals();
}
$this->getOnepage()->getQuote()->collectTotals()->save();
}
}
Now in my original class that is overriding (Mage_Checkout_Model_Type_Onepage) I did this.
if($data['method']=='cashondelivery'){
$cliente = new Varien_Http_Client();
$_configuracion = array('maxredirects'=>5, 'timeout'=>30);
$llamada = Mage::getBaseUrl()."checkout/onepage/actualizaShippingMethod/";
$cliente->setUri($llamada)
->setConfig($_configuracion)
->setMethod(Zend_Http_Client::POST)
->setParameterPost('shipping_method','flatrate_flatrate');
$respuesta = $cliente->request();
$quote->getShippingAddress()->setShippingAmount(0);
$quote->getShippingAddress()->setBaseShippingAmount(0);
$quote->getShippingAddress()->setShippingInclTax(0);
$quote->getShippingAddress()->setBaseShippingInclTax(0);
$quote->collectTotals()->save();
}
$this->getCheckout()
->setStepData('payment', 'complete', true)
->setStepData('review', 'allow', true);
return array();
Now the order is passing without shipping cost as spected but the order review (summary) is not updating the final costs. And I thinks this solution has a bug because if the user returns and select another payment method the shipping cost is 0 again.
Any kind of help, whatever, will be highly, highly appreciated
THANKS
Finally I have a solution and I think is an answer to the original question. If not please pardon me.
Forget to override savePayment($data) on Mage_Checkout_Model_Type_Onepage. Just focus on overriding Mage_Checkout_OnepageController, and add to the savePaymentAction() method the following code.
$data = $this->getRequest()->getPost('payment', array());
/*Custom code*/
if($data['method']=='cashondelivery'){//Only if payment method is cashondelivery
$result = $this->getOnepage()->savePayment($data);
// get section and redirect data
$redirectUrl = $this->getOnepage()->getQuote()->getPayment()->getCheckoutRedirectUrl();
if (empty($result['error']) && !$redirectUrl) {
$this->loadLayout('checkout_onepage_review');
$result['goto_section'] = 'review';
$result['update_section'] = array(
'name' => 'review',
'html' => $this->_getReviewHtml()
);
}
if ($redirectUrl) {
$result['redirect'] = $redirectUrl;
}
//Update totals for Shipping Methods
$resultado = $this->getOnepage()->saveShippingMethod('flatrate_flatrate');
$this->getOnepage()->getQuote()->collectTotals()->save();
}else{
$result = $this->getOnepage()->savePayment($data);
// get section and redirect data
$redirectUrl = $this->getOnepage()->getQuote()->getPayment()->getCheckoutRedirectUrl();
if (empty($result['error']) && !$redirectUrl) {
$this->loadLayout('checkout_onepage_review');
$result['goto_section'] = 'review';
$result['update_section'] = array(
'name' => 'review',
'html' => $this->_getReviewHtml()
);
}
if ($redirectUrl) {
$result['redirect'] = $redirectUrl;
}
//Return the original values according with the initial user sellection
//I use a session variable to store the original selection
$shippingMethod = Mage::getSingleton('core/session')->getShippingInicial();
$resultado = $this->getOnepage()->saveShippingMethod($shippingMethod);
$this->getOnepage()->getQuote()->collectTotals()->save();
}
} catch (Mage_Payment_Exception $e) {
if ($e->getFields()) {
...
Then you have to override saveShippingMethodAction() and add the following code.
...
$result = $this->getOnepage()->saveShippingMethod($data);
//We store the Shipping Method initial selection
Mage::getSingleton('core/session')->setShippingInicial($data);
// $result will contain error data if shipping method is empty
if (!$result) { ...
If you test this you will find that it works as expected. But now it takes 2 loading times to correctly show the total costs in the review part. I read this question (IWD one page checkout extension Magento: review refresh) but it doesn't help a lot.
Could somebody point me in the right direction to update the review part twice?.
WARMING REGARDS!
Could somebody have an idea how to achieve this?. Regards!
I'm just getting started with dependency injection and I have immediately hit a problem: I have two classes that depend on each other.
The classes are Basket and Shipping.
In my Basket class I have the following relevant methods:
public function totalShipping()
{
return $this->_shipping->rate();
}
public function grandTotal()
{
return $this->totalProductsPrice() + $this->totalShipping();
}
public function totalWeight()
{
$weight = 0;
$products = $this->listProducts();
foreach ($products as $product) {
$weight += $product['product_weight'];
}
return ($weight == '') ? 0 : $weight;
}
$this->_shipping is an instance of the Shipping class
In my Shipping class I have the following relevant methods:
public function rate()
{
if (isset($_SESSION['shipping']['method_id'])) {
$methodId = $_SESSION['shipping']['method_id'];
return $this->_rates[$methodId]['Shipping Price'];
}
// Method not set
return NULL;
}
// Available Methods depend on country and the total weight of products added to the customer's basket. E.g. USA and over 10kg
public function listAvailableMethods()
{
$rates = array();
if (isset($_SESSION['customer']['shipping_address']['country_code'])) {
foreach ($this->_rates as $method_id => $rate) {
if (($_SESSION['customer']['shipping_address']['country_code'] == $rate['Country']) && ($this->_basket->totalWeight() > $rate['Weight From']) && ($this->_basket->totalWeight() < $rate['Weight To'])) {
$rates[$method_id] = $rate;
}
}
}
return $rates;
}
$this->_basket is an instance of the Basket class.
I am totally clueless as to how to resolve this circular dependency. Thank you for your help in advance.
Update
In my Shipping Class I also have this method:
public function setMethod($method_id)
{
// A check to make sure that the method_id is one of the provided methods
if ( !array_key_exists($method_id, $this->listAvailableMethods()) ) return false;
$_SESSION['shipping'] = array(
'method_id' => $method_id
);
}
I have ended up renaming Shipping to Shipping_Methods and I have created a new class called Customer_Shipping_Methods. Essentially Customer_Shipping_Methods could be part of the Basket class but I'd rather keep it separate.
#RyanLaBarre was totally right. I was essentially mixing methods that should have been in the Basket Class with methods in my Shipping_Methods class. Shipping_Methods should have only contained general shipping data methods which were not specific to the current session.
I think what threw me, was that Shipping_Methods sources its data from a csv file rather than a database table. Once I started seeing Shipping_Methods as just another table, it all clicked in my mind.
#rdlowrey that is very good advice. I will be putting my session globals into my controllers immediately!