Overview

Namespaces

  • None
  • PHP

Classes

  • Eabi_DpdEE_Block_Adminhtml_Config_Form_Field_Country
  • Eabi_DpdEE_Block_Info_Payment
  • Eabi_DpdEE_Block_Invoice
  • Eabi_DpdEE_Block_Order_Courier
  • Eabi_DpdEE_Helper_Data
  • Eabi_DpdEE_Model_Api
  • Eabi_DpdEE_Model_Button_Courier
  • Eabi_DpdEE_Model_Config
  • Eabi_DpdEE_Model_Flat
  • Eabi_DpdEE_Model_Observer
  • Eabi_DpdEE_Model_Payment_Processor
  • Eabi_DpdEE_Model_Post
  • Eabi_DpdEE_Model_Source_Label_Position
  • Eabi_DpdEE_Model_Source_Service
  • Eabi_Livehandler_Adminhtml_LivehandlerController
  • Eabi_Livehandler_Adminhtml_RemoveController
  • Eabi_Livehandler_Block_Adminhtml_Config_Form_Field_Button
  • Eabi_Livehandler_Block_Adminhtml_Config_Form_Field_Remove
  • Eabi_Livehandler_Block_Email
  • Eabi_LiveHandler_Block_Footer
  • Eabi_Livehandler_Helper_Data
  • Eabi_Livehandler_Helper_Keypair
  • Eabi_Livehandler_IndexController
  • Eabi_Livehandler_Model_Abstract
  • Eabi_Livehandler_Model_Action_Abstract
  • Eabi_Livehandler_Model_Action_Postoffice_Print
  • Eabi_Livehandler_Model_Action_Postoffice_Send
  • Eabi_Livehandler_Model_Adminhtml_Gridmanager
  • Eabi_Livehandler_Model_Directory_Collection
  • Eabi_Livehandler_Model_Entry
  • Eabi_Livehandler_Model_File_Object
  • Eabi_Livehandler_Model_Mysql4_Entry
  • Eabi_Livehandler_Model_Mysql4_Entry_Collection
  • Eabi_Livehandler_Model_Ordergrid
  • Eabi_Livehandler_Model_System_Config_Backend_Button
  • Eabi_Postoffice_Adminhtml_PostofficeController
  • Eabi_Postoffice_Block_Adminhtml_Config_Form_Field_License
  • Eabi_Postoffice_Block_Adminhtml_Config_Form_Field_Remove
  • Eabi_Postoffice_Block_Config_Rebuildbutton
  • Eabi_Postoffice_Helper_Countrycode
  • Eabi_Postoffice_Helper_Data
  • Eabi_Postoffice_IndexController
  • Eabi_Postoffice_Model_Carrier_Abstract
  • Eabi_Postoffice_Model_Carrier_Result
  • Eabi_Postoffice_Model_Carriermodule
  • Eabi_Postoffice_Model_Mysql4_Carriermodule
  • Eabi_Postoffice_Model_Mysql4_Carriermodule_Collection
  • Eabi_Postoffice_Model_Mysql4_Office
  • Eabi_Postoffice_Model_Mysql4_Office_Collection
  • Eabi_Postoffice_Model_Observer
  • Eabi_Postoffice_Model_Office
  • Eabi_Postoffice_Model_Orderview
  • Eabi_Postoffice_Model_Source_Sendevent
  • Eabi_Postoffice_Model_Updater
  • Overview
  • Namespace
  • Class
  • Tree
   1: <?php
   2: /*
   3:   
   4:  *
   5:  * NOTICE OF LICENSE
   6:  *
   7:  * This source file is subject to the Open Software License (OSL 3.0)
   8:  * or OpenGPL v3 license (GNU Public License V3.0)
   9:  * that is bundled with this package in the file LICENSE.txt.
  10:  * It is also available through the world-wide-web at this URL:
  11:  * http://opensource.org/licenses/osl-3.0.php
  12:  * or
  13:  * http://www.gnu.org/licenses/gpl-3.0.txt
  14:  * If you did not receive a copy of the license and are unable to
  15:  * obtain it through the world-wide-web, please send an email
  16:  * to info@e-abi.ee so we can send you a copy immediately.
  17:  *
  18:  * DISCLAIMER
  19:  *
  20:  * Do not edit or add to this file if you wish to upgrade this module to newer
  21:  * versions in the future.
  22:  *
  23:  * @category   Eabi
  24:  * @package    Eabi_Dpd
  25:  * @copyright  Copyright (c) 2014 Aktsiamaailm LLC (http://en.e-abi.ee/)
  26:  * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  27:  * @license    http://www.gnu.org/licenses/gpl-3.0.txt  GNU Public License V3.0
  28:  * @author     Matis Halmann
  29:  * 
  30: 
  31:  */
  32: 
  33: /**
  34:  * <p>Base class for carriers, which ask customer to pick parcel terminal of choice from dropdown list.</p>
  35:  * <p>Offers following business functions:</p>
  36:  * <ul>
  37:      <li>Chosen parcel terminal is forwarded to the Merchant</li>
  38:      <li>Monitors if shipment parcel data is sent to remote server</li>
  39:      <li>Offers PDF packing slip printing function, if subclasses implement actual fetch procedure.</li>
  40:      <li>Offers auto update functionality for parcel terminals if subclasses implement actual parcel terminal fetch procedure</li>
  41:      <li>Offers cash on delivery functionality with help of extra plugins.</li>
  42:  * <li>Offers clickable tracking url or iframe functionality from Magento</li>
  43:  </ul>
  44:  * @author matishalmann
  45:  */
  46: abstract class Eabi_Postoffice_Model_Carrier_Abstract extends Mage_Shipping_Model_Carrier_Abstract {
  47:     
  48:     /**
  49:      * <p>Actual URL can be entered here, where %s in the url would be replaced with supplied tracking number.</p>
  50:      * <p>When tracking number is entered, then user is provided with link to track the status of package on remote server.</p>
  51:      * @var bool|string
  52:      */
  53:     protected $_tracking_url = false;
  54:     
  55:     /**
  56:      * <p>When set to true and $_tracking_url is provided, then instead of clickable link iframe is displayed instead.</p>
  57:      * @var bool
  58:      */
  59:     protected $_track_iframe = false;
  60:     
  61:     /**
  62:      *
  63:      * @var Mage_Sales_Model_Quote
  64:      */
  65:     protected $_quote = false;
  66:     
  67: 
  68:     
  69:     
  70:     /**
  71:      *  <p>This method should be implemented in subclasses of this carrier.</p>
  72:      * <p>Purpose of this method is to return array of Postoffices/Parcel terminals associated to this carrier.</p>
  73:      * <p>This method is called automatically by Magento's cron and the update frequency is regulated by the carriers
  74:      * configuration data of <code>update_interval</code> which is expressed in minutes.</p>
  75:      * <p>Usually the carriers are fetched from some remote location and sometimes the fetching may fail, in this case
  76:      * this method should return boolean false in order to avoid Postoffice list being empty.</p>
  77:      *  
  78:     * <p>Each element contained in this array should have the following structure:
  79:      * <pre>
  80:      * <code>
  81:      *         array(
  82:                     'place_id' => (int)unique remote id for this office (Mandatory),
  83:                     'name' => Unique name for this office (Mandatory),
  84:                     'city' => City where this office is located,
  85:                     'county' => County where this office is located,
  86:                     'description' => Description where this office is located,
  87:                     'country' => Country ID where this office is located format: EN, EE, FI,
  88:                     'zip' => Zip code for this office,
  89:                     'group_sort' => higher number places group higher in the parcel terminal list, defaults to 0,
  90:                 );
  91: 
  92:      * </code>
  93:      * </pre>
  94:      * </p>
  95:      * <p>You can also supply <code>group_sort</code> parameter, if you have it. Offices which have greater group_sort parameter are displayed before
  96:      * other postoffices. Alternatively you can write your own group_sort generator function by overwriting the getGroupSort(group_name) method
  97:      * which should return integer value.</p>
  98:      * <p>It is advised to supply at least city or county parameter, because first select menu will be created from group_name parameters
  99:      * and group_name parameter is basically: county_name/city_name</p>
 100:      * 
 101:      * @return array of postoffices, where each element is assoc array with described structure.
 102:      *  
 103:      */
 104:     abstract public function getOfficeList();
 105:     
 106:     
 107:     /**
 108:      * <p>If you would like to display certain counties or cities before the others, then you can overwrite this function.</p>
 109:      * <p>This function should return positive integer. The greater the number returned means this county/city is more important than the others
 110:      * and should be displayed before the others.</p>
 111:      * <p>In general postoffices will be displayed according to the following rules:
 112:      * <ul>
 113:      * <li>group_sort descending</li>
 114:      * <li>group_name ascending</li>
 115:      * <li>name ascending</li>
 116:      * </ul>
 117:      * </p>
 118:      * <p>This function is called only when getOfficeList function does not supply group_sort parameter</p>
 119:      * 
 120:      * 
 121:      * @param string $group_name county/city or county or city
 122:      * @return int greater value, means this office belongs to more important group.
 123:      */
 124:     public function getGroupSort($group_name) {
 125:         return 0;
 126:     }
 127:     
 128:     /**
 129:      *  <p>This function is called right after:
 130:      * <ul>
 131:      * <li>This carrier is active</li>
 132:      * <li>Cart's max weight does not exceed the limit</li>
 133:      * <li>Cart's min weight is not below the limit</li>
 134:      * </ul>
 135:      * </p>
 136:      * <p>If this function returns false, then this carrier is not available.</p>
 137:      * 
 138:      * @param Mage_Shipping_Model_Rate_Request $request
 139:      * @return boolean false, if this carrier should not be available.
 140:      */
 141:     protected function _isAvailable(Mage_Shipping_Model_Rate_Request $request) {
 142:         return true;
 143:     }
 144:     
 145:     /**
 146:      * <p>If carrier supports external tracking URL's then it should return true</p>
 147:      * @return boolean
 148:      */
 149:     public function isTrackingAvailable() {
 150:         if ($this->getTrackingUrl()) {
 151:             return true;
 152:         }
 153:         return false;
 154:     }
 155:     
 156: 
 157: 
 158:     /**
 159:      * <p>Returns tracking URL for current carrier if one exists.</p>
 160:      * @return bool|string
 161:      */
 162:     public function getTrackingUrl() {
 163:         return $this->_tracking_url;
 164:     }
 165: 
 166:     /**
 167:      * <p>When set to true and $_tracking_url is provided, then instead of clickable link iframe is displayed instead.</p>
 168:      * @return bool
 169:      */
 170:     public function getTrackingInIframe() {
 171:         return $this->_track_iframe;
 172:     }
 173:     
 174:     /**
 175:      * <p>Attempts to display tracking link or tracking iframe if tracking is supported by the carrier and tracking url is available.</p>
 176:      * @param string $number tracking number
 177:      * @return Varien_Object|null
 178:      */
 179:     public function getTrackingInfo($number) {
 180:         if ($this->getTrackingUrl()) {
 181:             $custom = new Varien_Object();
 182: 
 183:             $trackingUrl = sprintf($this->getTrackingUrl(), $number);
 184:             if ($this->getTrackingInIframe()) {
 185: 
 186:                 $custom->setTracking('<iframe src="' . $trackingUrl . '" style="border:0px #FFFFFF none;" name="abc" scrolling="no" frameborder="0" marginheight="0px" marginwidth="0px" height="100%" width="100%"></iframe>');
 187:             } else {
 188:                 $custom->setTracking(sprintf('<a href="%s" target="_blank">%s</a>', $trackingUrl, $this->_getEabi()->__('Tracking URL')));
 189:             }
 190: 
 191:             return $custom;
 192:         }
 193:         return null;
 194:     }
 195: 
 196:     /**
 197:      *  Returns true if this Mage_Shipping_Model_Rate_Request is multishipping.
 198:      * 
 199:      * 
 200:      * @param Mage_Shipping_Model_Rate_Request $request
 201:      * @return boolean 
 202:      */
 203:     protected function _isMultishipping(Mage_Shipping_Model_Rate_Request $request) {
 204:         foreach ($request->getAllItems() as $item) {
 205:             if ($item instanceof Mage_Sales_Model_Quote_Address_Item) {
 206:                 return true;
 207:             }
 208:             break;
 209:         }
 210:         return false;
 211:     }
 212: 
 213: 
 214:     /**
 215:      *  <p>use <code>_isAvailable()</code> function to determine if the carrier is available.</p>
 216:      * <p>use <code>_calculateAdditionalShippingPrice</code> function to calculate any additional shipping cost.</p>
 217:      * 
 218:      *  <p>Checks for the following conditions:
 219:      * <ul>
 220:      * <li>This carrier is active</li>
 221:      * <li>Cart's max weight does not exceed the limit</li>
 222:      * <li>Cart's min weight is not below the limit</li>
 223:      * </ul>
 224:      * </p>
 225:      *  <p>Calculates the shipping price based on the following:
 226:      * <ul>
 227:      * <li>Configurations like <code>enable_free_shipping</code>,<code>free_shipping_from</code> are enabled or disabled </li>
 228:      * <li>Configuration like <code>handling_fee</code> which is the base shipping price.</li>
 229:      * <li>Configuration like <code>handling_action</code> which determines whether the shipping price is based on per order or per item</li>
 230:      * <li>If shopping cart rules specify free shipping.</li>
 231:      * <li>Price found from the conditions above will be passed as second parameter to the function <code>_calculateAdditionalShippingPrice</code> which in turn can alter the shipping price further.</li>
 232:      * </ul>
 233:      * </p>
 234:      * 
 235:      * 
 236:      * @param Mage_Shipping_Model_Rate_Request $request
 237:      * @return boolean|Eabi_Postoffice_Model_Carrier_Result false, if carrier is not available.
 238:      */
 239:     final public function collectRates(Mage_Shipping_Model_Rate_Request $request) {
 240:         //determine if this shipping method is available
 241:         $addressId = (string)$this->getAddressId($request);
 242:         
 243:         
 244:         if (!$this->getConfigData('active')) {
 245:             $this->clearAddressId($addressId);
 246:             return false;
 247:         }
 248:         if ($this->getConfigData('use_per_item_weight')) {
 249:             //we compare each item individually
 250:             //if any of the items is overweight, disable
 251:             //if any of the items is underweight, disable
 252:             $loadedProductWeights = array();
 253:             if ($this->getConfigData('max_package_weight') > 0 || $this->getConfigData('min_package_weight') > 0) {
 254:                 //get request items
 255:                 if ($request->getAllItems()) {
 256:                     foreach ($request->getAllItems() as $requestItem) {
 257:                         $productToWeight = $this->_getProductModel()->load($requestItem->getProduct()->getId());
 258:                         for ($i = 0; $i < $requestItem->getQty(); $i++) {
 259:                             $loadedProductWeights[] = $productToWeight->getWeight();
 260:                         }
 261:                     }
 262:                 }
 263:             }
 264:             if ($this->getConfigData('max_package_weight') > 0) {
 265:                 if (max($loadedProductWeights) > (float) $this->getConfigData('max_package_weight')) {
 266:                     $this->clearAddressId($addressId);
 267:                     return false;
 268:                 }
 269:             }
 270:             
 271:             if ($this->getConfigData('min_package_weight') > 0) {
 272:                 if (min($loadedProductWeights) < (float) $this->getConfigData('min_package_weight')) {
 273:                     $this->clearAddressId($addressId);
 274:                     return false;
 275:                 }
 276:             }
 277:             $request->setEabiProductWeights($loadedProductWeights);
 278:             
 279:         } else {
 280:             //we summarize weight of all cart and apply the weight rule
 281:             //total cart is overweight, disable
 282:             //total cart is underweight, disable
 283:             if ($this->getConfigData('max_package_weight') > 0) {
 284:                 if ($request->getPackageWeight() > (float) $this->getConfigData('max_package_weight')) {
 285:                     $this->clearAddressId($addressId);
 286:                     return false;
 287:                 }
 288:             }
 289:             if ($this->getConfigData('min_package_weight') > 0) {
 290:                 if ($request->getPackageWeight() < (float) $this->getConfigData('min_package_weight')) {
 291:                     $this->clearAddressId($addressId);
 292:                     return false;
 293:                 }
 294:             }
 295:         }
 296: 
 297:         $isAvailable = $this->_isAvailable($request);
 298:         if ($isAvailable === false) {
 299:             $this->clearAddressId($addressId);
 300:             return false;
 301:         }
 302:         
 303:         //determine the shipping price
 304:         $price = 0;
 305:         
 306:         //fetch the base handling fee
 307:         $handlingFee = (float)str_replace(',', '.', $this->getConfigData('handling_fee'));
 308:         //shipping method is available. Find the price.
 309:         $isFree = false;
 310:         
 311:         //if we have defined free shipping from certain cart subtotal level
 312:         if ($this->getConfigData('enable_free_shipping') && $request->getPackageValueWithDiscount() >= $this->getConfigData('free_shipping_from')) {
 313:             $price = 0;
 314:             $isFree = true;
 315:         }
 316:         
 317:         //if there is free shipping defined by shopping cart rule
 318:         if ($request->getFreeShipping() === true && !$isFree) {
 319:             $isFree = true;
 320:         }
 321: 
 322:         if (!$isFree) {
 323:             $freeBoxes = 0;
 324:             //if there are any free boxes defined by shopping cart rule
 325:             foreach ($request->getAllItems() as $item) {
 326:                 if ($item->getFreeShipping() && !$item->getProduct()->isVirtual()) {
 327:                     $freeBoxes += $item->getQty();
 328:                 }
 329:             }
 330:             $this->setFreeBoxes($freeBoxes);
 331:         }
 332:         
 333:         
 334:         //if there is no free shipping, attempt to calcualte the price
 335:         //on per order or per item basis
 336:         if ($this->getConfigData('handling_action') == 'O' && !$isFree) {
 337:             //handling action per_order basis
 338:             $price = $handlingFee;
 339:         } else if ($this->getConfigData('handling_action') == 'P' && !$isFree) {
 340:             //handling action per item basis
 341:             if ($this->getConfigData('use_per_item_weight')) {
 342:                 //calculate number of packages first
 343:                 $price = ($this->_getOfficeHelper()->getNumberOfPackagesFromItemWeights($loadedProductWeights, $this->getConfigData('max_package_weight'))  - $this->getFreeBoxes()) * $handlingFee;
 344:                 
 345:             } else {
 346:                 $price = ($request->getPackageQty() * $handlingFee) - ($this->getFreeBoxes() * $handlingFee);
 347:             }
 348:             if ($price == 0) {
 349:                 $isFree = true;
 350:             }
 351:         } else if (!$isFree) {
 352:             //handling action type could not be detected, return false
 353:             //shipping method not available
 354:             $this->clearAddressId($addressId);
 355:             
 356:             return false;
 357:         }
 358:         
 359:         //if there is any additional logic for calculating the price
 360:         if (!$isFree) {
 361:             $price = $this->_calculateAdditionalShippingPrice($request, $price);
 362:         }
 363:         if ($price === false) {
 364:             return false;
 365:         }
 366:         Mage::dispatchEvent('eabi_postoffice_collect_rates_terminals_load_before', array(
 367:             'request' => $request,
 368:             'shipment_method' => $this,
 369:         ));
 370:         
 371:         if ($request->getCancelRateCollection()) {
 372:             return false;
 373:         }
 374:         $session = Mage::getSingleton('core/session');
 375:         
 376:         $this->registerAddressId($addressId);
 377: 
 378:         
 379:         
 380:         $result = Mage::getModel('eabi_postoffice/carrier_result');
 381:         //list the offices
 382:         $method = Mage::getModel('shipping/rate_result_method');
 383:         $method->setCarrier($this->_code);
 384:         $method->setCarrierTitle($this->getConfigData('title'));
 385:         
 386:         $method->setMethod($this->_code);
 387:         
 388:         //if COD is enabled, then add COD fee on top of the shipping price
 389:         $price += $this->_applyPriceFromCod($request);
 390:         
 391:         $method->setPrice($price);
 392:         $loadingText = Mage::helper('eabi_postoffice')->__('Loading offices...');
 393:         $html = '';
 394:         if ($this->_isMultishipping($request)) {
 395:             $html .= '<div id="eabi_carrier_'.$addressId.'_'.$this->_code.'" class="eabi_carrier eabi_carrier_' . $this->_code. '" style="display:inline-block;">'.$loadingText.'</div>';
 396:         } else {
 397:             $html .= '<div id="eabi_carrier_'.$this->_code.'" style="display:inline-block;"  class="eabi_carrier eabi_carrier_' . $this->_code. '"></div>';
 398:         }
 399:         $url = Mage::getUrl('eabi_postoffice/index/office', array('_secure' => true));
 400:         
 401:         if (Mage::app()->getStore()->isAdmin()) {
 402:             $url = Mage::helper('adminhtml')->getUrl('eabi_postoffice/adminhtml_postoffice/office', array('store_id' => $request->getStoreId(), '_secure' => true));
 403:         }
 404:         
 405:         $carrierId = 's_method_'.$this->_code.'_'.$this->_code;
 406:         $divId = 'eabi_carrier_'.$this->_code;
 407:         if ($this->_isMultishipping($request)) {
 408:             $carrierId = 's_method_'.$addressId.'_'.$this->_code.'_'.$this->_code;
 409:             $divId = 'eabi_carrier_'.$addressId.'_'.$this->_code;
 410:         }
 411:         $carrierCode = $this->_code;
 412:         
 413:         $html .= <<<EOT
 414:         <script type="text/javascript">
 415:             /* <![CDATA[ */
 416:                 $('{$carrierId}').writeAttribute('value', '');
 417:                 new Ajax.Request('{$url}', {
 418:                     method: 'post',
 419:                     parameters: {
 420:                         carrier_id: '{$carrierId}',
 421:                         carrier_code: '{$carrierCode}',
 422:                         div_id: '{$divId}',
 423:                         address_id: '{$addressId}',
 424:                     },
 425:                     onSuccess: function(transport) {
 426:                         $('{$divId}').update(transport.responseJSON.html);
 427:                     }
 428:                     });
 429:             /* ]]> */
 430:         </script>
 431: EOT;
 432:         $method->setMethodTitle($html);
 433:         $terminalsCollection = $this->getTerminals();
 434:         if ($terminalsCollection->count() == 1) {
 435:             //if we have only one terminal in the collection, then do not create select drop downs.
 436:             //just render the single element and return the result.
 437:             $office = $terminalsCollection->getFirstItem();
 438:             $method->setMethodTitle($this->getTerminalTitle($office));
 439:             $method->setCarrier($this->_code);
 440:             $method->setCarrierTitle($this->getConfigData('title'));
 441:         
 442:             $method->setMethod($this->_code.'_'.$office->getRemotePlaceId());
 443:             $result->append($method);
 444:             return $result;
 445:         }
 446:         
 447: 
 448:         $result->append($method);
 449:         
 450:         
 451:         $addedMethods = array();
 452:         //try to see, if we have any extra methods stored in a session
 453:         $sessionData = $session->getData('eabi_carrier_' . $this->_code);
 454:         $shippingAddress = $this->_getAddressModel()->load($addressId);
 455:         if (is_array($sessionData) && isset($sessionData[$addressId])) {
 456:             foreach ($sessionData[$addressId] as $subCarrier) {
 457:                 
 458:                 if (isset($subCarrier['country_id']) && $subCarrier['country_id'] != $shippingAddress->getCountryId()) {
 459:                     //on country mismatch do not append the method
 460:                     
 461:                     
 462:                     continue;
 463:                 }
 464:                 $method = Mage::getModel('shipping/rate_result_method');
 465:                 $method->setCarrier($subCarrier['carrier']);
 466:                 $method->setCarrierTitle($subCarrier['carrier_title']);
 467:                 $addedMethods[$subCarrier['method']] = $subCarrier['method'];
 468: 
 469:                 $method->setMethod($subCarrier['method']);
 470:                 $method->setMethodTitle($subCarrier['method_title']);
 471:                 $method->setPrice($price);
 472:                 $result->append($method);
 473:             }
 474:         }
 475: 
 476:         //TODO: add the method if we are able to detect the postoffice automatically
 477:         $additionalOffices = $this->getOfficesFromAddress($request);
 478:         foreach ($additionalOffices as $office) {
 479:             $methodName = $this->_code .'_' .$office->getRemotePlaceId();
 480:             if (!isset($addedMethods[$methodName])) {
 481:                 $method = Mage::getModel('shipping/rate_result_method');
 482:                 $method->setCarrier($this->_code);
 483:                 $method->setCarrierTitle($this->getConfigData('title'));
 484:                 $addedMethods[$methodName] = $method;
 485: 
 486:                 $method->setMethod($methodName);
 487:                 $method->setMethodTitle($this->getAdminTerminalTitle($office));
 488:                 $method->setPrice($price);
 489:                 $result->append($method);
 490:                 
 491:             }
 492:         }
 493: 
 494: 
 495:         return $result;
 496:         
 497:     }
 498:     
 499:     /**
 500:      * <p>Returns true if cash on delivery is specified for target address</p>
 501:      * @param Mage_Customer_Model_Address $address
 502:      * @return bool
 503:      */
 504:     public function isCodEnabled($address) {
 505:         return $this->getConfigData('enable_cod');
 506:     }
 507:     
 508:     
 509:     /**
 510:      * <p>Applies extra price from Cash on Delivery, which is added on top of shipping price</p>
 511:      * @param Mage_Shipping_Model_Rate_Request $request
 512:      * @return double|int
 513:      */
 514:     protected function _applyPriceFromCod(Mage_Shipping_Model_Rate_Request $request) {
 515:         if ($this->_getQuote() && !$this->_getQuote()->isVirtual() && $this->getConfigData('enable_cod') && $this->_getQuote()->getPayment() && $this->_getQuote()->getPayment()->getMethod() && $this->_getQuote()->getPayment()->getMethod() == 'eabicodpayment' && strpos($this->_getQuote()->getShippingAddress()->getShippingMethod(), $this->getCarrierCode()) === 0) {
 516: 
 517:             return $this->getConfigData('cod_fee');
 518:         }
 519:         return 0;
 520:     }
 521: 
 522:     /**
 523:      * <p>Registers current address id in session, so no outsiders could tamper with selected parcel terminal data.</p>
 524:      * @param string $addressId
 525:      * @return Eabi_Postoffice_Model_Carrier_Abstract
 526:      */
 527:     private function registerAddressId($addressId) {
 528:         $addressId = (string)$addressId;
 529:         $session = Mage::getSingleton('core/session');
 530:         $sessionData = $session->getData('eabi_allowedcarriers');
 531:         if (!is_array($sessionData)) {
 532:             $sessionData = array();
 533:         }
 534:         if (!isset($sessionData[$addressId])) {
 535:             $sessionData[$addressId] = array();
 536:         }
 537:         if (!isset($sessionData[$addressId][$this->_code])) {
 538:             $sessionData[$addressId][$this->_code] = $this->_code;
 539:         }
 540:         $session->setData('eabi_allowedcarriers', $sessionData);
 541:         return $this;
 542:     }
 543:     
 544:     /**
 545:      *  Security  related, used to prevent customer to enter arbitrary data as their shipping carrier.
 546:      * 
 547:      * 
 548:      * @param int $addressId
 549:      * @return boolean 
 550:      */
 551:     final public function isAjaxInsertAllowed($addressId) {
 552:         $addressId = (string)$addressId;
 553:         $session = Mage::getSingleton('core/session');
 554:         $sessionData = $session->getData('eabi_allowedcarriers');
 555:         if (is_array($sessionData) && isset($sessionData[$addressId]) && isset($sessionData[$addressId][$this->_code])) {
 556:             return true;
 557:         }
 558:         return false;
 559:     }
 560:     
 561:     /**
 562:      * <p>After successful checkout all entered parcel terminal data should be cleared by calling this function.</p>
 563:      * @param string $addressId
 564:      * @return Eabi_Postoffice_Model_Carrier_Abstract
 565:      */
 566:     private function clearAddressId($addressId) {
 567:         $addressId = (string)$addressId;
 568:         $session = Mage::getSingleton('core/session');
 569:         $sessionData = $session->getData('eabi_allowedcarriers');
 570:         if (is_array($sessionData) && isset($sessionData[$addressId]) && isset($sessionData[$addressId][$this->_code])) {
 571:             unset($sessionData[$addressId][$this->_code]);
 572:         }
 573:         return $this;
 574:     }
 575:     
 576:     /**
 577:      *  <p>This function is called right after the initial price calculation by the </code>collectRates</code> has been called.</p>
 578:      * <p>Overwrite this function if you want to apply more complicated price calculation rules, than </code>collectRates</code>
 579:      * function offers.</p>
 580:      * 
 581:      * 
 582:      * 
 583:      * @param Mage_Shipping_Model_Rate_Request $request
 584:      * @param float $price pre-calculated price by the </code>collectRates</code> function.
 585:      * @return float new price, this carrier should have. 
 586:      */
 587:     protected function _calculateAdditionalShippingPrice(Mage_Shipping_Model_Rate_Request $request, $price) {
 588:         return $price;
 589:     }
 590:     
 591:     /**
 592:      * <p>Overwrite this function in your subclass if you would like to offer automatic postoffice selection based on the user entered address.</p>
 593:      *
 594:      * ["dest_country_id"] => string(2) "EE" 
 595:      * ["dest_region_id"] => string(3) "345" 
 596:      * ["dest_region_code"] => string(5) "EE-57" 
 597:      * ["dest_street"] => string(11) "mina ei tea" 
 598:      * ["dest_city"] => string(7) "tallinn" 
 599:      * ["dest_postcode"] => string(5) "12345" 
 600:      * ["package_value"] => float(16.33) 
 601:      * ["package_value_with_discount"] => float(16.33) 
 602:      * ["package_weight"] => float(16.16) 
 603:      * ["package_qty"] => int(2) 
 604:      * ["package_physical_value"] => float(16.33) 
 605:      * ["free_method_weight"] => float(16.16) 
 606:      * ["store_id"] => string(1) "2" 
 607:      * ["website_id"] => string(1) "1" 
 608:      * ["free_shipping"] => int(0) 
 609:      * ["base_currency (Mage_Directory_Model_Currency)"] => array(1) { ["currency_code"] => string(3) "EUR" } 
 610:      * ["package_currency (Mage_Directory_Model_Currency)"] => array(1) { ["currency_code"] => string(3) "EUR" } 
 611:      * ["country_id"] => string(2) "EE" 
 612:      * ["region_id"] => string(1) "0" 
 613:      * ["city"] => string(0) "" 
 614:      * ["postcode"] => string(0) "" 
 615:      * 
 616:      * @param Mage_Shipping_Model_Rate_Request $request
 617:      * @return array of 'eabi_postoffice/office' models belonging to this carrier.
 618:      */
 619:     protected function getOfficesFromAddress(Mage_Shipping_Model_Rate_Request $request) {
 620:         return array();
 621:     }
 622:     
 623:     /**
 624:      *  <p>Returns distinct group_name,group_id,group_sort as Eabi_Postoffice_Model_Mysql4_Office_Collection of 'eabi_postoffice/office' models</p>
 625:      * <p>Result of this function is used to render the first select menu (county/city) for this carrier.</p>
 626:      * <p>If no groups can be found, then this function returns boolean false.</p>
 627:      * 
 628:      * 
 629:      * @param int $addressId when supplied then only groups from the addressId country are returned.
 630:      * @return boolean|array 
 631:      */
 632:     public function getGroups($addressId = null) {
 633:         if( $this->getConfigData('drop_menu_selection')){
 634:             return false;
 635:         }
 636:         $groups = Mage::getModel('eabi_postoffice/office')->getCollection()
 637:                 ->distinct(true)
 638:                 ->addFieldToFilter('remote_module_name', $this->_code);
 639:         $groups->getSelect()->reset(Zend_Db_Select::COLUMNS)
 640:                 ->columns(array('group_id', 'group_name', 'group_sort'));
 641:         $groups->addOrder('group_sort', 'DESC');
 642:         $groups->addOrder('group_name', 'ASC');
 643:         if ($addressId) {
 644:             $address = $this->_getAddressModel()->load($addressId);
 645:             if ($address->getCountryId()) {
 646:                 $groups->addFieldToFilter('country', $address->getCountryId());
 647:             }
 648:         }
 649:         
 650:         
 651:         if ($groups->count() <= 1) {
 652:             return false;
 653:         }
 654:         return $groups;
 655:     }
 656: 
 657:     /**
 658:      * 
 659:      *  <p>Returns Eabi_Postoffice_Model_Mysql4_Office_Collection which should contain the actual postoffices
 660:      * which belong to the selected group_id in alplabetically sorted order.</p>
 661:      * <p>If no $groupId is supplied, then all the postoffices are returned.</p>
 662:      * <p>Offices are sorted by</p>
 663:      * <ul>
 664:          <li>group_sort descending</li>
 665:          <li>group_name ascending</li>
 666:          <li>name ascending</li>
 667:      </ul>
 668:      * @param int $groupId
 669:      * @param int $addressId when supplied then only offices from the addressId country are returned.
 670:      * @return Eabi_Postoffice_Model_Mysql4_Office_Collection
 671:      * @see Eabi_Postoffice_Model_Carrier_Abstract::getGroupSort()
 672:      */
 673:     public function getTerminals($groupId = null, $addressId = null) {
 674:         $terminals = Mage::getModel('eabi_postoffice/office')->getCollection()
 675:                 ->addFieldToFilter('remote_module_name', $this->_code)
 676:                 ->addOrder('group_sort', 'DESC')
 677:                 ->addOrder('group_name', 'ASC')
 678:                 ->addOrder('name', 'ASC')
 679:         ;
 680:         
 681:         if ($addressId) {
 682:             $address = $this->_getAddressModel()->load($addressId);
 683:             if ($address->getCountryId()) {
 684:                 $terminals->addFieldToFilter('country', $address->getCountryId());
 685:             }
 686:         }
 687:         
 688:         if ($groupId !== null) {
 689:             $terminals->addFieldToFilter('group_id', $groupId);
 690:         }
 691:         return $terminals;
 692:     }
 693:     
 694:     
 695:     /**
 696:      *  <p>Returns the selected postoffice by it's place id.<p>
 697:      * <p>If no postoffice found, then returns boolean false.</p>
 698:      * 
 699:      * @param int $placeId
 700:      * @return Eabi_Postoffice_Model_Office|boolean false 
 701:      */
 702:     public function getTerminal($placeId) {
 703:         $places = Mage::getModel('eabi_postoffice/office')->getCollection()
 704:                 ->addFieldToFilter('remote_module_name', $this->_code)
 705:                 ->addFieldToFilter('remote_place_id', $placeId);
 706:         if ($places->count() == 1) {
 707:             return $places->getFirstItem();
 708:         }
 709:         return false;
 710:     }
 711: 
 712:     /**
 713:      *  Determines how name of each postoffice in the second select menu should be rendered.
 714:      * 
 715:      * 
 716:      * @param Eabi_Postoffice_Model_Office $office
 717:      * @return string 
 718:      */
 719:     public function getTerminalTitle(Eabi_Postoffice_Model_Office $office) {
 720:         return htmlspecialchars($office->getName());
 721:     }
 722:     /**
 723:      *  Determines how name of each county/city in the first select menu should be rendered.
 724:      * 
 725:      * 
 726:      * @param Eabi_Postoffice_Model_Office $office
 727:      * @return string 
 728:      */
 729:     public function getGroupTitle(Eabi_Postoffice_Model_Office $office) {
 730:         return htmlspecialchars($office->getGroupName());
 731:     }
 732:     
 733:     
 734:     /**
 735:      * <p>Should return extra comment for the selected postoffice. For example shipping time.</p>
 736:      * <p>Extra comment is displayed next to select menu just before price display</p>
 737:      * <p>Returning boolean false causes comment to be hidden</p>
 738:      * @param Eabi_Postoffice_Model_Office $office
 739:      * @return boolean|string
 740:      */
 741:     public final function getTerminalComment(Eabi_Postoffice_Model_Office $office) {
 742:         $terminalCommentResult = new Varien_Object(array(
 743:             'comment' => false,
 744:             'is_error' => false,
 745:         ));
 746:         //get descriptional message (not to do it now)
 747:         //get future shipping date -> supply start date as parameter
 748:         //get disabled with message
 749:         
 750:         $shippingTimestamp = $this->_getDeliveryTime($office);
 751:         if ($shippingTimestamp !== false && $this->getConfigData('show_delivery_time')) {
 752:             $date = date('d.m.Y', $shippingTimestamp);
 753:             $time = date('H:i', $shippingTimestamp);
 754:             $dateDiff = (int)(($this->__removeTimePart($shippingTimestamp) - $this->__removeTimePart(time())) / 86400);
 755:             switch ($dateDiff) {
 756:                 case 0:
 757:                     $date = $this->_getOfficeHelper()->__('today');
 758:                     break;
 759:                 case 1:
 760:                     $date = $this->_getOfficeHelper()->__('tomorrow');
 761:                     break;
 762:                 case 2:
 763:                     $date = $this->_getOfficeHelper()->__('day after tomorrow');
 764:                     break;
 765:             }
 766:             if ($time == '00:00') {
 767:                 $terminalCommentResult->setComment($this->_getOfficeHelper()->__('Delivery on %s', $date));
 768:             } else {
 769:                 $terminalCommentResult->setComment($this->_getOfficeHelper()->__('Delivery on %1$s by %2$s', $date, $time));
 770:             }
 771:         }
 772:         
 773:         //if we have an error
 774:         $disabledComment = $this->_getDisabledComment($office);
 775:         
 776:         if ($disabledComment) {
 777:             $terminalCommentResult->setIsError(true);
 778:             $terminalCommentResult->setComment($disabledComment);
 779:             
 780:             //remove selected shipping method (todo at some later date)
 781:             
 782:         }
 783:         
 784:         Mage::dispatchEvent('eabi_' . $this->_code . '_get_terminal_comment', array(
 785:             'selected_office' => $office,
 786:             'shipment_method' => $this,
 787:             'terminal_comment_result' => $terminalCommentResult,
 788:         ));
 789:         
 790:         return $terminalCommentResult;
 791:     }
 792:     
 793:     /**
 794:      * <p>Returns calculated delivery time for the specified office</p>
 795:      * <p>If no delivery time calculation is available, then boolean FALSE is returned</p>
 796:      * @param Eabi_Postoffice_Model_Office $office
 797:      * @return boolean|int
 798:      */
 799:     protected function _getDeliveryTime(Eabi_Postoffice_Model_Office $office) {
 800:         return false;
 801:     }
 802:     
 803:     /**
 804:      * <p>Should return string text, when specified pickup-point is disabled.</p>
 805:      * <p>If specified pickup-point should not be disabled then this method returns boolean FALSE</p>
 806:      * @param Eabi_Postoffice_Model_Office $office
 807:      * @return boolean|string
 808:      */
 809:     protected function _getDisabledComment(Eabi_Postoffice_Model_Office $office) {
 810:         return false;
 811:     }
 812:     
 813:     
 814:     
 815:     
 816:     
 817:     protected function _getStartingDayStamp($timestamp) {
 818:         $limitTime = $this->getConfigData('same_day_time_limit');
 819:         if (!$limitTime) {
 820:             return null;
 821:         }
 822:         $resultTimestamp = $timestamp;
 823:         
 824:         $currentTimeParts = explode(',', date('H,i,s', $timestamp));
 825:         $limitTimeParts = explode(',', $limitTime);
 826:         $weekDayToLook = (int)date('N', $timestamp);
 827:         //1 = monday
 828:         //7 = sunday
 829:         
 830:         
 831:         if ($this->_getSeconds($currentTimeParts) > $this->_getSeconds($limitTimeParts)) {
 832:             //first day is tomorrow
 833:             $weekDayToLook++;
 834:             $resultTimestamp += (int)(24 * 3600);
 835:         } else {
 836:             //first day is today
 837:         }
 838:         
 839:         if ($weekDayToLook > 7) {
 840:             $weekDayToLook -= 7;
 841:         }
 842:         
 843:         
 844:         return $this->__removeTimePart($resultTimestamp);
 845:         
 846:     }
 847:     
 848:     
 849:     /**
 850:      * <p>Removes hours, minutes, seconds from specified timestamp and returns the result</p>
 851:      * @param int $timestamp
 852:      * @return int
 853:      */
 854:     private function __removeTimePart($timestamp) {
 855:         $dateParts = explode(',', date('d,m,Y', $timestamp));
 856:         return mktime(0, 0, 0, $dateParts[1], $dateParts[0], $dateParts[2]);
 857:     }
 858:     
 859:     
 860:     /**
 861:      *  Determines how name of customer selected postoffice should be rendered and this is also how merchant sees the selected postoffice.
 862:      * 
 863:      * 
 864:      * @param Eabi_Postoffice_Model_Office $office
 865:      * @return string 
 866:      */
 867:     public function getAdminTerminalTitle(Eabi_Postoffice_Model_Office $office) {
 868:         $name = $office->getName();
 869:         if ($office->getGroupName() != '') {
 870:             $name = $office->getGroupName().' - '.$office->getName();
 871:         }
 872:         return htmlspecialchars($name);
 873:     }
 874:     
 875:     
 876:     /**
 877:      *
 878:      * Used to fetch the price from 'sales/quote_address_rate' database table.
 879:      * 
 880:      * @param type $addressId
 881:      * @return boolean 
 882:      */
 883:     final protected function getPriceFromAddressId($addressId) {
 884:         $calculatedPriceModelCollection = Mage::getModel('sales/quote_address_rate')
 885:                 ->getCollection()
 886:                 ->addFieldToFilter('address_id', $addressId)
 887:                 ->addFieldToFilter('carrier', $this->_code)
 888:                 ->addFieldToFilter('code', $this->_code . '_' . $this->_code)
 889:         ;
 890:         if ($calculatedPriceModelCollection->count() == 1) {
 891:             return $calculatedPriceModelCollection->getFirstItem()->getPrice();
 892:         }
 893:         return false;
 894:     }
 895:     
 896:     /**
 897:      *  <p>Initially this carrier does not set up all the shipping methods for this carrier in the 'sales/quote_address_rate' database table.
 898:      * since storing too many methods in there is not the smartest thing to do</p>
 899:      * <p>So once the user selects the actual office, an AJAX callback is performed and this one inserts the selected office to the database
 900:      * and also to the session, in order the customer would easily reach latest selected offices and the order itself could be placed,
 901:      * since user selected postoffices have to exist in the 'sales/quote_address_rate' database table.</p>
 902:      * <p>This one results in less entries in 'sales/quote_address_rate' database table.</p>
 903:      * 
 904:      * 
 905:      * @param int $addressId
 906:      * @param Eabi_Postoffice_Model_Office $office
 907:      * @throws Exception 
 908:      */
 909:     final public function setOfficeToSession($addressId, Eabi_Postoffice_Model_Office $office) {
 910:         
 911:         $addressRateModelCollection = Mage::getModel('sales/quote_address_rate')
 912:                 ->getCollection()
 913:                 ->addFieldToFilter('address_id', $addressId)
 914:                 ->addFieldToFilter('carrier', $this->_code)
 915:                 ->addFieldToFilter('code', $this->_code . '_' . $this->_code . '_' . $office->getRemotePlaceId())
 916:         ;
 917:         if ($addressRateModelCollection->count() == 0) {
 918:             //insert
 919:             $newRate = Mage::getModel('sales/quote_address_rate');
 920:             $newRate->setData('address_id', $addressId);
 921:             $newRate->setData('carrier', $this->_code);
 922:             $newRate->setData('country_id', $office->getCountry());
 923:             $newRate->setData('code', $this->_code . '_' . $this->_code . '_' . $office->getRemotePlaceId());
 924:             $newRate->setData('method', $this->_code . '_' . $office->getRemotePlaceId());
 925:             
 926: 
 927:             $title = $this->getAdminTerminalTitle($office);
 928: 
 929:             $newRate->setData('carrier_title', $this->getConfigData('title'));
 930:             $newRate->setData('method_title', $title);
 931:             $price = $this->getPriceFromAddressId($addressId);
 932:             if ($price === false) {
 933:                 throw new Exception('Cannot calculate price');
 934:             }
 935:             $newRate->setPrice($price);
 936:             $newRate->save();
 937:             $session = Mage::getSingleton('core/session');
 938:             $sessionData = $session->getData('eabi_carrier_' . $this->_code);
 939:             if (!is_array($sessionData)) {
 940:                 $sessionData = array();
 941:             }
 942:             if (!isset($sessionData[(string)$addressId])) {
 943:                 $sessionData[(string)$addressId] = array();
 944:             }
 945:             if ($this->getConfigData('disable_session')) {
 946:                 foreach ($sessionData[(string)$addressId] as $k => $v) {
 947:                     if ($k != $this->_code) {
 948:                         unset($sessionData[(string)$addressId][$k]);
 949:                     }
 950:                 }
 951:                 
 952:             }
 953:             $sessionData[(string)$addressId][$this->_code . '_' . $this->_code . '_' . $office->getRemotePlaceId()] = $newRate->debug();
 954:             $session->setData('eabi_carrier_' . $this->_code, $sessionData);
 955:         }
 956:     }
 957: 
 958:     /**
 959:      *  Clears all the session data created by this carrier.
 960:      * 
 961:      * 
 962:      * @return \Eabi_Postoffice_Model_Carrier_Abstract 
 963:      */
 964:     final public function clearSession() {
 965:         Mage::getSingleton('core/session')->unsetData('eabi_allowedcarriers');
 966:         Mage::getSingleton('core/session')->unsetData('eabi_carrier_' . $this->_code);
 967:         return $this;
 968:     }
 969:     
 970: 
 971: 
 972:     /**
 973:      * <p>Sets Magento store config for current carrier specified by key</p>
 974:      * @param string $key
 975:      * @param mixed $value
 976:      * @return Eabi_Postoffice_Model_Carrier_Abstract|boolean
 977:      */
 978:     public function setConfigData($key, $value) {
 979:         if (empty($this->_code)) {
 980:             return false;
 981:         }
 982:         Mage::helper('eabi')->setConfigData('carriers/'.$this->_code.'/'.$key, $value);
 983:         return $this;
 984:     }
 985:     
 986:     /**
 987:      *  Should return true, when this carrier can automatically send shipment data to third party carrier server.
 988:      * 
 989:      * 
 990:      * @return bool
 991:      */
 992:     public function isAutoSendAvailable() {
 993:         return (bool)$this->getConfigData('senddata_enable');
 994:     }
 995:     
 996:     /**
 997:      * <p>Should return the actual generated barcode by the third party carrier server.
 998:      * Overwrite this method in the subclass.</p>
 999:      * <p>This function is available to the merchant, if he/she wants to print the packing slip in the order view.</p>
1000:      * 
1001:      * 
1002:      * 
1003:      * @param Mage_Sales_Model_Order $order order, to get the barcode for.
1004:      * @return boolean|string 
1005:      */
1006:     public function getBarcode(Mage_Sales_Model_Order $order) {
1007:         return false;
1008:     }
1009:     
1010:     /**
1011:      * <p>Should return the actual Pdf binary which should be packing slip for this order and false in every other case.</p>
1012:      * <p>This function is available to the merchant, if he/she wants to print the packing slip in the order view.</p>
1013:      * 
1014:      * 
1015:      * @param Mage_Sales_Model_Order $order
1016:      * @return boolean 
1017:      */
1018:     public function getBarcodePdf(Mage_Sales_Model_Order $order) {
1019:         return false;
1020:     }
1021:     
1022:     /**
1023:      * <p>Returns true, if data has been sent</p>
1024:      * <p>Returns false, if data has not been sent</p>
1025:      * <p>Returns null, if data sending is not available.</p>
1026:      * 
1027:      * @param Mage_Sales_Model_Order $order
1028:      * @return boolean 
1029:      */
1030:     public function isDataSent(Mage_Sales_Model_Order $order) {
1031:         if ($this->isAutoSendAvailable()) {
1032:             return false;
1033:         }
1034:         return null;
1035:     }
1036:     
1037:     /**
1038:      *
1039:      * If the barcode function is available at all for this carrier.
1040:      * @return boolean 
1041:      */
1042:     public function isBarcodeFunctionAvailable() {
1043:         return false;
1044:     }
1045:     
1046:     
1047: 
1048:     /**
1049:      * <p> If automatic data sending is available, then this function should be overwritten and the actual data sending should be performed in here.</p>
1050:      * <p>Also Configuration value of <code>senddata_enable</code> should be set to '1' or this function will never be called.</p>
1051:      * <p>If automatic sending is not applicable, then this function should return boolean false.</p>
1052:      * <p>If automatic data sending is successful, then the result will be added to the order comments using <code>print_r()</code> function.</p>
1053:      * 
1054:      * 
1055:      * 
1056:      * @param Mage_Sales_Model_Order $order
1057:      * @param type $selectedOfficeId remote_place_id - id of the carrier, that the customer selected.
1058:      * @return boolean|array 
1059:      */
1060:     public function autoSendData(Mage_Sales_Model_Order $order, $selectedOfficeId) {
1061:         return false;
1062:     }
1063:     
1064:     /**
1065:      *  Wrapper function for the parent class, simply for security and session management.
1066:      * For example, when user first selects country, where the carrier is available and then switches country and the carrier is not available any more,
1067:      * then the session has to be cleared a bit, in order to avoid the user entering arbitrary data for the previously available carrier.
1068:      * 
1069:      * @param Mage_Shipping_Model_Rate_Request $request
1070:      * @return \Mage_Shipping_Model_Rate_Result_Error 
1071:      */
1072:     public function checkAvailableShipCountries(Mage_Shipping_Model_Rate_Request $request) {
1073:         $checkResult = parent::checkAvailableShipCountries($request);
1074:         if ($checkResult === false || ($checkResult instanceof Mage_Shipping_Model_Rate_Result_Error)) {
1075:             $this->clearAddressId($this->getAddressId($request));
1076:         }
1077:         return $checkResult;
1078:     }
1079:     
1080:     /**
1081:      * <p>Indicates if specified order has been picked up by courier.</p>
1082:      * <p>Should return the following</p>
1083:      * <ul>
1084:          <li><b>true</b> - If the order has been picked up by courier</li>
1085:          <li><b>false</b> - If the order has not been picked up by courier</li>
1086:          <li><b>null</b> - If courier pickup is not applicable to specified order</li>
1087:      </ul>
1088:      * @param Mage_Sales_Model_Order $order
1089:      * @return null|bool
1090:      */
1091:     public function isPickedUpByCourier(Mage_Sales_Model_Order $order) {
1092:         return null;
1093:     }
1094:     
1095:     /**
1096:      *  Gets the address_id, which will be used in the 'sales/quote_address_rate' database table, in order to handle user selection of postoffice
1097:      * related to this carrier.
1098:      * 
1099:      * 
1100:      * @param Mage_Shipping_Model_Rate_Request $request
1101:      * @return type 
1102:      */
1103:     protected function getAddressId(Mage_Shipping_Model_Rate_Request $request) {
1104:         if (Mage::app()->getStore()->isAdmin()) {
1105:             return Mage::getSingleton('adminhtml/sales_order_create')->getQuote()->getShippingAddress()->getId();
1106:         } else if ($this->_isMultishipping($request)) {
1107:             $shippingAddresses = Mage::getSingleton('checkout/type_multishipping')->getQuote()->getAllShippingAddresses();
1108:             foreach ($shippingAddresses as $shippingAddress) {
1109:                 if ($this->_compareAddressToRequest($request, $shippingAddress)) {
1110:                     if ($shippingAddress->getId() <= 0) {
1111:                         $shippingAddress->save();
1112:                     }
1113:                     return $shippingAddress->getId();
1114:                 }
1115:             }
1116:         } else {
1117:             return Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getId();
1118:         }
1119:         
1120:     }
1121:     
1122:     /**
1123:      * <p>In multishipping scenarios shipping addresses may not be saved and thus lacking correct id. In such scenario they need to be compared manually to detect the correct chosen parcel terminal</p>
1124:      * @param Mage_Shipping_Model_Rate_Request $request
1125:      * @param Mage_Sales_Model_Quote_Address $address
1126:      * @return boolean
1127:      */
1128:     protected function _compareAddressToRequest(Mage_Shipping_Model_Rate_Request $request, $address) {
1129:         $compareFields = array(
1130:             'dest_country_id' => 'country_id',
1131:             'dest_region_id' => 'region_id',
1132:             'dest_street' => 'street',
1133:             'dest_city' => 'city',
1134:             'dest_postcode' => 'postcode',
1135:         );
1136:         foreach ($compareFields as $requestField => $addressField) {
1137:             if ($request->getData($requestField) != $address->getData($addressField)) {
1138:                 return false;
1139:             }
1140:         }
1141:         return true;
1142:     }
1143:     
1144:     /**
1145:      * <p>Converts array input of three elements into seconds</p>
1146:      * <p>First element in array should represent hours</p>
1147:      * <p>Second element in array should represent minutes</p>
1148:      * <p>Third element in array should represent seconds</p>
1149:      * @param array $input
1150:      * @return int
1151:      */
1152:     protected function _getSeconds($input) {
1153:         $multipliers = array(
1154:             3600,
1155:             60,
1156:             1,
1157:         );
1158:         $sum = 0;
1159:         foreach ($multipliers as $i => $multiplier) {
1160:             $sum += (int)($input[$i] * $multiplier);
1161:         }
1162:         return $sum;
1163:     }
1164:     
1165:     
1166:     /**
1167:      * <p>Gets current carrier code for usage in other helper classes.</p>
1168:      * @return string
1169:      */
1170:     public function getCode() {
1171:         return $this->_code;
1172:     }
1173:     
1174:     
1175:     
1176:     /**
1177:      * 
1178:      * @return Mage_Sales_Model_Quote_Address
1179:      */
1180:     protected function _getAddressModel() {
1181:         return Mage::getModel('sales/quote_address');
1182:     }
1183:     
1184:     /**
1185:      * 
1186:      * @return Mage_Catalog_Model_Product
1187:      */
1188:     protected function _getProductModel() {
1189:         return Mage::getModel('catalog/product');
1190:     }
1191:     
1192:     protected function _getOfficeModel() {
1193:         return Mage::getModel('eabi_postoffice/office');
1194:     }
1195:     
1196:     
1197:     /**
1198:      * 
1199:      * @return Eabi_Livehandler_Helper_Data
1200:      */
1201:     protected function _getEabi() {
1202:         return Mage::helper('eabi');
1203:     }
1204:     
1205:     /**
1206:      * 
1207:      * @return Eabi_Postoffice_Helper_Data
1208:      */
1209:     protected function _getOfficeHelper() {
1210:         return Mage::helper('eabi_postoffice');
1211:     }
1212:     
1213:     
1214:     /**
1215:      * 
1216:      * @return Eabi_Postoffice_Helper_Countrycode
1217:      */
1218:     protected function _getDialCodeHelper() {
1219:         return Mage::helper('eabi_postoffice/countrycode');
1220:     }
1221:     
1222:     /**
1223:      * Return checkout session object
1224:      *
1225:      * @return Mage_Checkout_Model_Session
1226:      */
1227:     protected function _getCheckoutSession() {
1228:         if (Mage::app()->getStore()->isAdmin()) {
1229:             return Mage::getSingleton('adminhtml/session_quote');
1230:         }
1231:         return Mage::getSingleton('checkout/session');
1232:     }
1233: 
1234:     /**
1235:      * Return checkout quote object
1236:      *
1237:      * @return Mage_Sales_Model_Quote
1238:      */
1239:     protected function _getQuote() {
1240:         if (!$this->_quote) {
1241:             $this->_quote = $this->_getCheckoutSession()->getQuote();
1242:         }
1243:         return $this->_quote;
1244:     }
1245:     
1246:     
1247:     
1248: }
1249: 
1250: 
DPD Eesti - Pakivedu.ee Shipping module for Magento API documentation generated by ApiGen 2.8.0