As a customer, there are two things prioritizing choices of shipping methods. First one, of course, is shipping price and other is delivery date. Since Magento is already showing us shipping prices on the checkout we don’t need to worry about that.
Magento offers us a lot of different shipping possibilities and each one has its own way of communicating and returning shipping details so there is not one single solution for all of them, but for now, we can show you how to do this for FedEx.
Changing FedEx API
Biggest problem we encounter with getting delivery date is that shipping provider as FedEx is not returning that date back to us. To resolve this, we need to request this data from Fedex and to do so, we need to change our API request.
That is why we want to overwrite _formRateRequest method in Mage_Usa_Model_Shipping_Carrier_Fedex class and add “ReturnTransitAndCommit” in API call.
protected function _formRateRequest($purpose)
{
$ratesRequest = parent::_formRateRequest($purpose);
$ratesRequest['ReturnTransitAndCommit'] = true;
return $ratesRequest;
}
Adding this attribute in call will request that Transit Time information is included in the reply from Fedex.
Fedex will return to us delivery timestamp for each method, but to make this more readable and accessible to shipping rate we will overwrite _prepareRateResponse method in same class and split it into date and time.
protected function _prepareRateResponse($response)
{
$costArr = array();
$priceArr = array();
$errorTitle = 'Unable to retrieve tracking';
if (is_object($response)) {
if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') {
if (is_array($response->Notifications)) {
$notification = array_pop($response->Notifications);
$errorTitle = (string)$notification->Message;
} else {
$errorTitle = (string)$response->Notifications->Message;
}
} elseif (isset($response->RateReplyDetails)) {
$allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
if (is_array($response->RateReplyDetails)) {
foreach ($response->RateReplyDetails as $rate) {
$serviceName = (string)$rate->ServiceType;
if (in_array($serviceName, $allowedMethods)) {
$amount = $this->_getRateAmountOriginBased($rate);
$costArr[$serviceName] = $amount;
$priceArr[$serviceName] = $this->getMethodPrice($amount, $serviceName);
$deliveryTimestamp[$serviceName] = $rate->DeliveryTimestamp;
}
}
asort($priceArr);
} else {
$rate = $response->RateReplyDetails;
$serviceName = (string)$rate->ServiceType;
if (in_array($serviceName, $allowedMethods)) {
$amount = $this->_getRateAmountOriginBased($rate);
$costArr[$serviceName] = $amount;
$priceArr[$serviceName] = $this->getMethodPrice($amount, $serviceName);
}
}
}
}
$result = Mage::getModel('shipping/rate_result');
if (empty($priceArr)) {
$error = Mage::getModel('shipping/rate_result_error');
$error->setCarrier($this->_code);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setErrorMessage($errorTitle);
$error->setErrorMessage($this->getConfigData('specificerrmsg'));
$result->append($error);
} else {
foreach ($priceArr as $method=>$price) {
$rate = Mage::getModel('shipping/rate_result_method');
$rate->setCarrier($this->_code);
$rate->setCarrierTitle($this->getConfigData('title'));
$rate->setMethod($method);
$rate->setMethodTitle($this->getCode('method', $method));
$rate->setDeliveryDate(date("l, F d",strtotime($deliveryTimestamp[$method])));
$rate->setDeliveryTime(date("h:i A", strtotime($deliveryTimestamp[$method])));
$rate->setCost($costArr[$method]);
$rate->setPrice($price);
$result->append($rate);
}
}
return $result;
}
Now we made sure that Fedex is returning transit data.
Displaying delivery data
Before we can use this on a template we need to add it to shipping rate. To do this we will overwrite importShippingRate method in Mage_Sales_Model_Quote_Address_Rate class and append our new data to shipping.
public function importShippingRate(Mage_Shipping_Model_Rate_Result_Abstract $rate)
{
$shippingRate = parent::importShippingRate($rate);
if($rate->getDeliveryDate()){
$shippingRate->setDeliveryDate($rate->getDeliveryDate());
$shippingRate->setDeliveryTime($rate->getDeliveryTime());
}
return $shippingRate;
}
Now we can simply access this in checkout\onepage\shipping_method\available.phtml template as $_rate attribute and create our delivery message.
<label for="s_method_<?php echo $_rate->getCode() ?>"><?php echo $this->escapeHtml($_rate->getMethodTitle()) ?>
<?php $_excl = $this->getShippingPrice($_rate->getPrice(), $this->helper('tax')->displayShippingPriceIncludingTax()); ?>
<?php $_incl = $this->getShippingPrice($_rate->getPrice(), true); ?>
<?php echo $_excl; ?>
<?php if ($this->helper('tax')->displayShippingBothPrices() && $_incl != $_excl): ?>
(<?php echo $this->__('Incl. Tax'); ?> <?php echo $_incl; ?>)
<?php endif; ?>
<?php if($_rate->getDeliveryDate()): ?>
<?php echo "Delivery on " . $_rate->getDeliveryDate(). " in " . $_rate->getDeliveryTime(); ?>
<?php endif ?>
</label>
This was a simple modification on an existing call and it gave us one useful feature that makes it easier for a customer to decide what shipping method to use. But there are many cool things that Fedex Api offers that are not used in Magento. I invite you to play with it and give a little more flexibility to your shipping methods.
If you find this useful and would like this functionality on some other shipping method please comment below.
The post When can you deliver? (FedEx) appeared first on Inchoo.