* @copyright 2016-2017 GFI Informatique, 2016-2017 TNT * @license https://opensource.org/licenses/MIT MIT License */ require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_Debug.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_Logger.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_JsonRPCClient.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_PasswordManager.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/helper/TNTOfficiel_OrderHelper.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/helper/TNTOfficiel_AddressHelper.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/helper/TNTOfficiel_ParcelsHelper.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/exceptions/TNTOfficiel_OrderAlreadyShippedException.php'; class TNTOfficiel_ShipmentHelper { /** * The directory where the BT are stored. */ const BT_DIR = 'tnt_media/media/bt'; /** @var Singleton */ private static $_instance = null; /** @var TNTOfficiel_Logger */ private $logger; /** * Constructor. */ public function __construct() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $this->logger = new TNTOfficiel_Logger(); } /** * Creates a singleton. * * @param void * * @return TNTOfficiel_ShipmentHelper */ public static function getInstance() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); if (is_null(TNTOfficiel_ShipmentHelper::$_instance)) { TNTOfficiel_ShipmentHelper::$_instance = new TNTOfficiel_ShipmentHelper(); } return TNTOfficiel_ShipmentHelper::$_instance; } /** * Send a shipment request to the middleware. * * @param $cart * @param $orderId * * @return bool * * @throws Exception */ public function saveShipment($cart, $orderId) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $order = new Order($orderId); try { $arrTNTOrder = TNTOfficiel_OrderHelper::getInstance()->getOrderData($orderId); if ($arrTNTOrder['is_shipped']) { throw new TNTOfficiel_OrderAlreadyShippedException('The shipment has already been created for the order ' + $orderId); } $arrTNTAddress = TNTOfficiel_AddressHelper::getInstance()->getAddressData($order->id_address_delivery, $order->id_cart); $parcels = TNTOfficiel_ParcelsHelper::getInstance()->getParcels($orderId); } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); throw $objException; } //call the middleware $arrParams = $this->_getParams( $cart->id_shop, $arrTNTOrder, $arrTNTAddress, $this->_getParcelsData($parcels, $order->reference), $arrTNTOrder['shipping_date'] ); $response = $this->_callMiddleware($arrParams); if (is_string($response)) { throw new PrestaShopException($response); } //save the BT if ($response) { $this->_saveBT($response['bt'], $order); $this->_saveTrackingUrls($response['parcels'], $orderId); $this->_savePickupNumber($response['pickUpNumber'], $orderId); } return true; } /** * Check if a shipment was successfully done for an order. * * @param $orderId * * @return bool */ public function isShipmentSaved($orderId) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $sql = 'SELECT * FROM '._DB_PREFIX_.'tntofficiel_order WHERE id_order = '.(int)$orderId; $arrOrder = Db::getInstance()->getRow($sql, false); return (bool)$arrOrder['is_shipped']; } /** * Get the params. * * @param $intArgShopID * @param $arrArgTNTOrder * @param $arrArgTNTAddress * @param $parcelsData * * @return array */ private function _getParams($intArgShopID, $arrArgTNTOrder, $arrArgTNTAddress, $parcelsData, $shippingDate = false) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $productCode = $arrArgTNTOrder['carrier_code']; $typeId = (empty($arrArgTNTOrder['carrier_xett'])) ? $arrArgTNTOrder['carrier_pex'] : $arrArgTNTOrder['carrier_xett']; $arrParams = array( 'store' => $intArgShopID, 'merchant' => array( 'identity' => Configuration::get('TNT_CARRIER_USERNAME'), 'password' => TNTOfficiel_PasswordManager::getHash(), 'merchant_number' => Configuration::get('TNT_CARRIER_ACCOUNT'), ), 'product' => $productCode, 'recipient' => array( 'xett' => $arrArgTNTOrder['carrier_xett'], 'pex' => $arrArgTNTOrder['carrier_pex'], 'firstname' => $arrArgTNTAddress['firstname'], 'lastname' => $arrArgTNTAddress['lastname'], 'address1' => Tools::substr($arrArgTNTAddress['address1'], 0, 32), 'address2' => Tools::substr($arrArgTNTAddress['address2'], 0, 32), 'post_code' => $arrArgTNTAddress['postcode'], 'city' => $arrArgTNTAddress['city'], 'email' => $arrArgTNTAddress['customer_email'], 'phone' => $arrArgTNTAddress['customer_mobile'], 'access_code' => $arrArgTNTAddress['address_accesscode'], 'floor' => $arrArgTNTAddress['address_floor'], 'building' => $arrArgTNTAddress['address_building'], 'name' => $arrArgTNTAddress['company'], 'typeId' => $typeId, ), 'parcels' => $parcelsData, ); if ($shippingDate) { $arrParams['shipping_date'] = $shippingDate; } return $arrParams; } /** * Get parcels data. * * @param $parcels array * * @return array */ private function _getParcelsData($parcels, $orderReference) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $parcelsData = array(); foreach ($parcels as $parcel) { $parcelsData[] = array( 'reference' => $orderReference, 'weight' => $parcel['weight'], ); } return $parcelsData; } /** * Call the middleware to save the shipment. * * @param $params * * @return mixed * * @throws Exception */ private function _callMiddleware($params) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $client = new TNTOfficiel_JsonRPCClient(Configuration::get('TNT_CARRIER_MIDDLEWARE_URL')); try { $result = $client->execute('saveShipment', $params); $this->logger->logMessageTnt('saveShipment', null, 'JSON', true, 'SUCCESS'); } catch (Exception $objException) { $strStatus = ($objException->getCode() == 500) ? 'FATAL' : 'ERROR'; $strMsg = $objException->getMessage(); $this->logger->logMessageTnt('saveShipment', $strMsg, 'JSON', false, $strStatus); throw $objException; } return $result; } /** * Call the middleware to save the shipment. * * @param $params * * @return mixed * * @throws Exception */ private function _callMiddlewareWithService($params, $service) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $client = new TNTOfficiel_JsonRPCClient(Configuration::get('TNT_CARRIER_MIDDLEWARE_URL')); try { $result = $client->execute($service, $params); $this->logger->logMessageTnt($service, null, 'JSON', true, 'SUCCESS'); } catch (Exception $objException) { $strStatus = ($objException->getCode() == 500) ? 'FATAL' : 'ERROR'; $strMsg = $objException->getMessage(); $this->logger->logMessageTnt($service, $strMsg, 'JSON', false, $strStatus); throw $objException; } return $result; } /** * Saves the BT in the file system. * * @param $strBTContent * @param $order * * @throws Exception */ private function _saveBT($strBTContent, $order) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); //creates the directory if not exists if (!is_dir(_PS_MODULE_DIR_.TNTOfficiel_ShipmentHelper::BT_DIR)) { mkdir(_PS_MODULE_DIR_.TNTOfficiel_ShipmentHelper::BT_DIR, 0777, true); } $date = date('Y-m-d_H-i-s'); $strBTFilename = sprintf('BT_%s_%s.pdf', $order->reference, $date); //create the file try { file_put_contents(_PS_MODULE_DIR_.TNTOfficiel_ShipmentHelper::BT_DIR.'/'.$strBTFilename, utf8_decode($strBTContent)); Db::getInstance()->update( 'tntofficiel_order', array('bt_filename' => pSQL($strBTFilename), 'is_shipped' => true, 'previous_state' => (int)$order->current_state), 'id_order = '.(int)$order->id ); } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); throw $objException; } } /** * Saves the tracking url for each parcel. * * @param $tntParcels * @param $orderId * * @throws Exception */ private function _saveTrackingUrls($tntParcels, $orderId) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $sql = 'SELECT * FROM '._DB_PREFIX_.'tntofficiel_order_parcels where id_order = '.(int)$orderId; $parcels = Db::getInstance()->executeS($sql); $i = 0; foreach ($tntParcels as $tntParcel) { try { Db::getInstance()->update( 'tntofficiel_order_parcels', array( 'tracking_url' => pSQL($tntParcel['tracking_url']), 'parcel_number' => pSQL($tntParcel['number']), ), 'id_parcel = '.pSQL($parcels[$i]['id_parcel']) ); } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); throw $objException; } ++$i; } } private function _savePickupNumber($pickupNumber, $orderId) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $sql = 'SELECT * FROM '._DB_PREFIX_.'tntofficiel_order where id_order = '.(int)$orderId; $orders = Db::getInstance()->executeS($sql); foreach ($orders as $order) { Db::getInstance()->update( 'tntofficiel_order', array('pickup_number' => pSQL($pickupNumber)), 'id_tntofficiel_order = '.(int)$order['id_tntofficiel_order'] ); } } /** * Get the first available shipping date. * * @param $cart * @param $intArgOrderID * * @return string|bool * * @throws Exception */ public function getShippingDate($intArgOrderID) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $objOrder = new Order($intArgOrderID); try { $arrTNTOrder = TNTOfficiel_OrderHelper::getInstance()->getOrderData($intArgOrderID); if ($arrTNTOrder['is_shipped']) { throw new TNTOfficiel_OrderAlreadyShippedException('The shipment has already been created for the order ' + $intArgOrderID); } $arrTNTAddress = TNTOfficiel_AddressHelper::getInstance()->getAddressData($objOrder->id_address_delivery, $objOrder->id_cart); $parcels = TNTOfficiel_ParcelsHelper::getInstance()->getParcels($intArgOrderID); } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); throw $objException; } //call the middleware $arrParams = $this->_getParams( $objOrder->id_shop, $arrTNTOrder, $arrTNTAddress, $this->_getParcelsData($parcels, $objOrder->reference) ); $arrMDWResponse = $this->_callMiddlewareWithService($arrParams, 'getShippingDate'); if (is_string($arrMDWResponse)) { throw new PrestaShopException($arrMDWResponse); } return $arrMDWResponse; } /** * Get the first available shipping date. * * @param $cart * @param $orderId * * @return string|bool * * @throws Exception */ public function checkSaveShipmentDate($orderId, $shippingDate) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $order = new Order($orderId); try { $arrTNTOrder = TNTOfficiel_OrderHelper::getInstance()->getOrderData($orderId); $arrTNTAddress = TNTOfficiel_AddressHelper::getInstance()->getAddressData($order->id_address_delivery, $order->id_cart); $parcels = TNTOfficiel_ParcelsHelper::getInstance()->getParcels($orderId); } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); throw $objException; } //call the middleware $arrParams = $this->_getParams( $order->id_shop, $arrTNTOrder, $arrTNTAddress, $this->_getParcelsData($parcels, $order->reference), $shippingDate ); $arrMDWResponse = $this->_callMiddlewareWithService($arrParams, 'checkSaveShipment'); return $arrMDWResponse; } public function getNewShippingDate($intArgOrderID) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $arrMDWShippingDate = TNTOfficiel_ShipmentHelper::getInstance()->getShippingDate($intArgOrderID); //$shippingDatePrepa = $response['shippingDatePrepa']; $shippingDatePrepa = $arrMDWShippingDate['shippingDate']; $arrMDWShippingDate = TNTOfficiel_ShipmentHelper::getInstance()->checkSaveShipmentDate($intArgOrderID, $shippingDatePrepa); if (!array_key_exists('shippingDate', $arrMDWShippingDate)) { return false; } return $arrMDWShippingDate; } }