* @copyright 2016-2019 GFI Informatique, 2016-2019 TNT * @license https://opensource.org/licenses/MIT MIT License */ if (!defined('_PS_VERSION_')) { exit; } require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_ClassLoader.php'; /** * Class TNTOfficiel. */ class TNTOfficiel extends CarrierModule { // Name identifier. const MODULE_NAME = 'tntofficiel'; // Carrier name. const CARRIER_NAME = 'TNT'; // Release stamp : (((+new Date())/1000)|0).toString(36) const MODULE_RELEASE = 'pihmhe'; // Status that trigger shipment creation (eg: PS_OS_PREPARATION). const ORDERSTATE_SAVESHIPMENT = 'PS_OS_SHIPPING'; // Path to the module Log. const PATH_LOG = 'log/'; // Google Map API Version (google.maps.version). const GMAP_API_VER = '3.exp'; /** * Request timeout. */ // Timeout for connection to the server. const REQUEST_CONNECTTIMEOUT = 8; // Timeout global (expiration). const REQUEST_TIMEOUT = 32; /** * Reserved by Cart Model. * @var int|null Carrier ID set when retrieving shipping cost from module. * see getOrderShippingCost() */ public $id_carrier = null; /** * TNTOfficiel constructor. */ public function __construct() { TNTOfficiel_Logstack::log(); // Module is compliant with bootstrap. PS1.6+ $this->bootstrap = true; // Version. $this->version = '1.0.2'; // Prestashop supported version. PS1.7.0.5+ $this->ps_versions_compliancy = array('min' => '1.7.0.5', 'max' => '1.7.99.99'); // Prestashop modules dependencies. $this->dependencies = array(); // Name. $this->name = 'tntofficiel'; // TNTOfficiel::MODULE_NAME; // Displayed Name. $this->displayName = $this->l('TNT'); // TNTOfficiel::CARRIER_NAME; // Description. $this->description = $this->l('Offer your customers, different delivery methods with TNT'); // Type. $this->tab = 'shipping_logistics'; // Confirmation message before uninstall. $this->confirmUninstall = $this->l('Are you sure you want to delete this module?'); // Author. $this->author = 'Gfi Informatique'; // Module key provided by addons.prestashop.com. $this->module_key = '1cf0bbdc13a4d4f319266cfe0bfac777'; // Is this instance required on module when it is displayed in the module list. // This can be useful if the module has to perform checks on the PrestaShop configuration. $this->need_instance = 0; // Module Constructor. parent::__construct(); // If module not ready. if (!TNTOfficiel::isContextReady()) { // Do nothing. return; } $objTNTContextAccountModel = TNTOfficielAccount::loadContextShop(); // If no account available for this context. if ($objTNTContextAccountModel === null) { // Do nothing. return; } // Check each days credential state for auto invalidation (e.g: password changed). // If invalidated, module is disabled and carrier are not displayed on front-office. if ($objTNTContextAccountModel->getAuthValidatedDateTime() !== null) { $objTNTContextAccountModel->updateAuthValidation(60 * 60 * 24); } // Apply default carriers values if required. TNTOfficielCarrier::forceAllCarrierDefaultValues(); } /** * Module install. * * @return bool */ public function install() { TNTOfficiel_Logstack::log(); // If MultiShop and more than 1 Shop. if (Shop::isFeatureActive()) { // Define Shop context to all Shops. Shop::setContext(Shop::CONTEXT_ALL); } TNTOfficiel_Logger::logInstall( '____ '.TNTOfficiel::CARRIER_NAME.' ('.TNTOfficiel::MODULE_NAME.') : install init. ____' ); // Check tntofficiel release version. $strRLPrevious = (string)Configuration::get('TNTOFFICIEL_RELEASE'); $intTSPrevious = (int)base_convert($strRLPrevious, 36, 10); $intTSCurrent = base_convert(TNTOfficiel::MODULE_RELEASE, 36, 10); // If current release is older than the previously installed, then do not install. if ($intTSCurrent < $intTSPrevious) { TNTOfficiel_Logger::logInstall('Downgrade not allowed', false); $this->_errors[] = $this->l('Downgrade not allowed : Previously installed version is greater than the current one.'); return false; } // Check compatibility. if (!extension_loaded('curl')) { TNTOfficiel_Logger::logInstall('PHP cURL extension is required', false); $this->_errors[] = $this->l('You have to enable the cURL extension on your server to install this module.'); return false; } if (!extension_loaded('soap')) { TNTOfficiel_Logger::logInstall('PHP SOAP extension is required', false); $this->_errors[] = $this->l('You have to enable the SOAP extension on your server to install this module.'); return false; } // Store release. Configuration::updateGlobalValue('TNTOFFICIEL_RELEASE', TNTOfficiel::MODULE_RELEASE); // Remove deprecated files. TNTOfficiel_Install::uninstallDeprecatedFiles(); // Prestashop install. if (!parent::install()) { TNTOfficiel_Logger::logInstall('Module::install', false); $this->_errors[] = Tools::displayError('Impossible d\'installer Module::install().'); return false; } TNTOfficiel_Logger::logInstall('Module::install'); // Update settings. if (!TNTOfficiel_Install::updateSettings()) { $this->_errors[] = Tools::displayError('Impossible de définir la configuration.'); return false; } // Register hooks. foreach (TNTOfficiel_Install::$arrHookList as $strHookName) { if (!$this->registerHook($strHookName)) { TNTOfficiel_Logger::logInstall('Module::registerHook ('.$strHookName.')', false); $this->_errors[] = Tools::displayError(sprintf('Impossible d\'inscrire le hook "%s".', $strHookName)); return false; } } TNTOfficiel_Logger::logInstall('Module::registerHook'); // Create the TNT tab. if (!TNTOfficiel_Install::createTab()) { $this->_errors[] = Tools::displayError('Impossible d\'ajouter l\'onglet du menu.'); return false; } // Create the tables. if (!TNTOfficiel_Install::createTables()) { $this->_errors[] = Tools::displayError('Impossible de créer les tables de la base de donnée.'); return false; } // Clear cache. TNTOfficiel_Install::clearCache(); TNTOfficiel_Logger::logInstall( '____ '.TNTOfficiel::CARRIER_NAME.' ('.TNTOfficiel::MODULE_NAME.') : install complete. ____' ); return true; } /** * Module uninstall. * * @return bool */ public function uninstall() { TNTOfficiel_Logstack::log(); TNTOfficiel_Logger::logInstall( '____ '.TNTOfficiel::CARRIER_NAME.' ('.TNTOfficiel::MODULE_NAME.') : uninstall init. ____' ); // Uninstall class or controllers override. // Already done by parent::uninstall, but used to display error message. if (!$this->uninstallOverrides()) { TNTOfficiel_Logger::logInstall('Module::uninstallOverrides', false); $this->_errors[] = Tools::displayError('Impossible de supprimer la surcharge de classe.'); return false; } TNTOfficiel_Logger::logInstall('Module::uninstallOverrides'); // Unregister Hooks. foreach (TNTOfficiel_Install::$arrHookList as $strHookName) { if (!$this->unregisterHook($strHookName)) { TNTOfficiel_Logger::logInstall('Module::unregisterHook ('.$strHookName.')', false); $this->_errors[] = Tools::displayError(sprintf('Impossible de supprimer le hook "%s".', $strHookName)); return false; } } TNTOfficiel_Logger::logInstall('Module::unregisterHook'); // Delete Tab. if (!TNTOfficiel_Install::deleteTab()) { $this->_errors[] = Tools::displayError('Impossible de supprimer l\'onglet du menu.'); return false; } // Delete Settings. if (!TNTOfficiel_Install::deleteSettings()) { $this->_errors[] = Tools::displayError('Impossible de supprimer la configuration.'); return false; } // Prestashop Uninstall. if (!parent::uninstall()) { TNTOfficiel_Logger::logInstall('Module::uninstall', false); $this->_errors[] = Tools::displayError('Impossible de désinstaller Parent::uninstall().'); return false; } TNTOfficiel_Logger::logInstall('Module::uninstall'); TNTOfficiel_Logger::logInstall( '____ '.TNTOfficiel::CARRIER_NAME.' ('.TNTOfficiel::MODULE_NAME.') : uninstall complete. ____' ); // TODO: check default carrier is not TNT. // Configuration::get('PS_CARRIER_DEFAULT') return true; } /** * Module configuration page content. * Large form is displayed in a custom admin controller. * * @return string HTML content. */ public function getContent() { TNTOfficiel_Logstack::log(); Tools::redirectAdmin($this->context->link->getAdminLink('AdminAccountSetting')); return ''; } /** * Is module ready for current context. */ public static function isContextReady() { TNTOfficiel_Logstack::log(); // If module not installed (ps_module:id_module) $this->id > 0 // or module not activated (ps_module:active) $this->active ps_module_shop // or override class are disabled (performance/debug). if (!Module::isInstalled(TNTOfficiel::MODULE_NAME) || !Module::isEnabled(TNTOfficiel::MODULE_NAME) ) { return false; } return true; } /** * @return array */ public function getCommonVariable() { TNTOfficiel_Logstack::log(); $objContext = $this->context; $objLink = $objContext->link; $objShop = $objContext->shop; // Controller. $objController = $objContext->controller; // Get Controller Name. $strCurrentControllerName = get_class($objController); $objTNTContextAccountModel = TNTOfficielAccount::loadContextShop(); $boolContextAuth = false; $strAPIGoogleMapKey = ''; if ($objTNTContextAccountModel !== null) { $boolContextAuth = $objTNTContextAccountModel->getAuthValidatedDateTime() !== null; $strAPIGoogleMapKey = $objTNTContextAccountModel->api_google_map_key; } $arrCarrierList = array(); $arrObjTNTCarrierModelList = TNTOfficielCarrier::getContextCarrierModelList(); foreach ($arrObjTNTCarrierModelList as $intTNTCarrierID => $objTNTCarrierModel) { $arrCarrierList[$intTNTCarrierID] = $objTNTCarrierModel->carrier_type; } if (Configuration::get('PS_RESTRICT_DELIVERED_COUNTRIES')) { $arrCountryList = Carrier::getDeliveredCountries($this->context->language->id, true, true); } else { $arrCountryList = Country::getCountries($this->context->language->id, true); } // Javascript config. $arrTNTOfficiel = array( 'timestamp' => microtime(true) * 1000, 'module' => array( 'name' => TNTOfficiel::MODULE_NAME, 'title' => TNTOfficiel::CARRIER_NAME, 'version' => $this->version, 'context' => $boolContextAuth, 'ready' => TNTOfficiel::isContextReady() ), 'config' => array( 'google' => array( 'map' => array( 'url' => 'https://maps.googleapis.com/maps/api/js', 'data' => array( 'v' => TNTOfficiel::GMAP_API_VER, 'key' => $strAPIGoogleMapKey ), 'default' => array( "lat" => 46.827742, "lng" => 2.835644, "zoom" => 6 ) ) ) ), 'translate' => array( 'validateDeliveryAddress' => htmlentities($this->l('Validate your delivery address')), 'unknownPostalCode' => htmlentities($this->l('Unknown postal code')), 'validatePostalCodeDeliveryAddress' => htmlentities( $this->l('Please edit and validate the postal code of your delivery address.') ), 'unrecognizedCity' => htmlentities($this->l('Unrecognized city')), 'selectCityDeliveryAddress' => htmlentities( $this->l('Please select the city from your delivery address.') ), 'postalCode' => htmlentities($this->l('Postal code')), 'city' => htmlentities($this->l('City')), 'validate' => htmlentities($this->l('Validate')), 'validateAdditionalCarrierInfo' => htmlentities( $this->l('Please confirm the form with additional information for the carrier.') ), 'errorDownloadingHRA' => htmlentities( $this->l('Error while downloading the HRA list. Please contact the support.') ), 'errorInvalidPhoneNumber' => htmlentities($this->l('The phone number must be 10 digits')), 'errorInvalidEMail' => htmlentities($this->l('The email is invalid')), 'errorNoDeliveryOptionSelected' => htmlentities($this->l('No delivery options selected.')), 'errorNoDeliveryAddressSelected' => htmlentities($this->l('No delivery address selected.')), 'errorNoDeliveryPointSelected' => htmlentities($this->l('No delivery point selected.')), 'errorUnknow' => htmlentities($this->l('An error has occurred.')), 'errorTechnical' => htmlentities($this->l('A technical error occurred.')), 'errorConnection' => htmlentities($this->l('A connection error occurred.')) ), 'link' => array( 'controller' => Tools::strtolower($strCurrentControllerName), 'front' => array( 'shop' => $objShop->getBaseURL(true), 'module' => array( 'boxDeliveryPoints' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'carrier', array('action' => 'boxDeliveryPoints'), true ), 'saveProductInfo' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'carrier', array('action' => 'saveProductInfo'), true ), 'checkPaymentReady' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'carrier', array('action' => 'checkPaymentReady'), true ), 'storeReceiverInfo' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'address', array('action' => 'storeReceiverInfo'), true ), 'getAddressCities' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'address', array('action' => 'getCities'), true ), 'updateAddressDelivery' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'address', array('action' => 'updateDeliveryAddress'), true ), 'checkAddressPostcodeCity' => $objLink->getModuleLink( TNTOfficiel::MODULE_NAME, 'address', array('action' => 'checkPostcodeCity'), true ) ), 'page' => array( 'order' => $objLink->getPageLink('order', true) ) ), 'back' => null, 'image' => _MODULE_DIR_.TNTOfficiel::MODULE_NAME.'/views/img/' ), 'country' => array( 'list' => $arrCountryList ), 'carrier' => $arrCarrierList, 'cart' => array( 'isCarrierListDisplay' => false ), 'order' => array( 'isTNT' => false ) ); return $arrTNTOfficiel; } /** * HOOK (AKA backOfficeHeader) called inside the head tag. * Ideal location for adding JavaScript and CSS files. * Hook called even if module is disabled ! * * @param array $arrArgHookParams * * @return string HTML content in head tag. */ public function hookDisplayBackOfficeHeader($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objContext = $this->context; $objHookCookie = $arrArgHookParams['cookie']; // Controller. $objController = $objContext->controller; // Get Controller Name. $strCurrentControllerName = Tools::strtolower(get_class($objController)); $strAssetCSSPath = $this->getPathUri().'views/css/'.TNTOfficiel::MODULE_RELEASE.'/'; //$strAssetJSPath = $this->getPathUri().'views/js/'.TNTOfficiel::MODULE_RELEASE.'/'; // Global Admin CSS. $objController->addCSS($strAssetCSSPath.'Admin.css', 'all'); $arrJSONTNTOfficiel = $this->getCommonVariable(); $arrJSONTNTOfficiel['link']['back'] = array( 'module' => array( 'removeParcelUrl' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=removeParcel&ajax=true', 'addParcelUrl' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=addParcel&ajax=true', 'updateParcelUrl' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=updateParcel&ajax=true', 'checkShippingDateValidUrl' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=checkShippingDateValid&ajax=true', 'storeReceiverInfo' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=storeReceiverInfo&ajax=true', 'boxDeliveryPoints' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=boxDeliveryPoints&ajax=true', 'saveProductInfo' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=saveProductInfo&ajax=true', 'selectPostcodeCities' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=selectPostcodeCities&ajax=true', 'updateHRA' => $this->context->link->getAdminLink('AdminTNTOrders').'&action=updateHRA&ajax=true', ) ); $arrJSONTNTOfficiel['translate']['back'] = array( 'updateSuccessfulStr' => htmlentities($this->l('Update successful')), 'deleteStr' => htmlentities($this->l('Delete')), 'updateStr' => htmlentities($this->l('Update')), 'atLeastOneParcelStr' => htmlentities($this->l('An order requires at least one parcel')) ); if (!array_key_exists('alert', $arrJSONTNTOfficiel) || !is_array($arrJSONTNTOfficiel['alert']) ) { $arrJSONTNTOfficiel['alert'] = array( 'error' => array(), 'warning' => array(), 'success' => array() ); } // Cookie TNTOfficielError is used to display error message once after redirect. if (!empty($objHookCookie->TNTOfficielError)) { // Add error message to the admin page if exists. $arrJSONTNTOfficiel['alert']['error'][] = $objHookCookie->TNTOfficielError; // Delete cookie. $objHookCookie->TNTOfficielError = null; } if (!empty($objHookCookie->TNTOfficielWarning)) { // Add error message to the admin page if exists. $arrJSONTNTOfficiel['alert']['warning'][] = $objHookCookie->TNTOfficielWarning; // Delete cookie. $objHookCookie->TNTOfficielWarning = null; } if (!empty($objHookCookie->TNTOfficielSuccess)) { // Add error message to the admin page if exists. $arrJSONTNTOfficiel['alert']['success'][] = $objHookCookie->TNTOfficielSuccess; // Delete cookie. $objHookCookie->TNTOfficielSuccess = null; } // Add TNTOfficiel global variable with others in main inline script. Media::addJsDef(array('TNTOfficiel' => $arrJSONTNTOfficiel)); TNTOfficiel_Logstack::dump(array( 'ajax' => $objController->ajax, 'controller_type' => $objController->controller_type, 'controllername' => $strCurrentControllerName, 'controllerfilename' => Dispatcher::getInstance()->getController() )); // Display nothing. return ''; } /** * HOOK called to include CSS or JS files in the Back-Office header. * * @param array $arrArgHookParams */ public function hookActionAdminControllerSetMedia($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objContext = $this->context; // Controller. $objController = $objContext->controller; // Get Controller Name. $strCurrentControllerName = Tools::strtolower(get_class($objController)); $strAssetCSSPath = $this->getPathUri().'views/css/'.TNTOfficiel::MODULE_RELEASE.'/'; $strAssetJSPath = $this->getPathUri().'views/js/'.TNTOfficiel::MODULE_RELEASE.'/'; $objController->addCSS($strAssetCSSPath.'global.css'); $objController->addJS($strAssetJSPath.'global.js'); switch ($strCurrentControllerName) { // Back-Office Carrier Wizard. case 'admincarrierwizardcontroller': $objController->addJS($strAssetJSPath.'AdminCarrierWizard.js'); break; default: break; } TNTOfficiel_Logstack::dump(array( 'ajax' => $objController->ajax, 'controller_type' => $objController->controller_type, 'controllername' => $strCurrentControllerName, 'controllerfilename' => Dispatcher::getInstance()->getController() )); } /** * HOOK (AKA Header) displayed in head tag on Front-Office. * * @param array $arrArgHookParams * * @return string */ public function hookDisplayHeader($arrArgHookParams) { TNTOfficiel_Logstack::log(); //$objHookCart = $arrArgHookParams['cart']; $objContext = $this->context; // Controller. $objController = $objContext->controller; // Get Controller Name. $strCurrentControllerName = Tools::strtolower(get_class($objController)); // If module not ready. if (!TNTOfficiel::isContextReady()) { // Display nothing. return ''; } $objTNTContextAccountModel = TNTOfficielAccount::loadContextShop(); // If no account available for this context, or is not authenticated. if ($objTNTContextAccountModel === null || $objTNTContextAccountModel->getAuthValidatedDateTime() === null ) { // Display nothing. return ''; } $arrJSONTNTOfficiel = $this->getCommonVariable(); // Add TNTOfficiel global variable with others in main inline script. Media::addJsDef(array('TNTOfficiel' => $arrJSONTNTOfficiel)); // Google Font: Open Sans. $objController->addCSS('https://fonts.googleapis.com/css?family=Open+Sans:400,700', 'all'); $strAssetCSSPath = $this->getPathUri().'views/css/'.TNTOfficiel::MODULE_RELEASE.'/'; $strAssetJSPath = $this->getPathUri().'views/js/'.TNTOfficiel::MODULE_RELEASE.'/'; $objController->addCSS($strAssetCSSPath.'global.css'); $objController->addJS($strAssetJSPath.'global.js'); // Switch Controller Name. switch ($strCurrentControllerName) { // Front-Office Order History +guest. case 'orderdetailcontroller': case 'guesttrackingcontroller': // Form.css required for displayOrderDetail.tpl $objController->addCSS($strAssetCSSPath.'form.css', 'all'); break; // Front-Office Address. case 'addresscontroller': // Front-Office Guest Checkout Address. case 'authcontroller': // Form.css required for address-city-check, ExtraData $objController->addCSS($strAssetCSSPath.'form.css', 'all'); // FancyBox required to display form (cp/ville check). $objController->addJqueryPlugin('fancybox'); $objController->addJS($strAssetJSPath.'address.js'); break; // Front-Office Cart Process. case 'ordercontroller': // Form.css required for address-city-check, ExtraData $objController->addCSS($strAssetCSSPath.'form.css', 'all'); // $objController->addCSS($strAssetCSSPath.'carrier.css', 'all'); // Prestashop Validation system. $objController->addJS(_PS_JS_DIR_.'validate.js'); // FancyBox required to display form (cp/ville check). $objController->addJqueryPlugin('fancybox'); $objController->addJS($strAssetJSPath.'address.js'); // TNTOfficiel_inflate() TNTOfficiel_deflate(), required by carrierDeliveryPoint.js $objController->addJS($strAssetJSPath.'lib/string.js'); // jQuery.fn.nanoScroller, required by carrierDeliveryPoint.js $objController->addJS($strAssetJSPath.'lib/nanoscroller/jquery.nanoscroller.min.js'); $objController->addCSS($strAssetJSPath.'lib/nanoscroller/nanoscroller.css'); $objController->addJS($strAssetJSPath.'carrierDeliveryPoint.js', 'all'); $objController->addJS($strAssetJSPath.'carrierAdditionalInfo.js', 'all'); // TNTOfficiel_deliveryPointsBox, used in displayAjaxBoxDeliveryPoints.tpl $objController->addJS($strAssetJSPath.'carrier.js'); break; default: break; } TNTOfficiel_Logstack::dump(array( 'ajax' => $objController->ajax, 'controller_type' => $objController->controller_type, 'controllername' => $strCurrentControllerName, 'controllerfilename' => Dispatcher::getInstance()->getController(), 'js' => $arrJSONTNTOfficiel )); // Display nothing. return ''; } /** * HOOK (AKA beforeCarrier) displayed before the carrier list on Front-Office. * * @param array $arrArgHookParams * * @return string */ public function hookDisplayBeforeCarrier($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objContext = $this->context; $objPSCart = $objContext->cart; // If module not ready. if (!TNTOfficiel::isContextReady()) { // Display nothing. return ''; } // Force $objPSCart->id_carrier Update using autoselect if not set (without using cache). // $objPSCart->id_carrier maybe incorrectly set when autoselection determine current selected carrier. // e.g: only one core carrier available, input radio is always already preselected, // but not $objPSCart->id_carrier since setDeliveryOption() was not used (and no change is possible). $objPSCart->setDeliveryOption($objPSCart->getDeliveryOption(null, false, false)); $objPSCart->save(); $objTNTContextAccountModel = TNTOfficielAccount::loadContextShop(); // If no account available for this context, or is not authenticated. if ($objTNTContextAccountModel === null || $objTNTContextAccountModel->getAuthValidatedDateTime() === null ) { // Display nothing. return ''; } $boolCityPostCodeIsValid = true; $objPSAddressDelivery = TNTOfficielReceiver::getPSAddress($objPSCart->id_address_delivery); // If delivery address object is available. if ($objPSAddressDelivery !== null) { // Check the city/postcode. $arrResultCitiesGuide = $objTNTContextAccountModel->citiesGuide( Country::getIsoById($objPSAddressDelivery->id_country), $objPSAddressDelivery->postcode, $objPSAddressDelivery->city ); // Unsupported country or communication error is considered true to prevent // always invalid address form and show error "unknow postcode" on Front-Office checkout. $boolCityPostCodeIsValid = (!$arrResultCitiesGuide['boolIsCountrySupported'] || $arrResultCitiesGuide['boolIsRequestComError'] || $arrResultCitiesGuide['boolIsCityNameValid'] ); } $objHookCookie = $arrArgHookParams['cookie']; $strTNTPaymentReadyError = null; if (!empty($objHookCookie->TNTPaymentReadyError)) { $strTNTPaymentReadyError = $objHookCookie->TNTPaymentReadyError; } $objHookCookie->TNTPaymentReadyError = null; $this->smarty->assign(array( 'boolCityPostCodeIsValid' => $boolCityPostCodeIsValid, 'id_address_delivery' => (int)$objPSCart->id_address_delivery, 'strTNTPaymentReadyError' => $strTNTPaymentReadyError )); // Display template. return $this->fetch(sprintf( 'module:%s/views/templates/hook/displayBeforeCarrier.tpl', TNTOfficiel::MODULE_NAME )); } /** * HOOK called after the list of available carriers, during the order process. * Ideal location to add a carrier, as added by a module. * Display TNT products during the order process. * (displayCarrierList AKA extraCarrier is deprecated). * * @param array $arrArgHookParams array * * @return string */ public function hookDisplayAfterCarrier($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objHookCart = $arrArgHookParams['cart']; $intCartID = (int)$objHookCart->id; $intCarrierIDSelected = (int)$objHookCart->id_carrier; $intAddressIDDelivery = (int)$objHookCart->id_address_delivery; $intCustomerID = (int)$objHookCart->id_customer; // If module not ready. if (!TNTOfficiel::isContextReady()) { // Display nothing. return ''; } // Prevent AJAX bug with carrier id inconsistency. $objHookCart->save(); $objTNTContextAccountModel = TNTOfficielAccount::loadContextShop(); // If no account available for this context, or is not authenticated. if ($objTNTContextAccountModel === null || $objTNTContextAccountModel->getAuthValidatedDateTime() === null ) { // Display nothing. return ''; } $objTNTCartModel = TNTOfficielCart::loadCartID($intCartID, true); if ($objTNTCartModel === null) { // Display nothing. return ''; } $arrFormReceiverInfoValidate = null; $strExtraAddressDataValid = 'false'; // A delivery address is optional. $objPSAddressDelivery = TNTOfficielReceiver::getPSAddress($objHookCart->id_address_delivery); // If delivery address object is available. if ($objPSAddressDelivery !== null) { // Load TNT receiver info or create a new one for it's ID. $objTNTReceiverModel = TNTOfficielReceiver::loadAddressID($objPSAddressDelivery->id); // If success. if ($objTNTReceiverModel !== null) { $strCustomerEMail = null; // A shipping address is optional. $objCustomer = new Customer($intCustomerID); // If shipping address object is available. if ((int)$objCustomer->id === $intCustomerID && Validate::isLoadedObject($objCustomer) ) { $strCustomerEMail = $objCustomer->email; } $strAddressPhone = $objTNTReceiverModel::searchPhoneMobile($objPSAddressDelivery); // Validate & store receiver info, using the customer email and address mobile phone as default values. $arrFormReceiverInfoValidate = $objTNTReceiverModel->storeReceiverInfo( $objTNTReceiverModel->receiver_email ? $objTNTReceiverModel->receiver_email : $strCustomerEMail, $objTNTReceiverModel->receiver_mobile ? $objTNTReceiverModel->receiver_mobile : $strAddressPhone, $objTNTReceiverModel->receiver_building, $objTNTReceiverModel->receiver_accesscode, $objTNTReceiverModel->receiver_floor ); $strExtraAddressDataValid = $arrFormReceiverInfoValidate['stored'] ? 'true' : 'false'; } } // Get the carriers model list. $arrObjTNTCarrierModelList = TNTOfficielCarrier::getFeasibilitiesContextCarrierModelList( // Get the heaviest product weight from cart. $objTNTCartModel->getCartHeaviestProduct(), $intAddressIDDelivery ); // Load an existing TNT carrier. $objTNTCarrierModelSelected = TNTOfficielCarrier::loadCarrierID($intCarrierIDSelected, false); $this->smarty->assign(array( 'arrObjTNTCarrierModelList' => $arrObjTNTCarrierModelList, 'arrDeliveryOption' => $objTNTCartModel->getDeliveryOption(), 'strCarrierTypeSelected' => $objTNTCarrierModelSelected === null ? null : ($objTNTCarrierModelSelected->carrier_type), 'arrFormReceiverInfoValidate' => $arrFormReceiverInfoValidate, 'strExtraAddressDataValid' => $strExtraAddressDataValid, )); // Display template. return $this->fetch(sprintf( 'module:%s/views/templates/hook/displayAfterCarrier.tpl', TNTOfficiel::MODULE_NAME ))/* .'
'
        .'intCarrierIDSelected : '.$intCarrierIDSelected."\n"
        .'objHookCart : '.TNTOfficiel_Logstack::encJSON($objHookCart)."\n"
        .'objTNTCartModel : '.TNTOfficiel_Logstack::encJSON($objTNTCartModel)."\n"
        .'CartTotalWeight : '.TNTOfficiel_Logstack::encJSON($objTNTCartModel->getCartTotalWeight())."\n"
        .'CartTotalPrice : '.TNTOfficiel_Logstack::encJSON($objTNTCartModel->getCartTotalPrice())."\n"
        .'CartShippingFree : '
            .TNTOfficiel_Logstack::encJSON($objTNTCartModel->isCartShippingFree($intCarrierIDSelected)."\n"
        .'ExtraShippingCost : '.$objTNTCartModel->getCartExtraShippingCost($intCarrierIDSelected)."\n"
        .'
' */ ; } /** * HOOK called to display extra content of an available carriers when selected. * * @param array $arrArgHookParams * * @return string */ public function hookDisplayCarrierExtraContent($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objContext = $this->context; $arrHookCarrier = $arrArgHookParams['carrier']; $intCarrierID = (int)$arrHookCarrier['id']; $objHookCart = $objContext->cart; $intCartID = (int)$objHookCart->id; // If module not ready. if (!TNTOfficiel::isContextReady()) { // Display nothing. return ''; } // Load TNT cart info or create a new one for it's ID. $objTNTCartModel = TNTOfficielCart::loadCartID($intCartID, true); // If fail. if ($objTNTCartModel === null) { // Display nothing. return ''; } // Load an existing TNT carrier. $objTNTCarrierModel = TNTOfficielCarrier::loadCarrierID($intCarrierID, false); // If fail. if ($objTNTCarrierModel === null) { // Display nothing. return ''; } $objTNTCarrierAccountModel = $objTNTCarrierModel->getTNTAccountModel(); // If no account available for this carrier, or is not authenticated. if ($objTNTCarrierAccountModel === null || $objTNTCarrierAccountModel->getAuthValidatedDateTime() === null ) { // Display nothing. return ''; } /* * Estimated delivery date. */ $strDueDate = null; // A delivery address is optional. $objPSAddressDelivery = TNTOfficielReceiver::getPSAddress($objHookCart->id_address_delivery); // If delivery address object is available. if ($objPSAddressDelivery !== null) { $arrFeasibilitiesList = $objTNTCarrierModel->feasibilities( $objPSAddressDelivery->postcode, $objPSAddressDelivery->city ); foreach ($arrFeasibilitiesList as $arrFeasibility) { $strDueDate = $arrFeasibility['dueDate']; break; } } $this->smarty->assign(array( 'objTNTCarrierModel' => $objTNTCarrierModel, 'strDueDate' => $objTNTCarrierAccountModel->delivery_display_edd ? $strDueDate : null, 'deliveryPoint' => $objTNTCartModel->getDeliveryPoint(), )); // Display template. return $this->fetch(sprintf( 'module:%s/views/templates/hook/displayCarrierExtraContent.tpl', TNTOfficiel::MODULE_NAME ))/* .'
'
        .'Account : '.TNTOfficiel_Logstack::encJSON($objTNTCarrierAccountModel)."\n"
        .'Feasibilities : '.TNTOfficiel_Logstack::encJSON($arrFeasibilitiesList)."\n"
        .'ZonesConf : '.TNTOfficiel_Logstack::encJSON($objTNTCarrierModel->getZonesConf())."\n"
        .'
'*/ ; } /** * HOOK 1.7.1+ called when button continue is submitted (confirmDeliveryOption) on delivery step. * Check if state for a selected carrier of this module is completed. * https://github.com/PrestaShop/PrestaShop/commit/895255fd61b9cdf77e4e6096ef076b5149d884a4 * * @param array $arrArgHookParams * * @return bool */ public function hookActionValidateStepComplete($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objHookCart = $arrArgHookParams['cart']; $objHookCookie = $arrArgHookParams['cookie']; $intCartID = (int)$objHookCart->id; // Load TNT cart info or create a new one for it's ID. $objTNTCartModel = TNTOfficielCart::loadCartID($intCartID, true); if ($objTNTCartModel !== null) { $arrResult = $objTNTCartModel->isPaymentReady(); // Set to true if completed. $arrArgHookParams['completed'] = !array_key_exists('error', $arrResult) || !is_string($arrResult['error']); // Store error message to display later after redirect in BeforeCarrier Hook. if (array_key_exists('error', $arrResult) && is_string($arrResult['error'])) { $arrJSONTNTOfficiel = $this->getCommonVariable(); if (array_key_exists($arrResult['error'], $arrJSONTNTOfficiel['translate'])) { $objHookCookie->TNTPaymentReadyError = html_entity_decode( $arrJSONTNTOfficiel['translate'][ $arrResult['error']] ); } else { $objHookCookie->TNTPaymentReadyError = $arrResult['error']; } } } return true; } /** * HOOK (AKA newOrder) called during the new order creation process, right after it has been created. * Called from /classes/PaymentModule.php * * Create XETT/PEX address if required and create parcels. * * @param $arrArgHookParams array * * @return bool */ public function hookActionValidateOrder($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objHookOrder = $arrArgHookParams['order']; $intOrderID = (int)$objHookOrder->id; //$objHookCustomer = $arrArgHookParams['customer']; //$objHookCurrency = $arrArgHookParams['currency']; //$objHookOrderStatus = $arrArgHookParams['orderStatus']; // Load TNT order info or create a new one for it's ID. $objTNTOrderModel = TNTOfficielOrder::loadOrderID($intOrderID, true); // If fail. if ($objTNTOrderModel === null) { return false; } // Load an existing TNT carrier. $objTNTCarrierModel = $objTNTOrderModel->getTNTCarrierModel(); // If fail or carrier is not from TNT module. if ($objTNTCarrierModel === null) { // Do not have to save this cart. return false; } // Load TNT cart info or create a new one for it's ID. $objTNTCartModel = $objTNTOrderModel->getTNTCartModel(); // If fail. if ($objTNTCartModel === null) { return false; } // Creates parcels for order. $objTNTOrderModel->createParcels(); if ($objTNTCarrierModel->carrier_type === 'DEPOT' || $objTNTCarrierModel->carrier_type === 'DROPOFFPOINT' ) { $arrDeliveryPoint = $objTNTCartModel->getDeliveryPoint(); // Copy Delivery Point from cart. $mxdNewIDAddressDelivery = $objTNTOrderModel->setDeliveryPoint($arrDeliveryPoint); if (is_int($mxdNewIDAddressDelivery) && $mxdNewIDAddressDelivery > 0) { $objHookOrder->id_address_delivery = $mxdNewIDAddressDelivery; } elseif (!$mxdNewIDAddressDelivery) { return false; } // Save TNT order. $objTNTOrderModel->save(); } // Update shipping date if available. $objTNTOrderModel->updatePickupDate(); return true; } /** * HOOK (AKA adminOrder) called when the order's details are displayed, below the Client Information block. * Parcel management for orders with a tnt carrier. * * @param array $arrArgHookParams * * @return string */ public function hookDisplayAdminOrder($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objContext = $this->context; // Controller. $objController = $objContext->controller; //$objHookCookie = $arrArgHookParams['cookie']; //$objHookCart = $arrArgHookParams['cart']; $intHookOrderID = (int)$arrArgHookParams['id_order']; $objPSOrder = TNTOfficielOrder::getPSOrder($intHookOrderID); if ($objPSOrder === null) { // Display nothing. return ''; } // If order carrier is not created by tntofficiel module. if (!TNTOfficielCarrier::isTNTOfficielCarrierID($objPSOrder->id_carrier)) { // Display nothing. return ''; } // Prevent Prestahop bugs without override. // http://forge.prestashop.com/browse/BOOM-4050 // http://forge.prestashop.com/browse/BOOM-5821 //if (version_compare(_PS_VERSION_, '1.7.5', '<')) { if (Shop::getContext() !== Shop::CONTEXT_SHOP) { // Change context to order shop. Tools::redirectAdmin( $this->context->link->getAdminLink('AdminOrders', false) .'&id_order='.$objPSOrder->id.'&vieworder' .'&token='.Tools::getAdminTokenLite('AdminOrders') .'&setShopContext=s-'.$objPSOrder->id_shop ); } //} // Load TNT order info or create a new one for it's ID. $objTNTOrderModel = TNTOfficielOrder::loadOrderID($intHookOrderID, true); if ($objTNTOrderModel === null) { $this->context->controller->errors[] = sprintf( $this->l('Unable to load or create TNT Order for Order ID #%s'), $intHookOrderID ); // Display nothing. return ''; } $objTNTCarrierAccountModel = $objTNTOrderModel->getTNTAccountModel(); // If no account available for this carrier. if ($objTNTCarrierAccountModel === null) { $this->context->controller->errors[] = sprintf( $this->l('Unable to load TNT Account for Carrier ID #%s'), $objPSOrder->id_carrier ); return ''; } // If account is not authenticated. if ($objTNTCarrierAccountModel->getAuthValidatedDateTime() === null) { $this->context->controller->errors[] = sprintf( $this->l('TNT Account is not authenticated for Account ID #%s'), $objTNTCarrierAccountModel->id ); // Display nothing. return ''; } // Load TNT Receiver info or create a new one for it's ID. $objTNTReceiverModel = TNTOfficielReceiver::loadAddressID($objPSOrder->id_address_delivery); // If fail. if ($objTNTReceiverModel === null) { $this->context->controller->errors[] = sprintf( $this->l('Unable to load or create TNT Receiver for Address ID #%s'), $objPSOrder->id_address_delivery ); // Display nothing. return ''; } $strAssetCSSPath = $this->getPathUri().'views/css/'.TNTOfficiel::MODULE_RELEASE.'/'; $strAssetJSPath = $this->getPathUri().'views/js/'.TNTOfficiel::MODULE_RELEASE.'/'; // Form.css required for address-city-check, ExtraData $objController->addCSS($strAssetCSSPath.'form.css', 'all'); // $objController->addCSS($strAssetCSSPath.'carrier.css', 'all'); // FancyBox required to display form (cp/ville check). $objController->addJqueryPlugin('fancybox'); // TNTOfficiel_inflate() TNTOfficiel_deflate(), required by carrierDeliveryPoint.js $objController->addJS($strAssetJSPath.'lib/string.js'); // jQuery.fn.nanoScroller, required by carrierDeliveryPoint.js $objController->addJS($strAssetJSPath.'lib/nanoscroller/jquery.nanoscroller.min.js'); $objController->addCSS($strAssetJSPath.'lib/nanoscroller/nanoscroller.css'); $objController->addJS($strAssetJSPath.'carrierDeliveryPoint.js', 'all'); $objController->addJS($strAssetJSPath.'carrierAdditionalInfo.js', 'all'); $objController->addJS($strAssetJSPath.'AdminOrder.js', 'all'); // Remove script load of API Google Map to prevent conflicts. // Removed in this hook triggered after the setMedia to catch parent class script addition. foreach ($objController->js_files as $key => $jsFile) { if (preg_match('/^((https?:)?\/\/)?maps\.google(apis)?\.com\/maps\/api\/js/ui', $jsFile)) { unset($objController->js_files[$key]); } } // Load once using TNTOfficel module API key. $objController->addJS( 'https://maps.googleapis.com/maps/api/js?v='.TNTOfficiel::GMAP_API_VER.'&key=' .$objTNTCarrierAccountModel->api_google_map_key ); $strPickUpNumber = $objTNTCarrierAccountModel->pickup_display_number ? $objTNTOrderModel->pickup_number : null; // Creates parcels for order if not already done. $objTNTOrderModel->createParcels(); // Get the parcels. $arrObjTNTParcelModelList = TNTOfficielParcel::searchOrderID($intHookOrderID); // Check and display error about shipping date. if (!Tools::isSubmit('submitState')) { // Check or update the shipping date. $arrResultPickupDate = $objTNTOrderModel->updatePickupDate(); // If true error. if (is_string($arrResultPickupDate['strResponseMsgError'])) { $objController->errors[] = TNTOfficiel::CARRIER_NAME.' : ' .$arrResultPickupDate['strResponseMsgError']; } /* // If normal error. if (is_string($arrResultPickupDate['strResponseMsgWarning'])) { $objController->warnings[] = TNTOfficiel::CARRIER_NAME.' : ' .$arrResultPickupDate['strResponseMsgWarning']; } */ } $shippingDate = $objTNTOrderModel->shipping_date; $dueDate = ''; if ($objTNTOrderModel->due_date && $objTNTOrderModel->due_date !== '0000-00-00') { $arrTmpDate = explode('-', $objTNTOrderModel->due_date); $dueDate = $arrTmpDate[2].'/'.$arrTmpDate[1].'/'.$arrTmpDate[0]; } $arrTmpDate = explode('-', $objTNTOrderModel->start_date); $firstAvailableDate = $arrTmpDate[2].'/'.$arrTmpDate[1].'/'.$arrTmpDate[0]; $arrDeliveryPoint = $objTNTOrderModel->getDeliveryPoint(); $strDeliveryPointType = $objTNTOrderModel->getDeliveryPointType(); $strDeliveryPointCode = $objTNTOrderModel->getDeliveryPointCode(); $objCustomer = new Customer((int)$objPSOrder->id_customer); $objPSAddressDelivery = TNTOfficielReceiver::getPSAddress($objPSOrder->id_address_delivery); $strAddressPhone = $objTNTReceiverModel::searchPhoneMobile($objPSAddressDelivery); // Validate and store receiver info, using the customer email and address mobile phone as default values. $arrFormReceiverInfoValidate = $objTNTReceiverModel->storeReceiverInfo( $objTNTReceiverModel->receiver_email ? $objTNTReceiverModel->receiver_email : $objCustomer->email, $objTNTReceiverModel->receiver_mobile ? $objTNTReceiverModel->receiver_mobile : $strAddressPhone, $objTNTReceiverModel->receiver_building, $objTNTReceiverModel->receiver_accesscode, $objTNTReceiverModel->receiver_floor ); $strBTLabelName = ''; if ($objTNTOrderModel->isShipped()) { // Load TNT label info or create a new one for it's ID. $objTNTLabelModel = TNTOfficielLabel::loadOrderID($intHookOrderID, false); // If fail. if ($objTNTLabelModel !== null) { $strBTLabelName = $objTNTLabelModel->label_name; } } $this->smarty->assign(array( 'objPSOrder' => $objPSOrder, 'objPSAddressDelivery' => $objPSAddressDelivery, 'strPickUpNumber' => $strPickUpNumber, 'arrObjTNTParcelModelList' => $arrObjTNTParcelModelList, 'firstAvailableDate' => $firstAvailableDate, 'shippingDate' => $shippingDate, 'dueDate' => $dueDate, 'isShipped' => (bool)$objTNTOrderModel->isShipped(), 'strBTLabelName' => $strBTLabelName, 'strDeliveryPointType' => $strDeliveryPointType, 'strDeliveryPointCode' => $strDeliveryPointCode, 'arrFormReceiverInfoValidate' => $arrFormReceiverInfoValidate, 'arrDeliveryPoint' => $arrDeliveryPoint )); if (!$objTNTOrderModel->isShipped()) { $objOrderStateSaveShipment = new OrderState( (int)Configuration::get(TNTOfficiel::ORDERSTATE_SAVESHIPMENT), (int)$this->context->language->id ); if ($strDeliveryPointType !== null && $strDeliveryPointCode === null) { $objController->errors[] = TNTOfficiel::CARRIER_NAME.' : ' .sprintf( $this->l('This order must be finalized before passing the status to %s.'), $objOrderStateSaveShipment->name ).' ' .$this->l('In the CLIENT section, DELIVERY ADDRESS tab, SELECT a delivery point.'); } if ($arrFormReceiverInfoValidate['length'] !== 0) { $objController->errors[] = TNTOfficiel::CARRIER_NAME.' : ' .sprintf( $this->l('This order must be finalized before passing the status to %s.'), $objOrderStateSaveShipment->name ).' ' .$this->l('In the CUSTOMER section, DELIVERY ADDRESS tab, CONFIRM the ADDITIONAL INFORMATION form.'); } } // Display template. return $this->display(__FILE__, 'views/templates/admin/displayAdminOrder.tpl'); /* return $this->fetch(sprintf( 'module:%s/views/templates/admin/displayAdminOrder.tpl', TNTOfficiel::MODULE_NAME )); */ } /** * HOOK (AKA updateCarrier) called when a carrier is updated. * Updating a Carrier means preserve its previous state and adding a new one which include change using a new ID. * * @param array $arrArgHookParams * * @return bool */ public function hookActionCarrierUpdate($arrArgHookParams) { TNTOfficiel_Logstack::log(); $intHookCarrierIDModified = $arrArgHookParams['id_carrier']; $objHookCarrierNew = $arrArgHookParams['carrier']; // Update it. return TNTOfficielCarrier::updateCarrierID( $intHookCarrierIDModified, $objHookCarrierNew->id ); } /** * Carrier module : Method triggered form Cart Model if $carrier->need_range == false. * Get the cart shipping price without using the ranges. * (best price). * * @param Cart $objArgCart * * @return float|false */ public function getOrderShippingCostExternal($objArgCart) { TNTOfficiel_Logstack::log(); $fltPrice = $this->getOrderShippingCost($objArgCart, 0.0); return $fltPrice; } /** * Carrier module : Method triggered form Cart Model if $carrier->need_range == true. * Get the shipping price depending on the ranges that were set in the back office. * Get the shipping cost for a cart (best price), if carrier need range (default). * * @param Cart $objArgCart * * @return float|false false if no shipping cost (not available). */ public function getOrderShippingCost($objArgCart, $fltArgShippingCost) { TNTOfficiel_Logstack::log(); // See comment about current class $id_carrier property. $intCartID = (int)$objArgCart->id; $intCarrierID = (int)$this->id_carrier; $intAddressIDDelivery = (int)$objArgCart->id_address_delivery; // If cart carrier is not created by tntofficiel module. if (!TNTOfficielCarrier::isTNTOfficielCarrierID($intCarrierID)) { // No shipping cost, not available. return false; } // If module not ready. if (!TNTOfficiel::isContextReady()) { // No shipping cost, not available. return false; } // Load an existing TNT carrier. $objTNTCarrierModel = TNTOfficielCarrier::loadCarrierID($intCarrierID, false); // If fail or carrier is not from TNT module. if ($objTNTCarrierModel === null) { // No shipping cost, not available. return false; } $objTNTCarrierAccountModel = $objTNTCarrierModel->getTNTAccountModel(); // If no account available for this carrier, or is not authenticated. if ($objTNTCarrierAccountModel === null || $objTNTCarrierAccountModel->getAuthValidatedDateTime() === null ) { // No shipping cost, not available. return false; } $objTNTCartModel = TNTOfficielCart::loadCartID($intCartID, true); if ($objTNTCartModel === null) { // No shipping cost, not available. return false; } // Multi-Shipping with multiple address or different carrier not supported. $boolMultiShippingSupport = $objTNTCartModel->isMultiShippingSupport(); if (!$boolMultiShippingSupport) { return false; } $arrObjTNTCarrierModelList = TNTOfficielCarrier::getFeasibilitiesContextCarrierModelList( // Get the heaviest product weight from cart. $objTNTCartModel->getCartHeaviestProduct(), $intAddressIDDelivery ); // If carrier is feasible. if (array_key_exists($intCarrierID, $arrObjTNTCarrierModelList)) { $objTNTCarrierModel = $arrObjTNTCarrierModelList[$intCarrierID]; $fltPrice = $objTNTCarrierModel->getPrice( $objTNTCartModel->getCartTotalWeight(), $objTNTCartModel->getCartTotalPrice(), $intAddressIDDelivery ); // Use native Prestashop price. if ($fltPrice === null) { return $fltArgShippingCost; } // Carrier is disabled. if ($fltPrice === false) { return false; } // Get additional shipping cost for cart. $fltCartExtraShippingCost = $objTNTCartModel->getCartExtraShippingCost($intCarrierID); return $fltPrice + $fltCartExtraShippingCost; } // No shipping cost, not available. return false; } /** * HOOK (AKA updateOrderStatus) called when an order's status is changed, right before it is actually changed. * If status become ORDERSTATE_SAVESHIPMENT, then creates a shipment using middleware service 'saveShipment'. * * @param array $arrArgHookParams */ public function hookActionOrderStatusUpdate($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objHookCookie = $arrArgHookParams['cookie']; $objHookOrderStateNew = $arrArgHookParams['newOrderStatus']; $intHookOrderID = (int)$arrArgHookParams['id_order']; $intOrderStateIDNew = (int)$objHookOrderStateNew->id; // If new order status must trigger shipment creation. if (Configuration::get(TNTOfficiel::ORDERSTATE_SAVESHIPMENT) == $intOrderStateIDNew) { $objPSOrder = TNTOfficielOrder::getPSOrder($intHookOrderID); if ($objPSOrder === null) { return; } $intCarrierID = (int)$objPSOrder->id_carrier; // Load an existing TNT carrier. $objTNTCarrierModel = TNTOfficielCarrier::loadCarrierID($intCarrierID, false); // If fail or carrier is not from TNT module. if ($objTNTCarrierModel === null) { // Do nothing. return; } // Load TNT order info for it's ID. $objTNTOrderModel = TNTOfficielOrder::loadOrderID($intHookOrderID, false); // If fail. if ($objTNTOrderModel === null) { $objHookCookie->TNTOfficielError = 'Order not found for Order ID #'.$intHookOrderID; // Do nothing. return; } // Check or update the shipping date. $arrResultPickupDate = $objTNTOrderModel->updatePickupDate(); // If true error. if (is_string($arrResultPickupDate['strResponseMsgError'])) { $objHookCookie->TNTOfficielError = $arrResultPickupDate['strResponseMsgError']; } elseif (!$objTNTOrderModel->isShipped()) { // Send a shipment request to the middleware. $arrResponse = $objTNTOrderModel->saveShipment(); // If the response is a string, there is an error. if (is_string($arrResponse['strResponseMsgError'])) { $objHookCookie->TNTOfficielError = $arrResponse['strResponseMsgError']; } } // If normal error. if (is_string($arrResultPickupDate['strResponseMsgWarning'])) { $objHookCookie->TNTOfficielWarning = $arrResultPickupDate['strResponseMsgWarning']; } // If order has no shipment created. if ($objTNTOrderModel === null || !$objTNTOrderModel->isShipped()) { // Default error message. if (!$objHookCookie->TNTOfficielError) { $objHookCookie->TNTOfficielError = $this->l('Error create shipping'); } // Log. TNTOfficiel_Logger::logException(new Exception($objHookCookie->TNTOfficielError)); // Redirect to prevent new order state (cleaner than reverting). Tools::redirectAdmin( $this->context->link->getAdminLink('AdminOrders', false) .'&id_order='.$objPSOrder->id.'&vieworder' .'&token='.Tools::getAdminTokenLite('AdminOrders') //.'&setShopContext=s-'.$objPSOrder->id_shop ); } } } /** * HOOK (AKA postUpdateOrderStatus) called when an order's status is changed, right after it is actually changed. * Alert if the shipment was not saved (for an unknown reason). * * @param array $arrArgHookParams */ public function hookActionOrderStatusPostUpdate($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objHookCookie = $arrArgHookParams['cookie']; $objHookOrderStateNew = $arrArgHookParams['newOrderStatus']; $intHookOrderID = (int)$arrArgHookParams['id_order']; $objPSOrder = new Order($intHookOrderID); $intOrderStateIDNew = (int)$objHookOrderStateNew->id; $intCarrierID = (int)$objPSOrder->id_carrier; // Load an existing TNT carrier. $objTNTCarrierModel = TNTOfficielCarrier::loadCarrierID($intCarrierID, false); // If fail or carrier is not from TNT module. if ($objTNTCarrierModel === null) { // Do nothing. return; } // Check if the new order status is the one that must trigger shipment creation. if (Configuration::get(TNTOfficiel::ORDERSTATE_SAVESHIPMENT) == $intOrderStateIDNew) { // Load TNT order info for it's ID. $objTNTOrderModel = TNTOfficielOrder::loadOrderID($intHookOrderID, false); // If order has no shipment created. if ($objTNTOrderModel === null || !$objTNTOrderModel->isShipped()) { TNTOfficiel_Logger::logException(new Exception($this->l('Error create shipping'))); if (!$objHookCookie->TNTOfficielError) { $objHookCookie->TNTOfficielError = $this->l('Error create shipping'); } } } } /** * HOOK (AKA orderDetailDisplayed) displayed on order detail on Front-Office. * Insert parcel tracking block on order detail. * * @param array $arrArgHookParams * * @return string */ public function hookDisplayOrderDetail($arrArgHookParams) { TNTOfficiel_Logstack::log(); $objHookOrder = $arrArgHookParams['order']; $intHookOrderID = (int)$objHookOrder->id; // Load an existing TNT carrier. $objTNTCarrierModel = TNTOfficielCarrier::loadCarrierID($objHookOrder->id_carrier, false); // If fail or carrier is not from TNT module. if ($objTNTCarrierModel === null) { // Display nothing. return ''; } // Load TNT order info for it's ID. $objTNTOrderModel = TNTOfficielOrder::loadOrderID($intHookOrderID, false); // If order has no shipment created. if ($objTNTOrderModel === null || !$objTNTOrderModel->isShipped()) { // Display nothing. return ''; } $this->smarty->assign(array( 'trackingUrl' => $this->context->link->getModuleLink( TNTOfficiel::MODULE_NAME, 'tracking', array('action' => 'tracking', 'orderId' => $intHookOrderID), true ) )); // Display template. return $this->fetch(sprintf( 'module:%s/views/templates/hook/displayOrderDetail.tpl', TNTOfficiel::MODULE_NAME )); } }