')
);
// Check if we have data from previous sending try
//$show_dst_block = false;
$delivery_info = $post_data['delivery'];
if (count($delivery_info) > 1) {
//$show_dst_block = true;
$data['delivery'] = $delivery_info;
}
$emc_carrier =
isset($data['order'][0]['external_module_name']) && $data['order'][0]['external_module_name'] == $this->name;
$offer_data = $this->getOfferToSendPage($data, $helper, $post_data);
$smarty->assign('local_fancybox', $this->useLocalFancybox());
$smarty->assign('proforma', $offer_data['isProforma']);
$smarty->assign('proformaData', $offer_data['proforma']);
$smarty->assign('offer', $offer_data['offer']);
$smarty->assign('offers', $offer_data['allOffers']);
$smarty->assign('offersNb', count($offer_data['allOffers']));
$smarty->assign('installedServices', $offer_data['installedSrv']);
$smarty->assign('isFound', $offer_data['isFound']);
$smarty->assign('isEMCCarrier', $emc_carrier);
$smarty->assign('insuranceHtml', isset($offer_data['insuranceHtml']) ? $offer_data['insuranceHtml'] : '');
if (!$emc_carrier) {
$data['order'][0]['label_es'] = $data['order'][0]['name'];
$data['order'][0]['name_eo'] = $data['order'][0]['name'];
}
$smarty->assign('orderInfo', $data['order'][0]);
$smarty->assign('deliveryInfo', $data['delivery']);
$smarty->assign('shipperInfo', array(
'country' => 'FR',
'postalcode' => $config['EMC_POSTALCODE'],
'city' => $config['EMC_CITY']
));
$smarty->assign('orderId', $order_id);
$smarty->assign('envUrl', $this->environments[$config['EMC_ENV']]['link']);
$smarty->assign('multiParcel', $config['EMC_MULTIPARCEL'] == 'on');
$smarty->assign('token', Tools::getValue('token'));
$smarty->assign('alreadyPassed', $this->isPassed($order_id));
$smarty->assign('isSendLocked', $this->isSendLocked($order_id));
$smarty->assign('emcBaseDir', _MODULE_DIR_ . '/envoimoinscher/');
$weight = $data['productWeight'];
$parcels = $post_data['parcels'];
$parcels_length = count($parcels);
if ($parcels_length < 2) {
$parcels_length = '';
$parcels = array();
} else {
$weight = 0;
foreach ($parcels as $parcel) {
$weight += (float)$parcel;
}
}
$smarty->assign('parcels', $parcels);
$smarty->assign('baseJs', _PS_JS_DIR_);
$smarty->assign('dimensions', $data['dimensions']);
$smarty->assign('parcelsLength', $parcels_length);
unset($cookie->emc_order_parcels);
$smarty->assign('adminImg', _PS_ADMIN_IMG_);
$smarty->assign('baseDirCss', __PS_BASE_URI__);
$smarty->assign('moduleBaseDir', _PS_MODULE_DIR_ . 'envoimoinscher/');
$smarty->assign('showDstBlock', count($delivery_info) > 1 || (!$emc_carrier && !$offer_data['isFound']));
$smarty->assign('weight', $weight);
$smarty->assign('tableTemplate', _PS_MODULE_DIR_ . 'envoimoinscher/views/templates/admin/offersTable.tpl');
$smarty->assign(
'notFoundTemplate',
_PS_MODULE_DIR_ . 'envoimoinscher/views/templates/admin/offersNotFound.tpl'
);
if (!empty($order_stats)) {
$smarty->assign('ordersAll', $order_stats['total']);
$smarty->assign('ordersDone', $order_stats['skipped'] + $order_stats['ok'] + $order_stats['errors']);
$smarty->assign(
'orderTodo',
$order_stats['total'] - ($order_stats['skipped'] + $order_stats['ok'] + $order_stats['errors'])
);
} else {
$smarty->assign('orderTodo', 0);
$order_stats['total'] = 0;
}
$smarty->assign('nextOrderId', $emc_order->getNextOrderId());
$smarty->assign('massTemplate', _PS_MODULE_DIR_ . 'envoimoinscher/views/templates/admin/massOrders.tpl');
$smarty->assign('checkAssu', ((int)EnvoimoinscherModel::getConfig('EMC_ASSU') == 1));
if ($post_data['emcErrorSend'] == 1 && ($order_stats['total'] == 0 || $emc_order->isErrorType())) {
$smarty->assign('errorMessage', $post_data['emcErrorTxt']);
$smarty->assign('showErrorMessage', 1);
$smarty->assign('errorType', 'order');
} elseif (count($offer_data['errors']) > 0) {
$smarty->assign('errorMessage', implode(' ', $offer_data['errors']));
$smarty->assign('showErrorMessage', 1);
$smarty->assign('errorType', 'quote');
}
$this->model->removeTemporaryPost($order_id); // Delete post values
$cookie->normal_order_passed = -1; // show nothing on table page
if ((float)$weight == 0) {
$html .= parent::adminDisplayWarning(
$this->l(
'Your order has not weight, please check your products.'
)
);
}
return $html . $this->display(__FILE__, '/views/templates/admin/send.tpl');
}
/**
* Gets offer for changed weight.
* @access public
* @return Displayed template.
*/
public function getOffersNewWeight()
{
$smarty = $this->getContext()->smarty;
$order_id = (int)Tools::getValue('id_order');
$helper = new EnvoimoinscherHelper(EnvoimoinscherModel::getConfig('EMC_TYPE'));
$config = EnvoimoinscherModel::getConfigData();
$data = $this->model->prepareOrderInfo($order_id, $config);
$data['productWeight'] = (float)str_replace(',', '.', Tools::getValue('weight'));
// If option 'use content as parcel description' is checked
if ((int)$config['EMC_CONTENT_AS_DESC'] == 1) {
$category_row = EnvoimoinscherModel::getNameCategory($config['EMC_NATURE']);
$data['default']['colis.description'] = $category_row;
}
$offer_data = $this->getOfferToSendPage($data, $helper, false);
$smarty->assign('offer', $offer_data['offer']);
$smarty->assign('orderInfo', $data['order'][0]);
$smarty->assign('isFound', $offer_data['isFound']);
$smarty->assign('installedServices', $offer_data['installedSrv']);
$smarty->assign('offers', $offer_data['allOffers']);
$smarty->assign('offersNb', count($offer_data['allOffers']));
$smarty->assign('isajax', 1);
$smarty->assign('modifPrice', 1); // template was reloaded after weight or multi parcel change
$smarty->assign('adminImg', _PS_ADMIN_IMG_);
$smarty->assign('orderId', $order_id);
$smarty->assign('token', Tools::getValue('token'));
$smarty->assign('isEMCCarrier', $data['order'][0]['external_module_name'] == $this->name);
if ($offer_data['isFound']) {
return $this->display(__FILE__, '/views/templates/admin/offersTable.tpl');
} else {
return $this->display(__FILE__, '/views/templates/admin/offersNotFound.tpl');
}
}
/**
* Commands the shipping offer.
* @access public
* @return void
*/
public function command()
{
$cookie = $this->getContext()->cookie;
$helper = new EnvoimoinscherHelper(EnvoimoinscherModel::getConfig('EMC_TYPE'));
$config = EnvoimoinscherModel::getConfigData();
$order_id = (int)Tools::getValue('id_order');
$emc_order = new EnvoimoinscherOrder($this->model);
$stats = $emc_order->getStats();
$is_mass_order = (isset($stats['total']) && $stats['total'] > 0);
$emc_order->setOrderId($order_id);
$data = $this->model->prepareOrderInfo($emc_order->getOrderId(), $config);
$emc_order->setPrestashopConfig($this->getModuleConfig());
$emc_order->setOrderData($data);
$emc_order->setOfferData($this->getOfferToSendPage($data, $helper));
$result = $emc_order->doOrder(false);
if ($is_mass_order && ($result || (!$result && !$emc_order->isErrorType()))) {
$emc_order->skipOrder($order_id);
$emc_order->updateOrdersList();
}
$admin_link_base = $this->link->getAdminLink('AdminEnvoiMoinsCher');
if ($is_mass_order && $emc_order->doOtherOrders()) {
if (!$result && $emc_order->isErrorType()) {
Tools::redirectAdmin($admin_link_base . '&id_order=' . $order_id . '&option=send');
die();
}
// make next order
$this->model->removeTemporaryPost($order_id);
$emc_order->setOrderId(0);
Tools::redirectAdmin($admin_link_base . '&id_order=' . $emc_order->getOrderId() . '&option=send');
die();
} elseif ($is_mass_order && !$emc_order->doOtherOrders()) {
$this->model->removeTemporaryPost($order_id);
$cookie->mass_order_passed = 1;
Tools::redirectAdmin($admin_link_base);
die();
} elseif (!$is_mass_order) {
$cookie->normal_order_passed = (int)$result;
if ($result) {
Tools::redirectAdmin($admin_link_base);
die();
}
}
Tools::redirectAdmin($admin_link_base . '&id_order=' . $order_id . '&option=send');
die();
}
/**
* Replaces old offer by the new one.
* @return Smarty Smarty template.
*/
public function replaceOffer()
{
$cookie = $this->getContext()->cookie;
require_once('Env/WebService.php');
require_once('Env/Quotation.php');
$order_id = (int)Tools::getValue('id_order');
$code = explode('_', Tools::getValue('code'));
if (ctype_alnum($code[0]) && ctype_alnum($code[1])) {
$rows = Db::getInstance()->ExecuteS('SELECT * FROM ' . _DB_PREFIX_ . 'emc_services es
JOIN ' . _DB_PREFIX_ . 'emc_operators eo ON eo.code_eo = es.emc_operators_code_eo
LEFT JOIN ' . _DB_PREFIX_ . 'carrier c ON c.id_carrier = es.id_carrier
WHERE es.code_es = "' . $code[1] . '" AND es.emc_operators_code_eo = "' . $code[0] . '"');
if (count($rows) == 0 || (int)$rows[0]['id_carrier'] == 0) {
// get default tracking urls
$tracking_urls = EnvoimoinscherHelper::$tracking_urls;
// carrier was not found, insert a new carrier (which is deleted)
$data = array(
'name' => EnvoimoinscherHelper::getTranslation($rows[0]['srv_name_fo_es'], 'fr-fr'),
'active' => 0,
'is_module' => 1,
'need_range' => 1,
'deleted' => 1,
'range_behavior' => 1,
'shipping_external' => 1,
'external_module_name' => pSQL($this->name),
'url' => isset($tracking_urls[$rows[0]['emc_operators_code_eo'] . '_' . $rows[0]['code_es']]) ?
pSQL($tracking_urls[$rows[0]['emc_operators_code_eo'] . '_' . $rows[0]['code_es']]) : ''
);
$lang_data = array(
'id_lang' => (int)$cookie->id_lang,
'delay' => pSQL($rows[0]['desc_store_es'])
);
Db::getInstance()->autoExecute(_DB_PREFIX_ . 'carrier', $data, 'INSERT');
$lang_data['id_carrier'] = (int)Db::getInstance()->Insert_ID();
DB::getInstance()->Execute('UPDATE ' . _DB_PREFIX_ . 'carrier SET
id_reference = '. $lang_data['id_carrier'] .' WHERE id_carrier = '.(int)$lang_data['id_carrier']);
Db::getInstance()->autoExecute(_DB_PREFIX_ . 'carrier_lang', $lang_data, 'INSERT');
// prestashop standard ...
$carrier = array('id_carrier' => (int)$lang_data['id_carrier'], 'id_group' => 0);
Db::getInstance()->autoExecute(_DB_PREFIX_ . 'carrier_group', $carrier, 'INSERT');
$rows[0]['id_carrier'] = $lang_data['id_carrier'];
DB::getInstance()->Execute(
'UPDATE ' . _DB_PREFIX_ . 'emc_services
SET id_carrier = ' . (int)$lang_data['id_carrier'] . ',
ref_carrier = ' . (int)$lang_data['id_carrier'] . '
WHERE id_es = ' . (int)$rows[0]['id_es'] . ''
);
}
// update carrier for this order (check first if order exists in order_carrier)
$row = Db::getInstance()->getRow(
'SELECT * FROM ' . _DB_PREFIX_ . 'order_carrier WHERE id_order = ' . (int)$order_id
);
if ($row == false) {
Db::getInstance()->update(
'orders',
array(
'id_carrier' => (int)$rows[0]['id_carrier'],
),
'id_order = ' . (int)$order_id
);
} else {
Db::getInstance()->update(
'order_carrier',
array(
'id_carrier' => (int)$rows[0]['id_carrier'],
),
'id_order = ' . (int)$order_id
);
}
}
$admin_link_base = $this->link->getAdminLink('AdminEnvoiMoinsCher');
Tools::redirectAdmin($admin_link_base . '&option=send&id_order=' . $order_id);
}
/**
* Tracking function.
* @return Smarty Smarty template.
*/
public function getTracking()
{
$smarty = $this->getContext()->smarty;
$order_id = (int)Tools::getValue('id_order');
// get tracking informations
$order = $this->model->getOrderData($order_id);
$smarty->assign('rows', $this->model->getTrackingInfos($order_id));
$smarty->assign('order', $order[0]);
$smarty->assign('isAdmin', true);
return $this->display(__FILE__, '/views/templates/admin/tracking.tpl');
}
/**
* Gets offer choosen by customer.
* @access public
* @param arrat $data Configuration data.
* @return array
*/
public function getOfferToSendPage($data, $helper, $session_data = array())
{
$cookie = $this->getContext()->cookie;
$config = EnvoimoinscherModel::getConfigData();
if (isset($session_data['quote']) && count($session_data['quote']) > 0) {
$quote_data = $session_data['quote'];
}
if (isset($session_data['parcels']) && count($session_data['parcels']) > 0) {
$data['parcels'] = $session_data['parcels'];
}
require_once('Env/WebService.php');
require_once('Env/Quotation.php');
// EnvoiMoinsCher library
$cot_cl = new EnvQuotation(
array(
'user' => $config['EMC_LOGIN'],
'pass' => $config['EMC_PASS'],
'key' => $config['EMC_KEY_' . $config['EMC_ENV']]
)
);
$cot_cl->setPlatformParams($this->ws_name, _PS_VERSION_, $this->version);
$quot_info = array(
'collecte' => $this->setCollectDate(array(
'j1' => $config['EMC_PICKUP_J1'],
'j2' => $config['EMC_PICKUP_J2'],
'split' => $config['EMC_PICKUP_SPLIT'],
)),
'type_emballage.emballage' => EnvoimoinscherModel::getConfig('EMC_WRAPPING'),
'delai' => 'aucun',
'code_contenu' => $config['EMC_NATURE'],
'valeur' => (float)$data['order'][0]['total_products'],
'module' => $this->ws_name,
'version' => $this->local_version
);
$cot_cl->setEnv(Tools::strtolower($config['EMC_ENV']));
$cot_cl->setLocale($this->getContext()->language->language_code);
$cot_cl->setPerson(
'expediteur',
array(
'pays' => 'FR',
'code_postal' => $config['EMC_POSTALCODE'],
'ville' => $config['EMC_CITY'],
'type' => 'entreprise',
'adresse' => $config['EMC_ADDRESS']
)
);
$cot_cl->setPerson(
'destinataire',
array(
'pays' => $data['delivery']['pays'],
'code_postal' => $data['delivery']['code_postal'],
'ville' => $data['delivery']['ville'],
'type' => $data['delivery']['type'],
'adresse' => $data['delivery']['adresse']
)
);
$cot_cl->setType($config['EMC_TYPE'], $data['parcels']);
@$cot_cl->getQuotation($quot_info); // Init params for Quotation
$cot_cl->getOffers(false); // Get Offers
$is_found = false;
$final_offer = $proforma_data = array();
$is_proforma = false;
// $helper = new EnvoimoinscherHelper;
foreach ($cot_cl->offers as $o => $offer) {
if ($offer['operator']['code'] == $data['order'][0]['emc_operators_code_eo'] &&
$offer['service']['code'] == $data['order'][0]['code_es']) {
// handle session data
$offer['priceInsHT'] = (float)isset($offer['insurance']) ? $offer['insurance']['tax-exclusive'] : 0;
$offer['priceInsTTC'] = (float)isset($offer['insurance']) ? $offer['insurance']['tax-inclusive'] : 0;
$offer['priceHTNoIns'] = $offer['price']['tax-exclusive'];
$offer['priceTTCNoIns'] = $offer['price']['tax-inclusive'];
$offer['priceHT'] = $offer['price']['tax-exclusive'] + $offer['priceInsHT'];
$offer['priceTTC'] = $offer['price']['tax-inclusive'] + $offer['priceInsTTC'];
$offer['insurance'] = $data['default']['assurance.selection'];
$offer['collect'] = date('d-m-Y', strtotime($offer['collection']['date']));
$offer['delivery'] = date('d-m-Y', strtotime($offer['delivery']['date']));
foreach ($offer['mandatory'] as $mandatory) {
// special case : Chronopost (we have to pass an parameter for parcel point)
$default_info = '';
if (isset($quote_data[$mandatory['code']])) {
$default_info = $quote_data[$mandatory['code']];
} elseif (isset($data['default'][$mandatory['code']])) {
$default_info = $data['default'][$mandatory['code']];
}
$field_type = 'text';
if ($mandatory['code'] == 'depot.pointrelais' || $mandatory['code'] == 'retrait.pointrelais') {
if (strpos($default_info, '-') !== false) {
$data_def = explode('-', $default_info);
if (count($data_def) > 1) {
$info = $data_def[count($data_def) - 1];
} else {
$info = $data_def[1];
}
$default_info = $info;
}
if (preg_match('/POST/i', $mandatory['array'][0])) {
$field_type = 'hidden';
}
}
$offer['output'][] = $helper->prepareMandatory($mandatory, $default_info, $field_type, true);
}
if (isset($offer['mandatory']['proforma.description_en'])
&& count($offer['mandatory']['proforma.description_en']) > 0) {
$is_proforma = true;
$proforma_data = $data['proforma'];
$session_proforma = Tools::jsonDecode($cookie->emc_order_proforma, true);
if (isset($session_proforma[1]) && count($session_proforma[1]) > 1) {
$proforma_data = $session_proforma;
}
}
$assurance_html = array();
if (isset($offer['options']['assurance']['parameters'])) {
foreach ($offer['options']['assurance']['parameters'] as $a => $assurance) {
$default = '';
if (isset($session_data['quote'][$a])) {
$default = $session_data['quote'][$a];
} elseif (is_array($assurance['values']) && !empty($assurance['values'])) {
$default = min(array_keys($assurance['values']));
}
$helper->putNewInsuranceChoice($a, $assurance['values']);
$mandatory = array('code' => $a, 'label' => $assurance['label']);
$assurance_html[] = $helper->prepareMandatory($mandatory, $default, 'select');
}
}
$offer['insuranceHtml'] = $assurance_html;
$is_found = true;
$final_offer = $offer;
break;
}
$cot_cl->offers[$o]['code'] = $offer['operator']['code'] . '_' . $offer['service']['code'];
}
$all_offers = array();
$installed_srv = array();
$all_offers = $cot_cl->offers;
$services = Db::getInstance()->ExecuteS(
'SELECT *, CONCAT_WS("_", emc_operators_code_eo, code_es) AS offerCode FROM ' . _DB_PREFIX_ .
'emc_services'
);
foreach ($services as $service) {
$installed_srv[] = $service['offerCode'];
// add clean name for dropdown
foreach ($all_offers as $o => $offer) {
if (isset($offer['operator']['code'])
&& $service['emc_operators_code_eo'] == $offer['operator']['code']
&& isset($offer['service']['code'])
&& $service['code_es'] == $offer['service']['code']) {
$all_offers[$o]['label_es'] = $service['label_es'];
}
}
}
$errors = array();
if ($cot_cl->curl_error || $cot_cl->resp_error) {
if ($cot_cl->curl_error_text != '') {
$errors[] = $cot_cl->curl_error_text;
}
foreach ($cot_cl->resp_errors_list as $error) {
$errors[] = $error['message'];
}
}
unset($cookie->emc_order_data);
unset($cookie->emc_order_proforma);
unset($cookie->emc_delivery_contact);
return array(
'offer' => $final_offer,
'allOffers' => $all_offers,
'errors' => $errors,
'installedSrv' => $installed_srv,
'isFound' => (bool)$is_found,
'isProforma' => $is_proforma,
'proforma' => $proforma_data);
}
/**
* Make collect date. We can't collect on Sunday.
* @access public
* @var array $delays Delays array.
* @return String Collect date.
*/
public function setCollectDate($delays)
{
$today = strtotime('Today');
$time = strtotime(date('Y-m-d H:i'));
$time_split = strtotime(date('Y-m-d', $today) . ' ' . (int)$delays['split'] . ':00');
if ($time < $time_split) {
$days_delay = $delays['j1'];
} else {
$days_delay = $delays['j2'];
}
$result = strtotime('+' . $days_delay . 'days', $time);
if (date('N', $result) == 7) {
$result = strtotime('+1 day', $result);
}
return date('Y-m-d', $result);
}
/**
* Returns missed fields list.
* @param array $obligatory List with obligatory fields.
* @param array $values Values to check.
* @return array Empty array or with labels of missed fields.
*/
private function makeMissedList($obligatory, $values)
{
$missed = array();
$dictionnary = array(
'EMC_KEY_TEST' => $this->l('the test API key'),
'EMC_KEY_PROD' => $this->l('the production API key'),
'EMC_LOGIN' => $this->l('the EnvoiMoinsCher login'),
'EMC_PASS' => $this->l('the EnvoiMoinsCher password'),
'EMC_FNAME' => $this->l('the first name'),
'EMC_LNAME' => $this->l('the name'),
'EMC_COMPANY' => $this->l('the company'),
'EMC_ADDRESS' => $this->l('the address'),
'EMC_POSTALCODE' => $this->l('the postal code'),
'EMC_CITY' => $this->l('the town'),
'EMC_TEL' => $this->l('the phone number'),
'EMC_MAIL' => $this->l('the email address'),
'EMC_PICKUP_J1' => $this->l('the pickup day'));
foreach ($values as $k => $value) {
if (in_array($k, $obligatory) && trim($value) == '') {
$missed[] = $dictionnary[$k];
}
}
return $missed;
}
/**
* Returns false to not display carrier like a Prestashop carrier. These carriers are displayed by
* hookExtraCarrier method.
* @param array $ref List with cart data.
* @param float $shipping_cost Cost of shipping.
* @access public
* @return false
*/
public function getOrderShippingCost($ref, $shipping_cost)
{
return $this->getOrderShippingCostSubFunction($ref, $this->id_carrier);
}
/**
* Sub Function to getOrderShippingCost to be used from hookDisplayBeforeCarrier as well.
* Gets results from cache or api call and stores results in cache
* @param array $cart List with cart data.
* @param int $carrierId The carrier id.
* @access public
* @return rate or false if carrier shouldn't be displayed
*/
public function getOrderShippingCostSubFunction($cart, $carrierId)
{
// exit if module is offline or multishipping is enabled
if (EnvoimoinscherModel::getConfig('EMC_SRV_MODE') == EnvoimoinscherModel::MODE_CONFIG ||
(int) EnvoimoinscherModel::getConfig('PS_ALLOW_MULTISHIPPING') == 1) {
return false;
}
// if option disable cart 1 is enabled, we want an estimate until an address is set
if ($cart->id_address_delivery == 0 && (int)EnvoimoinscherModel::getConfig('EMC_DISABLE_CART') == 1) {
return $this->getPsRate($cart->id, $carrierId);
}
/* if option disable cart 2 is enabled, we want an estimate until carrier choice is done
* for 5-step checkout: we should need to check if id_carrier is set, and exclude carrier choice page (step 2)
* check on id_delivery_option needs to be done for 1st change of carrier
* for one-page-checkout: for controllers involved in carrier choice, we give an estimate until address is set
* for all other controllers, we give an estimate if address is not set or carrier choice is not done yet
*/
if ((int)EnvoimoinscherModel::getConfig('EMC_DISABLE_CART') == 2) {
$controller = $this->getContext()->controller;
$controllerClass = get_class($controller);
$carrierControllers = array(
"OrderOpcController",
"EnvoimoinscherAjaxModuleFrontController",
"PageNotFoundController"
);
if (((int)EnvoimoinscherModel::getConfig('PS_ORDER_PROCESS_TYPE') == 0 &&
Tools::getValue('step') != 2 && $cart->id_carrier == 0 && !Tools::isSubmit('id_delivery_option')) ||
((int)EnvoimoinscherModel::getConfig('PS_ORDER_PROCESS_TYPE') == 1 &&
((($cart->id_carrier == 0 || $cart->id_address_delivery == 0)
&& !in_array($controllerClass, $carrierControllers)) ||
($cart->id_address_delivery == 0 && in_array($controllerClass, $carrierControllers))))) {
return $this->getPsRate($cart->id, $carrierId);
}
}
// Get sender
$from = $this->model->getSender();
// Get recipient
$to = $this->model->getRecipient($cart->id, $cart->id_address_delivery);
/* if address is not set and EMC_DISABLE_CART is set to 0, the default address is used */
/* check on values is useful for sites which use an account validation through email */
if ((empty($to)
|| (isset($to['code_postal']) && $to['code_postal'] == "")
|| (isset($to['ville']) && $to['ville'] == "")
|| (isset($to['pays']) && Tools::strlen($to['pays']) != 2))
&& (int)EnvoimoinscherModel::getConfig('EMC_DISABLE_CART') == 0) {
$to = $this->model->getDefaultAddress();
}
// Get cart dimensions
$weight = $this->model->getCartWeight($cart->id);
$dimensions = $this->model->getDimensionsByWeight($weight);
$parcels = array(
1 => array(
'poids' => $weight,
'longueur' => isset($dimensions[0]['length_ed']) ? $dimensions[0]['length_ed'] : 0,
'largeur' => isset($dimensions[0]['width_ed']) ? $dimensions[0]['width_ed'] : 0,
'hauteur' => isset($dimensions[0]['height_ed']) ? $dimensions[0]['height_ed'] : 0
)
);
$params = array(
'collecte' => $this->setCollectDate(array(
'j1' => EnvoimoinscherModel::getConfig('EMC_PICKUP_J1'),
'j2' => EnvoimoinscherModel::getConfig('EMC_PICKUP_J2'),
'split' => EnvoimoinscherModel::getConfig('EMC_PICKUP_SPLIT'),
)),
'delai' => 'aucun',
'code_contenu' => EnvoimoinscherModel::getConfig('EMC_NATURE'),
'valeur' => $cart->getOrderTotal(true, Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING),
'module' => $this->ws_name,
'version' => $this->local_version,
'emc_type' => EnvoimoinscherModel::getConfig('EMC_TYPE')
);
$offers = $this->getQuote($from, $to, $parcels, $params, false, true);
// Store relay points and delivery date for display
$points = array();
$delivery_dates = array();
$helper = new EnvoimoinscherHelper;
if (count($offers) != 0) {
foreach ($offers as $offer) {
$tmpCarrierId = $this->model->getCarrierIdByCode($offer['service']['code'], $offer['operator']['code']);
if ($tmpCarrierId != 0) {
// Store relay points
if (isset($offer['mandatory']['retrait.pointrelais'])) {
$points[$tmpCarrierId] = implode(',', $offer['mandatory']['retrait.pointrelais']['array']);
}
// Store delivery date
if (isset($offer['delivery']['date'])) {
$delivery_dates[$tmpCarrierId] = $offer['delivery']['date'];
}
}
}
}
// put parcel points in cache
$pointCode = $helper->getPointCode($cart->id);
$this->model->setCache($pointCode, $points, 86400);
// put delivery dates in cache
$deliveryCode = $helper->getDeliveryDateCode($cart->id);
$this->model->setCache($deliveryCode, $delivery_dates, 86400);
// get cart rules (which use a code) if there is any
$cart_rules_in_cart = $helper->getCartRules($cart->id);
// cache offers override for a few seconds because PS calls this function for each carrier separately
$offerProcessedCode = $helper->getOfferProcessedCode($offers, $cart->id, $cart_rules_in_cart);
if (!$this->model->getCache($offerProcessedCode)) {
if (count($offers) != 0) {
// uncomment to see in logs why carriers don't show in front
// (fonction is useless here because PS excludes carriers beforehand)
// $offers = $this->psCarriersExclude($offers, $cart->id);
// convert price from euro to default currency if necessary
$defaultCurrency = new Currency(Currency::getDefaultCurrency()->id);
if ($defaultCurrency->iso_code != 'EUR') {
$euro = $this->model->getEuro();
foreach ($offers as $key => $offer) {
$convertedPrice = Tools::convertPrice($offer['price']['tax-exclusive'], $euro, false);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - converting price for carrier %1$s to %2$s: %3$s%2$s'),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$defaultCurrency->sign,
$convertedPrice
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
$offers[$key]['price']['tax-exclusive'] = $convertedPrice;
}
}
// apply rate price if needed
$offers = $this->applyRatePrice($offers, $cart->id);
// apply Prestashop price configuration
$offers = $this->psPriceOverride($offers, $cart->id);
// convert price from default currency to cart currency if necessary
$cartCurrency = new Currency($cart->id_currency);
if ($cartCurrency->iso_code != $defaultCurrency->iso_code) {
foreach ($offers as $key => $offer) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - converting price for carrier %1$s to %2$s: %3$s%2$s'),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$cartCurrency->sign,
Tools::convertPrice($offer['price']['tax-exclusive'], $cartCurrency, true)
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
$offers[$key]['price']['tax-exclusive'] = Tools::convertPrice(
$offer['price']['tax-exclusive'],
$cartCurrency,
true
);
}
}
$offers = $this->model->makeCarrierIdKeys($offers);
}
$this->model->setCache($offerProcessedCode, $offers, 30);
} else {
$offers = $this->model->getCache($offerProcessedCode);
}
if (isset($offers[$carrierId])) {
$return = $offers[$carrierId]['price']['tax-exclusive'];
} else {
$return = false;
}
return $return;
}
public function getPackageShippingCost($r, $s, $products = null)
{
return $this->getOrderShippingCost($r, 322);
}
/**
* Returns false to not display carrier like a Prestashop carrier. These carriers are displayed by
* hookExtraCarrier method.
* @param array $ref List with cart data.
* @param float $shipping_cost Cost of shipping.
* @access public
* @return false
*/
public function getOrderShippingCostExternal($ref)
{
return $this->getOrderShippingCost($ref, 322);
}
/**
* Get rates as defined by carrier ranges for quotation bypass if EMC_DISABLE_CART is on.
* @param int $cartId the cart id.
* @param int $id_carrier The carrier id.
* @access public
* @return false or float
*/
public function getPsRate($cartId, $id_carrier)
{
$cart = new Cart($cartId);
// check carrier is active for France
$zoneId = Db::getInstance()->ExecuteS('SELECT id_zone FROM ' . _DB_PREFIX_ . 'country WHERE iso_code = "FR"');
$zoneId = $zoneId[0]['id_zone'];
$carriers_zone = $this->model->getEmcCarriersByZone($zoneId, $cart->id_lang);
$is_available = false;
foreach ($carriers_zone as $carrier) {
if ($carrier['id_carrier'] = $id_carrier) {
$is_available = true;
}
}
if (!$is_available) {
return false;
}
$weight = $this->model->getCartWeightRaw($cartId);
$rate = 0;
$carrier = new Carrier($id_carrier);
$is_weight_method =
$carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT ? true : false;
if ($is_weight_method) {
if (Carrier::checkDeliveryPriceByWeight(
$id_carrier,
$weight,
$zoneId
)) {
$rate = $carrier->getDeliveryPriceByWeight(
$weight,
$zoneId
);
}
} else {
if (Carrier::checkDeliveryPriceByPrice(
$id_carrier,
$cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING),
$zoneId,
$cart->id_currency
)
) {
$rate = $carrier->getDeliveryPriceByPrice(
$cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING),
$zoneId
);
}
}
// check if there are additional costs (configured on products, calculated in cart)
$additionalCost = 0;
foreach ($cart->getProducts() as $product) {
$additionalCost += $product['additional_shipping_cost'];
}
$rate += $additionalCost;
// Handling cost
if ($carrier->shipping_handling) {
$shipping_handling = (float)EnvoimoinscherModel::getConfig('PS_SHIPPING_HANDLING');
$rate += $shipping_handling;
}
return $rate;
}
/**
* Adds PS configuration additional costs to offers.
* @param array $offers offers returned by API.
* @returns array $offers with prices override.
*/
private function psPriceOverride($offers, $cartId)
{
$cart = new Cart($cartId);
$defaultCurrency = new Currency(Currency::getDefaultCurrency()->id);
$configuration = EnvoimoinscherModel::getConfigMultiple(array(
'PS_SHIPPING_HANDLING',
'EMC_ENABLED_LOGS'
));
// check if there are additional costs (configured on products, calculated in cart)
$additionalCost = 0;
foreach ($cart->getProducts() as $product) {
$additionalCost += $product['additional_shipping_cost'] * $product['cart_quantity'];
}
foreach ($offers as $key => $offer) {
$carrierId = $this->model->getCarrierIdByCode($offer['service']['code'], $offer['operator']['code']);
// add additional costs
if ($additionalCost != 0) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - adding to carrier %1$s additional shipping fees %2$s%3$s'),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$additionalCost,
$defaultCurrency->sign
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
$offers[$key]['price']['tax-exclusive'] += $additionalCost;
}
// add shipping handling costs
$carrier = new Carrier($carrierId);
if (isset($configuration['PS_SHIPPING_HANDLING']) && $carrier->shipping_handling
&& $configuration['PS_SHIPPING_HANDLING'] > 0) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - adding to carrier %1$s handling charges %2$s%3$s'),
$offer['operator']['code'] . '_' .$offer['service']['code'],
(float)$configuration['PS_SHIPPING_HANDLING'],
$defaultCurrency->sign
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
$offers[$key]['price']['tax-exclusive'] += (float)$configuration['PS_SHIPPING_HANDLING'];
}
}
return $offers;
}
/**
* Set carriers free according to Prestashop configuration.
* @param array $offers offers returned by API.
* @returns array $offers with prices override.
*/
private function applyFree($offers, $cartId)
{
$cart = new Cart($cartId);
$configuration = EnvoimoinscherModel::getConfigMultiple(array(
'PS_SHIPPING_FREE_PRICE',
'PS_SHIPPING_FREE_WEIGHT',
'EMC_ENABLED_LOGS'
));
$helper = new EnvoimoinscherHelper;
// get carriers set free because of cart rules
// code taken from Prestashop Cart.php class. May differ depending on PS version...
$cart_rules = CartRule::getCustomerCartRules($cart->id_lang, $cart->id_customer, true, true, false, $cart);
$cart_rules_in_cart = $helper->getCartRules($cart->id);
$total_products_wt = $cart->getOrderTotal(true, Cart::ONLY_PRODUCTS);
$total_products = $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
$free_carriers_rules = array();
foreach ($cart_rules as $cart_rule) {
$total_price = $cart_rule['minimum_amount_tax'] ? $total_products_wt : $total_products;
// if cart rule is "Shipping included", exit function
if ($cart_rule['minimum_amount_shipping']) {
// if cart rule involves making shipping free, send warning in logs
if ($cart_rule['free_shipping']) {
$message = sprintf(
$this->l(
'Cart rules must be set to Shipping excluded in order to work properly. '.
'Check cart rule %1$s'
),
$cart_rule['id_cart_rule']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 4);
}
continue;
}
if ($cart_rule['free_shipping'] && $cart_rule['carrier_restriction']
&& $cart_rule['minimum_amount'] <= $total_price &&
(in_array((int)$cart_rule['id_cart_rule'], $cart_rules_in_cart) || $cart_rule['code'] == "")) {
$cr = new CartRule((int)$cart_rule['id_cart_rule']);
$context = Context::getContext();
if (!$context->cart) {
$context = $context->cloneContext();
$context->cart = $cart;
}
// for the simulator we need to add a default carrier in cart
if (!$context->cart->id_carrier) {
$firstCarrier = current($offers);
$context->cart->id_carrier = $this->model->getCarrierIdByCode(
$firstCarrier['service']['code'],
$firstCarrier['operator']['code']
);
}
if (Validate::isLoadedObject($cr) && $cr->checkValidity(
$context,
in_array((int)$cart_rule['id_cart_rule'], $cart_rules_in_cart),
false,
false
)) {
$carriers = $cr->getAssociatedRestrictions('carrier', true, false);
if (is_array($carriers) && count($carriers) && isset($carriers['selected'])) {
foreach ($carriers['selected'] as $carrier) {
if (isset($carrier['id_carrier']) && $carrier['id_carrier']) {
$free_carriers_rules[] = array('id_carrier' => (int)$carrier['id_carrier'],
'id_cart_rule' => $cart_rule['id_cart_rule']
);
}
}
}
}
} elseif ($cart_rule['free_shipping'] && $cart_rule['minimum_amount'] <= $total_price
&& (in_array((int)$cart_rule['id_cart_rule'], $cart_rules_in_cart) || $cart_rule['code'] == "")) {
// in case no carrier has been selected, all must be set free
foreach ($offers as $key => $offer) {
$carrierId = $this->model->getCarrierIdByCode(
$offer['service']['code'],
$offer['operator']['code']
);
$free_carriers_rules[] = array(
'id_carrier' => (int)$carrierId,
'id_cart_rule' => $cart_rule['id_cart_rule']
);
}
}
}
foreach ($offers as $key => $offer) {
$carrierId = $this->model->getCarrierIdByCode($offer['service']['code'], $offer['operator']['code']);
$carrier = new Carrier($carrierId);
// check if carrier is set free
if (isset($carrier->is_free) && $carrier->is_free) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - carrier %1$s is configured as a free carrier'),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
$offers[$key]['price']['tax-exclusive'] = 0;
}
// check if carrier is free because of cart rules
foreach ($free_carriers_rules as $free_carriers_rule) {
if (array_search($carrierId, $free_carriers_rule) !== false) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - carrier %1$s is set free by cart rule %2$s'),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$free_carriers_rule['id_cart_rule']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
$offers[$key]['price']['tax-exclusive'] = 0;
}
}
}
// check if free because of cart price
$free_fees_price = 0;
if (isset($configuration['PS_SHIPPING_FREE_PRICE'])) {
$free_fees_price = (float)$configuration['PS_SHIPPING_FREE_PRICE'];
}
if ($cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING) >= (float)$free_fees_price
&& (float)$free_fees_price > 0) {
if ((int)$configuration['EMC_ENABLED_LOGS'] == 1) {
$message = $this->l('Quotation - all carriers free because of cart price');
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
foreach ($offers as $key => $offer) {
$offers[$key]['price']['tax-exclusive'] = 0;
}
return $offers;
}
// check if free because of cart weight
if (isset($configuration['PS_SHIPPING_FREE_WEIGHT'])) {
$weight = $this->model->getCartWeightRaw($cartId);
if ($weight >= (float)$configuration['PS_SHIPPING_FREE_WEIGHT'] &&
(float)$configuration['PS_SHIPPING_FREE_WEIGHT'] > 0) {
if ((int)$configuration['EMC_ENABLED_LOGS'] == 1) {
$message = $this->l('Quotation - all carriers free because of cart weight');
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
foreach ($offers as $key => $offer) {
$offers[$key]['price']['tax-exclusive'] = 0;
}
return $offers;
}
}
return $offers;
}
/**
* Apply rate price if needed.
* @param array $offers offers returned by API.
* @returns array $offers with prices override.
*/
private function applyRatePrice($offers, $cartId)
{
$cart = new Cart($cartId);
$recipient = $this->model->getRecipient($cartId, $cart->id_address_delivery);
if (empty($recipient)) {
$recipient = $this->model->getDefaultAddress();
}
// get zone id for country
$zoneId = Db::getInstance()->ExecuteS(
'SELECT id_zone FROM ' . _DB_PREFIX_ . 'country WHERE iso_code = "'.pSQL($recipient['pays']).'"'
);
if (isset($zoneId[0]['id_zone'])) {
$zoneId = $zoneId[0]['id_zone'];
} else {
$zoneId = 0;
}
$weight = $this->model->getCartWeightRaw($cartId);
foreach ($offers as $key => $offer) {
$carrierId = $this->model->getCarrierIdByCode($offer['service']['code'], $offer['operator']['code']);
switch ($this->model->isRatePrice($carrierId)) {
case 0:
break;
case 1:
$carrier = new Carrier($carrierId);
if (Carrier::checkDeliveryPriceByWeight(
$carrierId,
$weight,
$zoneId
)
) {
$offers[$key]['price']['tax-exclusive'] = (float)$carrier->getDeliveryPriceByWeight(
$weight,
$zoneId
);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - price range applied to %1$s'),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
}
break;
case 2:
$carrier = new Carrier($carrierId);
if (Carrier::checkDeliveryPriceByPrice(
$carrierId,
$cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING),
$zoneId,
$cart->id_currency
)) {
$offers[$key]['price']['tax-exclusive'] = (float)$carrier->getDeliveryPriceByPrice(
$cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING),
$zoneId
);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - price range applied to %1$s'),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
}
break;
}
}
return $offers;
}
/**
* Excludes carriers if they aren't in PS configured ranges/zones. Used in tests().
* @param array $offers offers array.
* @param object $cartId cart id.
* @returns boolean. Returns true if the carrier needs to be excluded, false if not.
*/
private function psCarriersExclude($offers, $cartId)
{
$cart = new Cart($cartId);
$recipient = $this->model->getRecipient($cartId, $cart->id_address_delivery);
$helper = new EnvoimoinscherHelper;
// get zone id for country
$zoneId = Db::getInstance()->ExecuteS(
'SELECT id_zone FROM ' . _DB_PREFIX_ . 'country WHERE iso_code = "'.pSQL($recipient['pays']).'"'
);
if (isset($zoneId[0]['id_zone'])) {
$zoneId = $zoneId[0]['id_zone'];
} else {
$zoneId = 0;
}
// available carriers for this zone
$carriersZone = $helper->makeCodeKeys($this->model->getEmcCarriersByZone($zoneId, $cart->id_lang));
// exclude carriers from offers if they are not active for this zone
$weight = $this->model->getCartWeightRaw($cartId);
foreach ($offers as $key => $offer) {
// because is not active in this zone
if (!isset($carriersZone[$offer['operator']['code'] . '_' . $offer['service']['code']])) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - carrier %1$s not active for this zone'),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
$carrierId = $this->model->getCarrierIdByCode($offer['service']['code'], $offer['operator']['code']);
$carrier = new Carrier($carrierId);
if ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT) {
// because weight is out of range
if (!Carrier::checkDeliveryPriceByWeight(
$carrierId,
$weight,
$zoneId
)) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - %1$s is removed because of price range configuration'),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
} else {
// because price is out of range
if (!Carrier::checkDeliveryPriceByPrice(
$carrierId,
$cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING),
$zoneId,
$cart->id_currency
)) {
$offers[$key]['price']['tax-exclusive'] = $carrier->getDeliveryPriceByPrice(
$cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING),
$zoneId
);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - %1$s is removed because of price range configuration'),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
}
}
// Get cart dimensions
$shop = Context::getContext()->shop;
foreach ($offers as $key => $offer) {
$carrierId = $this->model->getCarrierIdByCode($offer['service']['code'], $offer['operator']['code']);
$carrier = new Carrier($carrierId);
// Product attributes at this time (PS 1.6.0.9) are not taken into account by PS
foreach ($cart->getProducts() as $product) {
// check weight
if ((float)$carrier->max_weight > 0 && (float)$carrier->max_weight < (float)$product['weight']) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l(
'Quotation - carrier %1$s is removed because product %2$s '
.'is over its configured max weight'
),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$product['id_product']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
// check width
if ((float)$carrier->max_width > 0 && (float)$carrier->max_width < (float)$product['width']) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l(
'Quotation - carrier %1$s is removed because product %2$s '
.'is over its configured max width'
),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$product['id_product']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
// check length
if ((float)$carrier->max_depth > 0 && (float)$carrier->max_depth < (float)$product['depth']) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l(
'Quotation - carrier %1$s is removed because product %2$s '
.'is over its configured max depth'
),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$product['id_product']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
// check height
if ((float)$carrier->max_height > 0 && (float)$carrier->max_height < (float)$product['height']) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l(
'Quotation - carrier %1$s is removed because product %2$s '
.'is over its configured max height'
),
$offer['operator']['code'] . '_' .$offer['service']['code'],
$product['id_product']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
// exclude because of product configuration
$cacheKey = 'carrier_list_by_product'.(int)$product['id_product'].'-'.(int)$shop->id;
if (!$this->model->getCache($cacheKey)) {
$productCarriers = Db::getInstance()->executeS(
'SELECT c.id_carrier FROM ' . _DB_PREFIX_ . 'product_carrier pc
JOIN ' . _DB_PREFIX_ . 'carrier c
ON c.id_reference = pc.id_carrier_reference AND c.deleted = 0
WHERE pc.id_product = '.(int)$product['id_product'].'
AND pc.id_shop = '.(int)$shop->id
);
$this->model->setCache($cacheKey, $productCarriers, 30);
}
$productCarriers = $this->model->getCache($cacheKey);
$availableCarriers = $helper->getProductCarrierIds($productCarriers);
if ($availableCarriers) {
$carrierId = $this->model->getCarrierIdByCode(
$offer['service']['code'],
$offer['operator']['code']
);
if (array_search($carrierId, $availableCarriers) === false) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l(
'Quotation - carrier %1$s is removed because at least one product '
.'has it deactivated'
),
$offer['operator']['code'] . '_' .$offer['service']['code']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
unset($offers[$key]);
}
}
}
}
// TO DO exclude because of stock management
return $offers;
}
/**
* Checks user credentials.
* @param array $data List of parameters.
* @return int 1 if the credentials are valid, 0 if not.
*/
private function checkCredentials($data)
{
// always check the credentials and notify user if they aren't valid
$options = array(
CURLOPT_URL => $this->environments[$data['apiEnv']]['link'] . '/verifier_utilisateur.html',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(array(
'login' => $data['apiLogin'],
'key' => $data['apiKey'],
'store' => $_SERVER['HTTP_HOST'],
'platform' => 'Prestashop',
'tested' => date('Y-m-d H:i:s'))),
CURLOPT_RETURNTRANSFER => 1
);
$options[CURLOPT_SSL_VERIFYPEER] = false;
$options[CURLOPT_SSL_VERIFYHOST] = 0;
$req = curl_init();
curl_setopt_array($req, $options);
$result = curl_exec($req);
curl_close($req);
$return = 1;
// api connection problem was detected (wrong credentials)
if (trim($result) != 1) {
$return = 0;
}
return $return;
}
/**
* Load all available carriers
*/
public function loadAllCarriers($ajax = true)
{
$result = array();
// on verifie qu'on est bien en mode de configuration
if (EnvoimoinscherModel::getConfig('EMC_SRV_MODE') != EnvoimoinscherModel::MODE_CONFIG) {
if ($ajax) {
echo $this->l('Your module must be in offline mode.');
die();
} else {
return false;
}
}
// on recupere les services present
$bd = Db::getInstance();
$sql_srv = 'SELECT * FROM ' . _DB_PREFIX_ . 'emc_services';
$sql_ope = 'SELECT * FROM ' . _DB_PREFIX_ . 'emc_operators';
$services = $bd->ExecuteS($sql_srv);
$operators = $bd->ExecuteS($sql_ope);
// on recupere les services depuis le serveur envoimoinscher
require_once('Env/WebService.php');
require_once('Env/CarriersList.php');
$login = EnvoimoinscherModel::getConfig('EMC_LOGIN');
$pass = EnvoimoinscherModel::getConfig('EMC_PASS');
$env = EnvoimoinscherModel::getConfig('EMC_ENV');
$key = EnvoimoinscherModel::getConfig('EMC_KEY_' . $env);
$lib = new EnvCarriersList(array('user' => $login, 'pass' => $pass, 'key' => $key));
$lib->setPlatformParams($this->ws_name, _PS_VERSION_, $this->version);
$lib->setEnv(Tools::strtolower($env));
$lib->setLocale('fr-fr'); // always check in french to keep label_es as is
$lib->getCarriersList($this->ws_name, $this->version);
if ($lib->curl_error) {
if ($ajax) {
echo $this->l('Error while updating your offers : ');
foreach ($lib->resp_errors_list as $message) {
echo ' ' . $message['message'];
}
die();
} else {
return false;
}
} elseif ($lib->resp_error) {
if ($ajax) {
echo $this->l('Error while updating your offers : ');
foreach ($lib->resp_errors_list as $message) {
echo ' ' . $message['message'];
}
die();
} else {
return false;
}
}
$ope_no_change = array();
$ope_to_delete = array();
$ope_to_update = array();
$ope_to_insert = array();
$srv_no_change = array();
$srv_to_delete = array();
$srv_to_update = array();
$srv_to_insert = array();
$op_found = -1;
$srv_found = -1;
// on tri les transporteurs a rajouter, supprimer, modifier et ceux restant identique
$last_ope_seen = ''; // on evite les doublons
foreach ($lib->carriers as $carrier) {
// modify language codes to match Prestashop conf ('fr_FR' => 'fr-fr')
if (isset($carrier['translations'])) {
foreach ($carrier['translations'] as $translated_field => $translations) {
foreach ($translations as $lang_code => $text) {
$carrier['translations'][$translated_field][Tools::strtolower(
str_replace('_', '-', $lang_code)
)] = $text;
unset($carrier['translations'][$translated_field][$lang_code]);
}
}
}
// operateur trouve, on regarde s'il est different
if ($last_ope_seen != $carrier['ope_code']) {
$last_ope_seen = $carrier['ope_code'];
// on compare l'operateur avec celui de la liste
$op_found = -1;
foreach ($operators as $id => $operator) {
if ($operator['code_eo'] == $carrier['ope_code']) {
$op_found = $id;
if ($operator['name_eo'] != $carrier['ope_name']) {
$ope_to_update[count($ope_to_update)] = $carrier;
} else {
$ope_no_change[count($ope_no_change)] = $carrier;
}
break;
}
}
if ($op_found == -1) {
$ope_to_insert[count($ope_to_insert)] = $carrier;
} else {
unset($operators[$op_found]);
}
}
// on compare le service avec celui de la liste
$srv_found = -1;
foreach ($services as $id => $service) {
if ($service['emc_operators_code_eo'] == $carrier['ope_code']
&& $service['code_es'] == $carrier['srv_code']) {
$srv_found = $id;
// service trouve, on regarde s'il est different
if ($service['label_es'] != $carrier['old_srv_name'] ||
$service['desc_store_es'] != serialize($carrier['translations']['description']) ||
$service['label_store_es'] != serialize($carrier['translations']['srv_name_bo']) ||
$service['srv_name_fo_es'] != serialize($carrier['translations']['srv_name_fo']) ||
$service['family_es'] != $carrier['family'] ||
$service['zone_fr_es'] != $carrier['zone_fr'] ||
$service['zone_eu_es'] != $carrier['zone_eu'] ||
$service['zone_int_es'] != $carrier['zone_int'] ||
$service['zone_restriction_es'] != serialize($carrier['translations']['zone_restriction']) ||
$service['details_es'] != serialize($carrier['translations']['details']) ||
$service['delivery_due_time_es'] != serialize($carrier['translations']['delivery_due_time']) ||
$service['delivery_type_es'] != $carrier['delivery_type'] ||
$service['is_parcel_pickup_point_es'] != $carrier['parcel_pickup_point'] ||
$service['is_parcel_dropoff_point_es'] != $carrier['parcel_dropoff_point'] ||
$service['pickup_place_es'] != serialize($carrier['translations']['pickup_place']) ||
$service['dropoff_place_es'] != serialize($carrier['translations']['dropoff_place'])
) {
$srv_to_update[] = $carrier;
} else {
$srv_no_change[] = $carrier;
}
break;
}
}
if ($srv_found == -1) {
$srv_to_insert[] = $carrier;
} else {
unset($services[$srv_found]);
}
}
$srv_to_delete = $services;
$ope_to_delete = $operators;
// On met à jour la base
// Requête insert services
$query = array();
$sql = '';
$first_line = true;
if (count($srv_to_insert) > 0) {
$sql = 'INSERT INTO ' . _DB_PREFIX_ . 'emc_services VALUES';
foreach ($srv_to_insert as $service) {
if (!$first_line) {
$sql .= ',';
}
$first_line = false;
$sql .= '(null,0,0,"' . pSQL($service['srv_code']) .
'","' . pSQL($service['ope_code']) .
'","' . pSQL($service['old_srv_name']) .
'","' . pSQL(serialize($service['translations']['description'])) .
'","' . pSQL(serialize($service['translations']['srv_name_bo'])) .
'","' . pSQL(serialize($service['translations']['srv_name_fo'])) .
'",' . (int)$service['family'] .
',' . (int)$service['zone_fr'] .
',' . (int)$service['zone_eu'] .
',' . (int)$service['zone_int'] .
',"' . pSQL(serialize($service['translations']['zone_restriction'])) .
'","' . pSQL(serialize($service['translations']['details'])) .
'","' . pSQL(serialize($service['translations']['delivery_due_time'])) .
'",' . (int)$service['delivery_type'] .
',' . (int)$service['parcel_pickup_point'] .
',' . (int)$service['parcel_dropoff_point'] .
',"' . pSQL(serialize($service['translations']['pickup_place'])) .
'","' . pSQL(serialize($service['translations']['dropoff_place'])) .
'",1)';
}
$sql .= ';';
$query[] = $sql;
}
// Requête insert opeateurs
if (count($ope_to_insert) > 0) {
$sql = 'INSERT INTO ' . _DB_PREFIX_ . 'emc_operators VALUES';
$first_line = true;
foreach ($ope_to_insert as $operator) {
if (!$first_line) {
$sql .= ',';
}
$first_line = false;
$sql .= '(null,"' . pSQL($operator['ope_name']) . '","' . pSQL($operator['ope_code']) . '")';
}
$sql .= ';';
$query[] = $sql;
}
// Requête update services
foreach ($srv_to_update as $service) {
$sql = 'UPDATE ' . _DB_PREFIX_ . 'emc_services SET
label_es = "' . pSQL($service['old_srv_name']) . '"
,desc_store_es = "' . pSQL(serialize($service['translations']['description'])) . '"
,label_store_es = "' . pSQL(serialize($service['translations']['srv_name_bo'])) . '"
,srv_name_fo_es = "' . pSQL(serialize($service['translations']['srv_name_fo'])) . '"
,family_es = ' . (int)$service['family'] . '
,zone_fr_es = ' . (int)$service['zone_fr'] . '
,zone_eu_es = ' . (int)$service['zone_eu'] . '
,zone_int_es = ' . (int)$service['zone_int'] . '
,zone_restriction_es = "' . pSQL(serialize($service['translations']['zone_restriction'])) . '"
,details_es = "' . pSQL(serialize($service['translations']['details'])) . '"
,delivery_due_time_es = "' . pSQL(serialize($service['translations']['delivery_due_time'])) . '"
,delivery_type_es = ' . (int)$service['delivery_type'] . '
,is_parcel_pickup_point_es = ' . (int)$service['parcel_pickup_point'] . '
,is_parcel_dropoff_point_es = ' . (int)$service['parcel_dropoff_point'] . '
,pickup_place_es = "' . pSQL(serialize($service['translations']['pickup_place'])) . '"
,dropoff_place_es = "' . pSQL(serialize($service['translations']['dropoff_place'])) . '"
WHERE code_es = "' . pSQL($service['srv_code']) . '"
AND emc_operators_code_eo = "' . pSQL($service['ope_code']) . '";';
$query[] = $sql;
}
// Requête update operateurs
foreach ($ope_to_update as $operator) {
$sql = 'UPDATE ' . _DB_PREFIX_ . 'emc_operators SET
name_eo = "' . pSQL($operator['ope_name']) . '" WHERE code_eo = "' . pSQL($operator['ope_code']) . '";';
$query[] = $sql;
}
// Requête delete services
if (count($srv_to_delete) > 0) {
$sql = 'UPDATE ' . _DB_PREFIX_ . 'carrier SET deleted = 1 WHERE ';
$first_line = true;
foreach ($srv_to_delete as $service) {
if (!$first_line) {
$sql .= ' OR ';
}
$first_line = false;
$sql .= 'id_carrier = ' . (int)$service['id_carrier'];
}
$sql .= ';';
$query[] = $sql;
$sql = 'DELETE FROM ' . _DB_PREFIX_ . 'emc_services WHERE ';
$first_line = true;
foreach ($srv_to_delete as $service) {
if (!$first_line) {
$sql .= ' OR ';
}
$first_line = false;
$sql .= 'id_es = ' . (int)$service['id_es'];
}
$sql .= ';';
$query[] = $sql;
}
// Requête delete operateurs
$first_line = true;
if (count($ope_to_delete) > 0) {
$sql = 'DELETE FROM ' . _DB_PREFIX_ . 'emc_operators WHERE ';
foreach ($ope_to_delete as $operator) {
if (!$first_line) {
$sql .= ' OR ';
}
$first_line = false;
$sql .= 'id_eo = ' . (int)$operator['id_eo'];
}
$sql .= ';';
$query[] = $sql;
}
Db::getInstance()->execute('START TRANSACTION;');
foreach ($query as $q) {
if ($q != '' && Db::getInstance()->execute($q) === false) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
Logger::addLog(
'['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' .
$this->l('Update : Error while updating your offers : ') . $q
);
}
if ($ajax) {
Db::getInstance()->execute('ROLLBACK;');
echo $this->l('Error while updating your offers : ') . $q;
die();
} else {
return false;
}
}
}
Db::getInstance()->execute('COMMIT;');
$result = array();
$result['offers_added'] = array();
$result['offers_updated'] = array();
$result['offers_deleted'] = array();
foreach ($srv_to_insert as $service) {
$result['offers_added'][count($result['offers_added'])] = $service['old_srv_name'];
}
foreach ($srv_to_update as $service) {
$result['offers_updated'][count($result['offers_updated'])] = $service['old_srv_name'];
}
foreach ($srv_to_delete as $service) {
$result['offers_deleted'][count($result['offers_deleted'])] = $service['label_es'];
}
$date = new DateTime();
EnvoimoinscherModel::updateConfig('EMC_LAST_CARRIER_UPDATE', $date->format('Y-m-d'));
// let's update categories while we're at it
$this->model->updateCategories();
if ($ajax) {
echo Tools::jsonEncode($result);
die();
} else {
return true;
}
}
/**
* Convert a date into string in the selected language
* @param $date : date to convert
* @param $dateTranslation : array of translation
* @return the date in string format
*/
public function dateToString($date)
{
$date_data = explode('/', strftime('%w/%d/%m/%Y', strtotime($date)));
return $this->l('day' . $date_data[0]) . ' ' . $date_data[1] . ' ' .
$this->l('month' . $date_data[2]) . ' ' . $date_data[3];
}
/**
* Show parcel point informations on backoffice.
* @access public
* @param array $params List of params.
* @return mixed Displayed template or nothing.
*/
public function hookAdminOrder($params)
{
$smarty = $this->getContext()->smarty;
require_once(_PS_MODULE_DIR_ . '/envoimoinscher/includes/EnvoimoinscherHelper.php');
$helper = new EnvoimoinscherHelper;
// check if order belongs to module and if the carrier handles parcel points
$point = $this->model->getPointInfos($params['id_order']);
if (isset($point['code'])) {
$smarty->assign('point', $point);
$smarty->assign('schedule', $helper->setSchedule($point['schedule']));
}
$smarty->assign('multiParcels', ($parcels = $this->model->getParcelsInfos($params['id_order'])));
$smarty->assign('multiSize', count($parcels));
return $this->display(__FILE__, '/views/templates/hook/hookAdminOrder.tpl');
}
/**
* Handle carrier choice. If the carrier must have a parcel point, put the point in the session.
* If the point wasn't specified, returns a error. It's called only for standard order mode.
* @access public
* @param array $params List of order params.
* @param bool $redirect Redirect boolean.
* @return void
*/
public function hookProcessCarrier($params, $redirect = true)
{
$cookie = $this->getContext()->cookie;
/*$price = 0.0;
if ($redirect || !$redirect) {
$price = 0.0;
}*/
$cartId = (int)$params['cart']->id;
$error_occured = false;
$correct_code = true;
$options = unserialize($params['cart']->delivery_option);
foreach ($options as $o => $option) {
$ope = $this->model->getCartCarrier($cartId, (int)str_replace(',', '', $option));
if (isset($ope) && count($ope) > 0) {
if ($ope[0]['selected_point']) {
$codes = explode('-', $ope[0]['selected_point']);
if ((!isset($codes[0]) || !isset($codes[1])) ||
(isset($codes[0]) && isset($codes[1]) && (trim($codes[0]) != $ope[0]['emc_operators_code_eo']
|| !ctype_alnum(trim($codes[1]))))
) {
$correct_code = false;
}
}
if (isset($ope[0]) && $ope[0]['is_parcel_pickup_point_es'] == 1 &&
!$correct_code && Tools::getValue('ajax') != 'true' &&
Tools::getValue('ajax') != 'true'
) {
$error_occured = true;
$error_message =
sprintf($this->l('The mandatory parcel point has not been chosen for the cart %s'), $cartId);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $error_message, 4);
}
$variable = 'choosePoint' . $ope[0]['emc_operators_code_eo'] . $o;
$cookie->$variable = 1;
}
/*$prices = Tools::jsonDecode($ope[0]['prices_eap'], true);
if (isset($prices[$o]) && isset($prices[$o][$ope[0]['id_carrier']])) {
$price = $price + $prices[$o][$ope[0]['id_carrier']];
}*/
}
}
if ($error_occured) {
Tools::redirect('order.php?step=2');
return false;
}
/*Db::getInstance()->autoExecute(
_DB_PREFIX_ . 'emc_api_pricing',
array('price_eap' => (float)$price),
'UPDATE',
_DB_PREFIX_ . 'cart_id_cart = ' . (int)$cartId . ' '
);*/
return true;
}
/**
* Page of order confirmation. If the shipper choosen by user has a parcel point, we need to
* insert it into emc_points table.
* @access public
* @param $params array List of order params.
* @return void
*/
public function hooknewOrder($params)
{
$cookie = $this->getContext()->cookie;
$helper = new EnvoimoinscherHelper;
$cookie->emc_carrier = '';
// Get cart carrier (if EnvoiMoinsCher, make some additional operations)
$row = $this->model->getCartCarrierByCart($params['cart']->id);
// if it's not our carrier, nothing to do here
if ($row[0]['external_module_name'] !== $this->name) {
return;
}
$cookie = $this->getContext()->cookie;
$cookie->emc_carrier = '';
if ($row[0]['selected_point']) {
// Insert parcel point informations
$point = explode('-', $row[0]['selected_point']);
if (ctype_alnum(trim($point[0])) && ctype_alnum(trim($point[1]))
&& strpos(trim($point[0]), $row[0]['emc_operators_code_eo']) !== false) {
$data = array(
_DB_PREFIX_ . 'orders_id_order' => (int)$params['order']->id,
'point_ep' => pSQL(trim($point[1])),
'emc_operators_code_eo' => pSQL(trim($point[0]))
);
Db::getInstance()->autoExecute(_DB_PREFIX_ . 'emc_points', $data, 'INSERT');
}
}
// deleted tmp data from cache
$pointCode = $helper->getPointCode($params['cart']->id);
$this->model->deleteFromCache($pointCode);
$deliveryCode = $helper->getDeliveryDateCode($params['cart']->id);
$this->model->deleteFromCache($deliveryCode);
// delete expired values from cache
$this->model->deleteExpiredFromCache();
return true;
}
/**
* Handles tracking informations.
* @param array $params List of params.
* @return void
*/
public function hookOrderDetail($params)
{
$smarty = $this->getContext()->smarty;
$cookie = $this->getContext()->cookie;
require_once(_PS_MODULE_DIR_ . '/envoimoinscher/includes/EnvoimoinscherHelper.php');
$helper = new EnvoimoinscherHelper;
// get tracking informations
$rows = $this->model->getTrackingByOrderAndCustomer(Tools::getValue('id_order'), $cookie->id_customer);
$smarty->assign('rows', $rows);
$smarty->assign('isAdmin', false);
$point = $this->model->getPointInfos(Tools::getValue('id_order'));
$is_point = 0;
if (is_array($params)) {
$is_point = 0;
}
if (isset($point['code'])) {
$is_point = 1;
$smarty->assign('point', $point);
$smarty->assign('schedule', $helper->setSchedule($point['schedule']));
}
$smarty->assign('showPoint', $is_point);
echo $this->display(__FILE__, '/views/templates/admin/tracking.tpl');
}
/**
* When an EnvoiMoinsCher carrier is updated, call this method.
* It inserts a new relation between the carrier of Prestashop and the service of
* EnvoiMoinsCher.
* @param array $params List of params used in the operation.
* @return void
*/
public function hookupdateCarrier($params)
{
// if it's not our carrier, nothing to do here
if ($params['carrier']->external_module_name !== $this->name) {
return;
}
$data = array('id_carrier' => (int)$params['carrier']->id);
Db::getInstance()->autoExecute(
_DB_PREFIX_ . 'emc_services',
$data,
'UPDATE',
'ref_carrier = ' . (int)$params['carrier']->id_reference
);
}
/**
* Header's hook. It displays included JavaScript for GoogleMaps API.
* @access public
* @return Displayed Smarty template.
*/
public function hookHeader()
{
$smarty = $this->getContext()->smarty;
$controller = $this->getContext()->controller;
$smarty->assign('emcBaseDir', _MODULE_DIR_ . '/envoimoinscher/');
$controllerClass = get_class($controller);
$carrierControllers = array(
"OrderOpcController",
"EnvoimoinscherAjaxModuleFrontController",
);
if (((int)EnvoimoinscherModel::getConfig('PS_ORDER_PROCESS_TYPE') == 0 && Tools::getValue('step') == 1) ||
((int)EnvoimoinscherModel::getConfig('PS_ORDER_PROCESS_TYPE') == 1 &&
in_array($controllerClass, $carrierControllers))) {
$smarty->assign('loaderSrc', __PS_BASE_URI__ . 'img/loader.gif');
$host = Tools::getShopProtocol() . Tools::getHttpHost().__PS_BASE_URI__ ;
$smarty->assign('host', $host);
$smarty->assign('closeMapTranslation', $this->l('close X'));
$this->getContext()->controller->addJs('https://maps.googleapis.com/maps/api/js?key=AIzaSyAFOrS3TAOJ97euuV0DGmMHIza4lRw709c');
return $this->display(__FILE__, '/views/templates/hook/header_hook.tpl');
}
}
/**
* Since Prestashop 1.5, this hook is used to display list of available carriers for each
* of order addresses.
* @access public
* @param array $params Parameters array (cart object, address informations)
* @return Display template.
*/
public function hookDisplayCarrierList($params)
{
// exit if module is offline or multishipping is enabled
if (EnvoimoinscherModel::getConfig('EMC_SRV_MODE') == EnvoimoinscherModel::MODE_CONFIG ||
(int)EnvoimoinscherModel::getConfig('PS_ALLOW_MULTISHIPPING') == 1) {
return;
}
$smarty = $this->getContext()->smarty;
$helper = new EnvoimoinscherHelper;
$cart = $params['cart'];
// adding this for $this->model->address to be filled in some cases
$this->model->getRecipient($cart->id, $cart->id_address_delivery);
$pointCode = $helper->getPointCode($cart->id);
$points = $this->model->getCache($pointCode);
if ($points) {
$smarty->assign('points', $points);
} else {
$smarty->assign('points', array());
}
$point = $this->model->getSelectedPoint($cart->id);
$deliveryCode = $helper->getDeliveryDateCode($cart->id);
$delivery = $this->model->getCache($deliveryCode);
if ($delivery) {
foreach ($delivery as $key => $value) {
// we need to update carrier id in case there has been a change in the carriers
$carrierId = $this->model->getActiveCarrierId($key);
if ($carrierId) {
unset($delivery[$key]);
$delivery[$carrierId] = $this->dateToString($value);
}
}
$smarty->assign('delivery', $delivery);
}
$deliveryLabel = EnvoimoinscherHelper::getTranslation(
EnvoimoinscherModel::getConfig('EMC_LABEL_DELIVERY_DATE'),
$this->getContext()->language->language_code
);
$smarty->assign('point', $point);
$smarty->assign('deliveryLabel', $deliveryLabel);
$smarty->assign('id_address', $params['address']->id);
$smarty->assign('destCountry', $this->model->getCountryIsoFromName($params['address']->country));
return $this->display(__FILE__, '/views/templates/hook/envoimoinscher_carrier.tpl');
}
/**
* Hook to remove free emc carriers when they are not suitable for the order
* @access public
* @param array $params Parameters array (cart object, carriers, ...)
* @return $params.
*/
public function hookDisplayBeforeCarrier(&$params)
{
$removeCarriers = array();
if (isset($params['delivery_option_list'])) {
foreach ($params['delivery_option_list'] as $carrier_list_raw) {
foreach ($carrier_list_raw as $key => $carrier_list) {
// for some reason, $key has a comma at the end of it
$carrier_id = str_replace(',', '', $key);
// this test is used for Prestashop 1.5
$price_without_tax = '';
if (isset($carrier_list['carrier_list'])) {
foreach ($carrier_list['carrier_list'] as $v) {
$price_without_tax = $v['price_without_tax'];
}
}
// check if carrier is set to free
if ((isset($carrier_list['is_free']) && $carrier_list['is_free']) || $price_without_tax == 0) {
// check if carrier is an emc carrier
$emc_carrier_test = Db::getInstance()->ExecuteS(
'SELECT * FROM ' . _DB_PREFIX_ . 'carrier
WHERE id_carrier = ' . (int)$carrier_id . ' AND external_module_name = "envoimoinscher"'
);
if (!empty($emc_carrier_test)) {
$rate = $this->getOrderShippingCostSubFunction($params['cart'], $carrier_id);
// if $rate is false, add carrier to carriers to be removed
if ($rate === false) {
$removeCarriers[] = $key;
}
}
}
}
}
}
// if $removeCarriers is not empty, remove unwanted carriers
if (!empty($removeCarriers)) {
$smarty = $this->getContext()->smarty;
$smarty->assign('removeCarriers', $removeCarriers);
return $this->display(__FILE__, '/views/templates/hook/hookDisplayBeforeCarrier.tpl');
}
}
/**
* Checks if EnvoiMoinsCher order was already passed for this prestashop command.
* @access private
* @param int $order_id Id of order.
* @return boolean True if passed, false if not.
*/
private function isPassed($order_id)
{
$row = Db::getInstance()->ExecuteS(
'SELECT ' . _DB_PREFIX_ . 'orders_id_order FROM ' .
_DB_PREFIX_ . 'emc_orders
WHERE ' . _DB_PREFIX_ . 'orders_id_order = ' . (int)$order_id . ''
);
$result = false;
if (isset($row[0]) && $row[0][_DB_PREFIX_ . 'orders_id_order'] != '') {
$result = true;
}
return $result;
}
/**
* Checks if the order is timed out.
* @access private
* @param int $order_id Id of order.
* @return boolean True if passed, false if not.
*/
private function isSendLocked($order_id)
{
$row = Db::getInstance()->ExecuteS(
'SELECT eopt.' . _DB_PREFIX_ . 'orders_id_order FROM '._DB_PREFIX_ . 'emc_orders_post eopt
WHERE eopt.' . _DB_PREFIX_ . 'orders_id_order = ' . (int)$order_id . ' AND eopt.type = "timeout"
AND DATE_ADD(eopt.date_eopo, INTERVAL 5 MINUTE) > NOW()'
);
$result = false;
if (isset($row[0]) && $row[0][_DB_PREFIX_ . 'orders_id_order'] != '') {
$result = true;
}
return $result;
}
/**
* Get parcel points from a carrier and address (passed in get values)
* @access public
* @return void
*/
public function getPoints()
{
require_once(_PS_MODULE_DIR_ . $this->name . '/Env/WebService.php');
require_once(_PS_MODULE_DIR_ . $this->name . '/Env/ParcelPoint.php');
$smarty = $this->getContext()->smarty;
// Load the parcel points for the chosen carrier and address
$helper = new EnvoimoinscherHelper;
$carrier = (int)Tools::getValue('carrier');
$address_id = (int)Tools::getValue('addressId');
$env_cl = new Envoimoinscher;
$config = EnvoimoinscherModel::getConfigData();
$poi_cl = new EnvParcelPoint(array(
'user' => $config['EMC_LOGIN'],
'pass' => $config['EMC_PASS'],
'key' => $config['EMC_KEY_' . $config['EMC_ENV']]));
$poi_cl->setPlatformParams($env_cl->ws_name, _PS_VERSION_, $env_cl->version);
$poi_cl->setEnv(Tools::strtolower($config['EMC_ENV']));
$poi_cl->setLocale($this->getContext()->language->language_code);
$poi_cl->construct_list = true;
foreach (explode(',', Tools::getValue('points')) as $point) {
if (Tools::getValue('country') == '' || ctype_alnum(Tools::getValue('country'))) {
$poi_cl->getParcelPoint('dropoff_point', $point, Tools::getValue('country'));
}
}
// add the inputs
$inputs = array();
$inputs['address'] = array();
$inputs['address']['name'] = 'parcelPoints' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['address']['id'] = 'parcelPoints' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['address']['value'] = array();
$inputs['info'] = array();
$inputs['info']['name'] = 'parcelInfos' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['info']['id'] = 'parcelInfos' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['info']['value'] = array();
$inputs['name'] = array();
$inputs['name']['name'] = 'parcelNames' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['name']['id'] = 'parcelNames' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['name']['value'] = array();
$inputs['id'] = array();
$inputs['id']['name'] = 'parcelIds' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['id']['id'] = 'parcelIds' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['id']['value'] = array();
$inputs['count'] = array();
$inputs['count']['name'] = 'counter' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['count']['id'] = 'counter' . $carrier . Tools::getValue('ope') . $address_id;
$inputs['count']['value'] = 0;
// ANTADIS PATCH :
// if the selected point is not in the list, ensure to erase the one saved in cart
$list_has_current_selection = false;
foreach ($poi_cl->points['dropoff_point'] as $point) {
if ($point['name'] != '') {
if ($point['code'] == Tools::getValue('pointValue')) {
$list_has_current_selection = true;
break;
}
}
}
if (!$list_has_current_selection) {
Db::getInstance()->execute(
'UPDATE `'._DB_PREFIX_ . 'emc_cart_tmp`
SET `selected_point` = ""
WHERE `id_cart` = '.(int)$this->getContext()->cookie->id_cart
);
}
// END ANTADIS PATCH
// add parcel points
$points = array();
$i = 0;
foreach ($poi_cl->points['dropoff_point'] as $point) {
if ($point['name'] != '') {
$point['checked'] = $point['code'] == Tools::getValue('pointValue');
$point['js'] = 'selectPr(\'' . $point['code'] . '\', \'' . (int)Tools::getValue('carrier') . '\', \'' .
$address_id . '\');';
$point['class'] = 'point' . $carrier . $address_id;
$point['input_name'] = 'point' . $carrier . Tools::getValue('ope') . $address_id;
$point['id'] = 'point' . $carrier . $point['code'] . $address_id;
$inputs['address']['value'][] = $point['address'] . ', ' . $point['zipcode'] . ' ' . $point['city'];
$inputs['info']['value'][] = implode(' ', $helper->setSchedule($point['schedule']));
$inputs['name']['value'][] = $point['name'];
$inputs['id']['value'][] = $point['code'];
$points[] = $point;
}
$i++;
}
if ($i == 0) {
return 'noPoint';
}
$inputs['address']['value'] = implode('|', $inputs['address']['value']);
$inputs['info']['value'] = implode('|', $inputs['info']['value']);
$inputs['name']['value'] = implode('|', $inputs['name']['value']);
$inputs['id']['value'] = implode('|', $inputs['id']['value']);
$smarty->assign('points', $points);
$smarty->assign('inputs', $inputs);
return $this->display(__FILE__, '/views/templates/front/get_points.tpl');
}
/**
* Sets parcel point in the database.
* @access public
* @param string $post_point Id of choosen parcel point.
* @return void
*/
public function setPoint($post_point)
{
$cookie = $this->getContext()->cookie;
$point = explode('-', $post_point);
if (ctype_alnum(trim($point[0])) && ctype_alnum(trim($point[1]))) {
$data = array(
'id_cart' => (int)$cookie->id_cart,
'selected_point' => pSQL(trim($post_point))
);
return Db::getInstance()->autoExecute(
_DB_PREFIX_ . 'emc_cart_tmp',
$data,
'REPLACE'
);
}
return 0;
}
/**
* Return the quotation for the informations given.
* This function SHOULD NOT include any PS configuration modifications on shipping, as this is what we store
* in cache and we shouldn't have to empty the offers cache for any PS configuration modification
* @access public
* @param $from : departure address
* @param $to : delivery address
* @param $parcels : parcel configuration
* @param $params : additional parameters
* @param $curlMulti : true : the function will do a multirequest on all activated services,
* else it will do a simple request
* @param $cache : true : if cache should be used
* @return array List with offers.
*/
public function getQuote($from, $to, $parcels, $params, $curlMulti = true, $cache = true)
{
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l('Quotation - from %1$s %2$s to %3$s %4$s'),
$from['code_postal'],
$from['ville'],
$to['code_postal'],
$to['ville']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
// Get cache
$pricingCode = EnvoimoinscherHelper::getPricingCode($from, $to, $parcels, $params, $curlMulti);
if ($cache) {
$offers = $this->model->getCache($pricingCode);
if ($offers !== false) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = $this->l('Quotation - Cache used');
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
return $offers;
}
}
$helper = new EnvoimoinscherHelper;
$config = EnvoimoinscherModel::getConfigData();
// check if call comes from tests()
if (!isset($params['testPage'])) {
$params['testPage'] = false;
}
// Create quotation object
require_once('Env/WebService.php');
require_once('Env/Quotation.php');
$lib = new EnvQuotation(
array(
'user' => $config['EMC_LOGIN'],
'pass' => $config['EMC_PASS'],
'key' => $config['EMC_KEY_' . $config['EMC_ENV']]
)
);
$lib->setEnv(Tools::strtolower($config['EMC_ENV']));
$lib->setLocale($this->getContext()->language->language_code);
$lib->setPlatformParams($this->ws_name, _PS_VERSION_, $this->version);
// Initialize the quotation
$lib->setPerson('expediteur', $from);
$lib->setPerson('destinataire', $to);
$lib->setType($params['emc_type'], $parcels);
// Curl multi or single request on all activated carriers
if (!$curlMulti) {
// get all activated services
$services = $helper->makeCodeKeys($this->model->getEmcCarriers());
if (count($services) == 0) {
if ($params['testPage']) {
$error_msg = $this->l(
'No carrier activated, please activate carriers before making a simulation'
);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = $this->l('Quotation - No carrier activated');
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
return array('isError' => 1, 'message' => $error_msg);
}
}
$params['offers'] = array();
foreach ($services as $carrier_code => $carrier) {
list($operator, $service) = explode('_', $carrier_code);
array_push($params['offers'], $operator.$service);
}
$lib->getQuotation($params);
$lib->getOffers(false);
} else {
// get all activated services
$services = $helper->makeCodeKeys($this->model->getEmcCarriers());
if (count($services) == 0) {
if ($params['testPage']) {
$error_msg = $this->l(
'No carrier activated, please activate carriers before making a simulation'
);
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = $this->l('Quotation - No carrier activated');
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
return array('isError' => 1, 'message' => $error_msg);
}
}
foreach ($services as $carrier_code => $carrier) {
list($operator, $service) = explode('_', $carrier_code);
$params['operator'] = $operator;
$params['service'] = $service;
$lib->setParamMulti($params);
}
$lib->getQuotationMulti();
$lib->getOffersMulti();
}
$offers = array();
if ($lib->curl_error) {
$error_msg = $this->l('The shipment platform is currently unavailable');
if ($params['testPage']) {
$offers = array('isError' => 1, 'message' => $error_msg);
}
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $error_msg, 3);
} elseif ($lib->resp_error) {
if ($params['testPage']) {
$offers = array('isError' => 1, 'message' => $lib->resp_errors_list[0]['message']);
}
$message = sprintf(
$this->l('Error while recovering offers: %1$s'),
$lib->resp_errors_list[0]['message']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 4);
} else {
$offers = $lib->offers;
if (count($offers) != 0) {
// If several offers have the same operator and service (Chrono18...), keep only the cheapest
$checkOffers = array();
foreach ($offers as $key => $offer) {
if (isset($checkOffers[$offer['operator']['code'].'_'.$offer['service']['code']])) {
if ($offer['price']['tax-exclusive'] <
$checkOffers[$offer['operator']['code'].'_'.$offer['service']['code']]['price']) {
$checkOffers[$offer['operator']['code'].'_'.$offer['service']['code']] = array(
'key' => $key,
'price' => $offer['price']['tax-exclusive']
);
unset(
$offers[$checkOffers[$offer['operator']['code'].'_'.$offer['service']['code']]['key']]
);
} else {
unset($offers[$key]);
}
} else {
$checkOffers[$offer['operator']['code'].'_'.$offer['service']['code']] = array(
'key' => $key,
'price' => $offer['price']['tax-exclusive']
);
}
}
// Log API base prices
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
foreach ($offers as $offer) {
$message = sprintf(
$this->l('Quotation - API tax-exclusive price for %1$s is %2$s€'),
$offer['operator']['code'] . '_' . $offer['service']['code'],
$offer['price']['tax-exclusive']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
}
}
}
if (count($offers) == 0) {
if ((int)EnvoimoinscherModel::getConfig('EMC_ENABLED_LOGS') == 1) {
$message = sprintf(
$this->l(
'Quotation - no offer found for shipping from %1$s %2$s to %3$s %4$s %5$s, '
.'the cart weighs %6$skg'
),
$from['code_postal'],
$from['ville'],
$to['code_postal'],
$to['ville'],
$to['pays'],
$parcels[1]['poids']
);
Logger::addLog('['.$this->l('ENVOIMOINSCHER').'][' . time() . '] ' . $message, 1);
}
}
// Cache API results
$this->model->setCache($pricingCode, $offers, 86400);
return $offers;
}
/**
* Gets environment's url.
* @access public
* @param string $env Environment key.
* @return string Environment's url.
*/
public function getEnvironment($env)
{
return $this->environments[$env]['link'];
}
/**
* Get the upgrade list of the module
*/
public function getUpgrades()
{
return $this->parseUpgradeXml(_PS_MODULE_DIR_ . $this->name . '/sql/upgrades/upgrades.xml');
}
/**
* Executes upgrade queries.
* @access public
* @return Displayed template
*/
public function makeUpgrade()
{
$cookie = $this->getContext()->cookie;
$smarty = $this->getContext()->smarty;
$error = false;
$list = $this->getUpgrades();
$id = (int)Tools::getValue('up_id');
$queries = explode(
'-- REQUEST --',
Tools::file_get_contents(_PS_MODULE_DIR_ . $this->name . '/sql/upgrades/' . $list[$id]['file'])
);
foreach ($queries as $q => $query) {
$query = str_replace('{PREFIXE}', _DB_PREFIX_, $query);
if (trim($query) != '' && !Db::getInstance()->Execute($query)) {
$error = true;
break;
}
unset($queries[$q]);
}
if (count($queries) > 0) {
file_put_contents(
_PS_MODULE_DIR_ . $this->name . '/sql/upgrades/' . $list[$id]['file'],
implode('-- REQUEST --', $queries)
);
} else {
$error = $this->removeUpgradeItem($id, _PS_MODULE_DIR_ . $this->name . '/sql/upgrades/upgrades.xml');
unlink(_PS_MODULE_DIR_ . $this->name . '/sql/upgrades/' . $list[$id]['file']);
}
$smarty->assign('error', $error);
$smarty->assign('adminImg', _PS_ADMIN_IMG_);
$smarty->assign(
'token',
Tools::getAdminToken(
'AdminModules' . (int)Tab::getIdFromClassName('AdminModules') . (int)$cookie->id_employee
)
);
return $this->display(__FILE__, '/views/templates/admin/upgrade.tpl');
}
/**
* Parse upgraded XML file and get list of upgrades.
* @access private
* @param string $file File name.
* @return array List with upgrades.
*/
private function parseUpgradeXml($file)
{
if (!file_exists($file)) {
return array();
}
$result = array();
$dom_cl = new DOMDocument();
$dom_cl->load($file);
$xpath = new DOMXPath($dom_cl);
$upgrades = $xpath->evaluate('/upgrades/upgrade');
foreach ($upgrades as $upgrade) {
$date = strtotime($upgrade->getElementsByTagName('date')->item(0)->nodeValue);
$result[$upgrade->getElementsByTagName('id')->item(0)->nodeValue] = array(
'from' => $upgrade->getElementsByTagName('from')->item(0)->nodeValue,
'to' => $upgrade->getElementsByTagName('to')->item(0)->nodeValue,
'date' => date('d-m-Y', $date),
'description' => $upgrade->getElementsByTagName('description')->item(0)->nodeValue,
'file' => $upgrade->getElementsByTagName('file')->item(0)->nodeValue);
}
return $result;
}
/**
* Removes upgraded item from XML file.
* @access private
* @param int $id Id of upgraded item.
* @param string $file File name.
* @return boolean True if executed correctly, false otherwise.
*/
private function removeUpgradeItem($id, $file)
{
$error = true;
$dom_cl = new DOMDocument();
$dom_cl->load($file);
$xpath = new DOMXPath($dom_cl);
$main = $xpath->evaluate('/upgrades')->item(0);
$upgrades = $xpath->evaluate('/upgrades/upgrade');
foreach ($upgrades as $upgrade) {
if ($upgrade->getElementsByTagName('id')->item(0)->nodeValue == $id) {
$main->removeChild($upgrade);
$error = false;
}
}
file_put_contents($file, $dom_cl->saveXML());
return $error;
}
/**
* Downloads one or more EnvoiMoinsCher's labels.
* @access public
* @return void
*/
public function downloadLabels()
{
$cookie = $this->getContext()->cookie;
$orders_to_get = array();
$refs = array();
$url = '';
$base_url = '';
$type = '';
$envoi = '';
if (Tools::isSubmit('orders')) {
foreach (Tools::getValue('orders') as $ord) {
$orders_to_get[] = (int)$ord;
}
} elseif (Tools::isSubmit('order')) {
$orders_to_get[] = (int)Tools::getValue('order');
}
// We need order's infos for the document's url and references
if (count($orders_to_get) > 0) {
$references = $this->model->getReferencesToLabels($orders_to_get);
foreach ($references as $reference) {
$refs[] = $reference['ref_emc_eor'];
}
}
// We now query the document
if (count($refs) > 0) {
// Get the document's base url
$base_url = explode('?', $references[0]['link_ed']);
$base_url = $base_url[0];
// Set url's params
if (Tools::getValue('sendValueRemises')) {
$type = 'remise';
} else {
$type = 'bordereau';
}
$envoi = implode(',', $refs);
// Set url
$url = $base_url . '?type=' . $type . '&envoi=' . $envoi;
// Send the pdf request
$cookie->error_labels = 0;
$helper = new EnvoimoinscherHelper;
$config = EnvoimoinscherModel::getConfigData();
$options = array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER =>
array('Authorization: ' . $helper->encode($config['EMC_LOGIN'] . ':' . $config['EMC_PASS'])),
CURLOPT_CAINFO => dirname(__FILE__) . '/ca/ca-bundle.crt',
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2
);
$req = curl_init();
curl_setopt_array($req, $options);
$result = curl_exec($req);
curl_close($req);
// We now display the pdf
header('Content-type: application/pdf');
if ($type == 'remise') {
header('Content-Disposition: attachment; filename="remises.pdf"');
} else {
header('Content-Disposition: attachment; filename="bordereaux.pdf"');
}
echo $result;
die();
}
$cookie->error_labels = 1;
$admin_link_base = $this->link->getAdminLink('AdminEnvoiMoinsCher');
Tools::redirectAdmin($admin_link_base . '&option=history');
}
public function checkUpdates()
{
$config = EnvoimoinscherModel::getConfigData();
$result = array();
$filename = $this->getEnvironment($config['EMC_ENV']) . '/api/check_updates.html?module=' . $this->ws_name .
'&version=' . $this->local_version;
$updates = (array)Tools::jsonDecode(Tools::file_get_contents($filename));
foreach ($updates as $u => $update) {
$info = (array)$update;
$result[] = array(
'version' => $u,
'name' => $info['name'],
'description' => $info['description'],
'url' => $this->getEnvironment($config['EMC_ENV']) . $info['url']);
}
echo Tools::jsonEncode($result);
die();
}
public function lookForCarrierUpdates()
{
require_once(_PS_MODULE_DIR_ . '/envoimoinscher/Env/WebService.php');
require_once(_PS_MODULE_DIR_ . '/envoimoinscher/Env/Carrier.php');
require_once(_PS_MODULE_DIR_ . '/envoimoinscher/Env/Service.php');
$config = EnvoimoinscherModel::getConfigData();
$ser_class = new EnvService(array(
'user' => $config['EMC_LOGIN'],
'pass' => $config['EMC_PASS'],
'key' => $config['EMC_KEY_' . $config['EMC_ENV']]));
$ser_class->setPlatformParams($this->ws_name, _PS_VERSION_, $this->version);
$ser_class->setEnv(Tools::strtolower($config['EMC_ENV']));
$ser_class->setLocale($this->getContext()->language->language_code);
$ser_class->setParam(array('module' => $this->ws_name, 'version' => $this->local_version));
$ser_class->setGetParams();
$ser_class->getServices();
$offers = $this->model->getOffers;
$installed = array();
$checksums = array();
$offers_json = array('added' => array(), 'updated' => array(), 'deleted' => array());
$deleted = 0;
$added = 0;
$updated = 0;
foreach ($offers as $offer) {
$installed[$offer['emc_operators_code_eo'] . '_' . $offer['code_es']] = $offer;
$checksums[$offer['emc_operators_code_eo'] . '_' . $offer['code_es']] = sha1(
$offer['desc_store_es'] . $offer['family_es']
);
}
foreach ($ser_class->carriers as $c => $carrier) {
foreach ($carrier['services'] as $service) {
$code = $c . '_' . $service['code'];
$exists = isset($installed[$code]);
$service_infos = array('label_backoffice' => '', 'label_store' => '');
if (isset($service['apiOptions']['prestashop'])) {
$service_infos = array(
'label_backoffice' =>
html_entity_decode($service['apiOptions']['prestashop']['label_backoffice']),
'label_store' => html_entity_decode($service['apiOptions']['prestashop']['label_store']),
'offer_family' => (int)$service['apiOptions']['prestashop']['offer_family']);
}
$srv_checksum = sha1(
$service_infos['label_backoffice'] . $service_infos['label_store'] . $service_infos['offer_family']
);
if (!$exists && $service['is_pluggable']) {
// install new service and remove from $installed array
$service['srvInfos'] = $service_infos;
if ($this->model->insertService($service, $carrier)) {
$carrier_lower = Tools::strtolower($carrier['code']);
file_put_contents(
_PS_MODULE_DIR_ . '/envoimoinscher/img/detail_' . $carrier_lower . '.jpg',
Tools::file_get_contents($carrier['logo_modules'])
);
$added++;
$offers_json['added'][] = $service['label'];
}
} elseif ($exists && !$service['is_pluggable']) {
// uninstall carrier
if ($this->model->uninstallService($code)) {
$deleted++;
$offers_json['deleted'][] = $service['label'];
}
} elseif ($exists && $checksums[$code] != $srv_checksum) {
// new data available, must update
$parts = explode('_', $code);
$up_data = array(
'desc_store_es' => pSQL($service_infos['label_store']),
'family_es' => (int)$service_infos['offer_family']
);
if ($this->model->updateService($up_data, $parts[0], $parts[1])) {
$updated++;
$offers_json['updated'][] = $service['label'];
}
unset($installed[$code]);
} elseif ($exists && isset($installed[$code])) {
unset($installed[$code]);
}
}
}
// clean up old services in Prestashop database
foreach ($installed as $code => $offer) {
if ($this->model->uninstallService($code)) {
$deleted++;
$offers_json['deleted'][] = $offer['label_es'];
}
}
echo Tools::jsonEncode(array(
'added' => $added,
'updated' => $updated,
'deleted' => $deleted,
'addedOffers' => implode(',', $offers_json['added']),
'updatedOffers' => implode(',', $offers_json['updated']),
'deletedOffers' => implode(',', $offers_json['deleted'])));
die();
}
public function checkLabelsAvailability()
{
$orders_id = explode(';', Tools::getValue('orders'));
if (count($orders_id) > 0) {
$documents = Db::getInstance()->ExecuteS(
'SELECT * FROM ' . _DB_PREFIX_ . 'emc_documents
WHERE generated_ed = 1 AND ' . _DB_PREFIX_ . 'orders_id_order in (' .
implode(',', array_map('intval', $orders_id)) . ')'
);
// get all documents for each order
$order_documents = array();
foreach ($documents as $document) {
$id = $document['ps_orders_id_order'];
if (!isset($order_documents[$id])) {
$order_documents[$id] = array();
}
$order_documents[$id][] = array(
'type' => $document['type_ed'],
'name' => $this->l('download ' . $document['type_ed']),
'url' => $document['link_ed']
);
}
}
echo Tools::jsonEncode($order_documents);
die();
}
/**
* Puts EnvoiMoinsCher's choosen carrier
* @access public
* @param int $ope Operator's id.
* @param boolean $is_discount True if discount is applied, false otherwise.
* @return void
*/
public function putOpe($ope, $is_discount)
{
$cookie = $this->getContext()->cookie;
$cookie->emc_carrier = (int)$ope;
$cookie->emc_discount = $is_discount;
}
private function getModuleConfig()
{
return array('wsName' => $this->ws_name, 'version' => $this->local_version, 'is13' => false);
}
/**
* Edit delivery address when order hasn't EMC carrier and the order address is incorrect (bad postal code etc.)
* @access public
* @return void
*/
public function editAddress()
{
$order_id = (int)Tools::getValue('id_order');
// get old address data
$address = $this->model->getOrderData($order_id);
$company = $address[0]['company'];
if (Tools::getValue('dest_company')) {
$company = Tools::getValue('dest_company');
}
$perso_alias = '_perso_' . $order_id;
// insert new address row
$insert_row = array(
'id_country' => (int)$address[0]['id_country'],
'id_state' => (int)$address[0]['id_state'],
'id_customer' => (int)$address[0]['id_customer'],
'id_manufacturer' => (int)$address[0]['id_manufacturer'],
'id_supplier' => (int)$address[0]['id_supplier'],
'alias' => pSQL(str_replace($perso_alias, '', $address[0]['alias']) . $perso_alias),
'company' => pSQL($company),
'lastname' => pSQL(Tools::getValue('dest_lname')),
'firstname' => pSQL(Tools::getValue('dest_fname')),
'address1' => pSQL(Tools::getValue('dest_add')),
'address2' => pSQL($address[0]['address2']),
'postcode' => pSQL(Tools::getValue('dest_code')),
'city' => pSQL(Tools::getValue('dest_city')),
'other' => pSQL($address[0]['other']),
'phone' => pSQL(Tools::getValue('dest_tel')),
'phone_mobile' => pSQL($address[0]['phone_mobile']),
'vat_number' => pSQL($address[0]['vat_number']),
'dni' => pSQL($address[0]['dni']),
'date_add' => date('Y-m-d H:i:s'),
'date_upd' => date('Y-m-d H:i:s'),
'active' => 0,
'deleted' => 1
);
// update id_address_delivery field on orders table
$this->model->putNewAddress($order_id, $insert_row, $address[0]);
$admin_link_base = $this->link->getAdminLink('AdminEnvoiMoinsCher');
Tools::redirectAdmin($admin_link_base . '&option=send&id_order=' . $order_id);
die();
}
/**
* Cleans pricing cache. It deletes only pricing older than 2 days.
* @access public
* @return void
*/
public function cleanCache()
{
$result = array('error' => 1);
if ($this->model->cleanCache()) {
$result['error'] = 0;
}
echo Tools::jsonEncode($result);
die();
}
/**
* Process
* @return mixed
*/
private function postProcess()
{
$this->link = 'index.php?controller=' . Tools::getValue('controller') .
'&token=' . Tools::getValue('token') .
'&configure=' . $this->name .
'&tab_module=' . $this->tab .
'&module_name=' . $this->name;
$this->getContext()->smarty->assign('EMC_link', $this->link);
// Onboarding popup
$emc_user = EnvoimoinscherModel::getConfig('EMC_USER');
if ((int)$emc_user == 0 && !Tools::isSubmit('ajax')) {
// If we need to previous configuration
if (Tools::isSubmit('previous')) {
Tools::redirectAdmin($this->link);
return;
}
// EMC configuration
if (Tools::getValue('btnEmc')) {
return $this->postProcessEmc();
}
}
// Save status
if (Tools::getValue('EMC_Status') && Tools::getValue('ajax')) {
$status = Tools::getValue('EMC_Status') === 'true' ?
EnvoimoinscherModel::MODE_ONLINE : EnvoimoinscherModel::MODE_CONFIG;
EnvoimoinscherModel::updateConfig('EMC_SRV_MODE', $status);
if ($status == EnvoimoinscherModel::MODE_ONLINE) {
$this->model->passToOnlineMode();
}
Tools::jsonEncode(true);
exit;
} elseif (Tools::getValue('EMC_Env') && Tools::getValue('ajax')) {
EnvoimoinscherModel::updateConfig('EMC_ENV', Tools::getValue('EMC_Env'));
Tools::jsonEncode(true);
exit;
} elseif (Tools::getValue('ajax')) {
$tab = Tools::ucfirst(Tools::strtolower(Tools::getValue('EMC_tab')));
/** Merchant Account **/
if ($tab === 'Merchant') {
echo $this->getContentMerchant();
} elseif ($tab === 'Sends') {
echo $this->getContentSends();
} elseif ($tab === 'Settings') {
echo $this->getContentSettings();
} elseif ($tab === 'Simple_carriers') {
echo $this->getContentCarriers('Simple');
} elseif ($tab === 'Advanced_carriers') {
echo $this->getContentCarriers('Advanced');
} elseif ($tab === 'Help') {
echo $this->getContentHelp();
}
exit;
} elseif (Tools::getValue('btnMerchant')) {
return $this->postProcessMerchant();
} elseif (Tools::getValue('btnCarriersSimple')) {
return $this->postProcessCarriersSimple();
} elseif (Tools::getValue('btnCarriersAdvanced')) {
return $this->postProcessCarriersAdvanced();
} elseif (Tools::getValue('btnSends')) {
return $this->postProcessSends();
} elseif (Tools::getValue('btnSettings')) {
if (Tools::getValue('EMC_track_mode') &&
Tools::getValue('EMC_ann') &&
Tools::getValue('EMC_envo') &&
Tools::getValue('EMC_cmd') &&
Tools::getValue('EMC_liv')
) {
// Update configuration
EnvoimoinscherModel::updateConfig('EMC_INDI', Tools::getValue('EMC_indiv'));
EnvoimoinscherModel::updateConfig('EMC_MULTIPARCEL', Tools::getValue('EMC_multiparcel'));
// Track mode
EnvoimoinscherModel::updateConfig('EMC_TRACK_MODE', (int)Tools::getValue('EMC_track_mode'));
// Status
EnvoimoinscherModel::updateConfig('EMC_ANN', Tools::getValue('EMC_ann'));
EnvoimoinscherModel::updateConfig('EMC_ENVO', Tools::getValue('EMC_envo'));
EnvoimoinscherModel::updateConfig('EMC_CMD', Tools::getValue('EMC_cmd'));
EnvoimoinscherModel::updateConfig('EMC_LIV', Tools::getValue('EMC_liv'));
EnvoimoinscherModel::updateConfig('EMC_DISABLE_CART', Tools::getValue('EMC_disable_cart'));
EnvoimoinscherModel::updateConfig('EMC_ENABLED_LOGS', Tools::getValue('EMC_enabled_logs'));
EnvoimoinscherModel::updateConfig('EMC_FILTER_TYPE_ORDER', Tools::getValue('EMC_filter_type_order'));
EnvoimoinscherModel::updateConfig(
'EMC_FILTER_STATUS',
implode(';', Tools::getValue('EMC_filter_status'))
);
EnvoimoinscherModel::updateConfig('EMC_FILTER_CARRIERS', Tools::getValue('EMC_filter_carriers'));
EnvoimoinscherModel::updateConfig(
'EMC_FILTER_START_DATE',
Tools::getValue('EMC_filter_start_order_date')
);
Tools::redirectAdmin($this->link . '&EMC_tabs=settings&conf=6');
} else {
return $this->displayError($this->l('Please check your form, some fields are requried'));
}
}
}
private function postProcessIntroduction()
{
}
private function postProcessEmc()
{
$errors = array();
$helper = new EnvoimoinscherHelper();
// Validation for account creation form
if (Tools::getValue('choice') == 'create') {
// validate gender
if (Tools::getValue('contact_civ')) {
if (Tools::getValue('contact_civ') == 'M.') {
EnvoimoinscherModel::updateConfig('EMC_CIV', 'M');
} else {
EnvoimoinscherModel::updateConfig('EMC_CIV', 'Mme');
}
}
// validate surname
if (Tools::getValue('contact_nom')) {
EnvoimoinscherModel::updateConfig('EMC_LNAME', Tools::getValue('contact_nom'));
} else {
$errors[] = $this->l('Please specify your surname');
}
// validate first name
if (Tools::getValue('contact_prenom')) {
EnvoimoinscherModel::updateConfig('EMC_FNAME', Tools::getValue('contact_prenom'));
} else {
$errors[] = $this->l('Please specify your first name');
}
// validate occupation
if (!Tools::getValue('profession')) {
$errors[] = $this->l('Please specify your occupation');
}
// validate email
if (!Tools::getValue('contact_email')) {
$errors[] = $this->l('Please specify your email address');
}
if (!Tools::getValue('contact_email2')) {
$errors[] = $this->l('Please confirm your email address');
} elseif (Tools::getValue('contact_email') != Tools::getValue('contact_email2')) {
$errors[] = $this->l('Please verify your email address and its confirmation');
} elseif (!$helper->validateEmail(Tools::getValue('contact_email'))) {
$errors[] = $this->l('Please specify a valid email address');
} else {
EnvoimoinscherModel::updateConfig('EMC_MAIL', Tools::getValue('contact_email'));
}
// validate login
if (Tools::getValue('login')) {
if (!$helper->validateAlpha(Tools::getValue('login'))) {
$errors[] = $this->l('Your ID may only contain alphanumerical characters');
} else {
EnvoimoinscherModel::updateConfig('EMC_LOGIN', Tools::getValue('login'));
}
} else {
$errors[] = $this->l('Please specify a login');
}
// validate password
if (!Tools::getValue('password')) {
$errors[] = $this->l('Please enter your password');
}
if (!Tools::getValue('confirm_password')) {
$errors[] = $this->l('Please confirm your password');
} elseif (Tools::getValue('password') != Tools::getValue('confirm_password')) {
$errors[] = $this->l('Please verify your password and its confirmation');
} elseif (Tools::strlen(Tools::getValue('password')) < 6) {
$errors[] = $this->l('Your password must contain at least 6 characters');
} else {
EnvoimoinscherModel::updateConfig('EMC_PASS', Tools::getValue('password'));
}
// validate company
if (Tools::getValue('contact_ste')) {
EnvoimoinscherModel::updateConfig('EMC_COMPANY', Tools::getValue('contact_ste'));
} else {
$errors[] = $this->l('Please specify your company');
}
// validate address
if (Tools::getValue('adresse1')) {
// save address only if country is France
if (Tools::getValue('pz_iso') == 'FR') {
$address = Tools::getValue('adresse1');
if (Tools::isSubmit('adresse2')) {
$address .= ' ' . Tools::getValue('adresse2');
}
if (Tools::isSubmit('adresse3')) {
$address .= ' ' . Tools::getValue('adresse3');
}
EnvoimoinscherModel::updateConfig('EMC_ADDRESS', $address);
}
} else {
$errors[] = $this->l('Please specify your address');
}
// validate postcode
if (Tools::getValue('contact_cp')) {
// save postcode only if country is France
if (Tools::getValue('pz_iso') == 'FR') {
EnvoimoinscherModel::updateConfig('EMC_POSTALCODE', Tools::getValue('contact_cp'));
}
} else {
$errors[] = $this->l('Please specify your postal code');
}
// validate city
if (Tools::getValue('contact_ville')) {
// save city only if country is France
if (Tools::getValue('pz_iso') == 'FR') {
EnvoimoinscherModel::updateConfig('EMC_CITY', Tools::getValue('contact_ville'));
}
} else {
$errors[] = $this->l('Please specify your city');
}
// validate phone
if (Tools::getValue('contact_tel')) {
if (!$helper->validatePhone(Tools::getValue('contact_tel'))) {
$errors[] = $this->l('Please specify a valid phone number');
} else {
EnvoimoinscherModel::updateConfig('EMC_TEL', Tools::getValue('contact_tel'));
}
} else {
$errors[] = $this->l('Please specify your telephone number');
}
// validate siret
if (!Tools::getValue('contact_stesiret')) {
if (Tools::getValue('pz_iso') == 'FR') {
$errors[] = $this->l('Please specify the SIRET (business identification) number');
} else {
$errors[] = $this->l('Please specify the legal registration or enrolment number in the country');
}
} elseif (Tools::getValue('pz_iso') == 'FR' && Tools::strlen(Tools::getValue('contact_stesiret')) != 14) {
$errors[] = $this->l(
'The SIRET (business identification) number is invalid. Please verify that it contains 14 figures'
);
}
// validate cgv
if (!Tools::getValue('cgv')) {
$errors[] = $this->l('Please check the General Terms of Sale before proceeding');
}
if (!empty($errors)) {
return $this->displayError(
$this->l('The following errors have occurred:') . '
' .
implode('
', $errors) . '
'
);
}
}
// Validation for "get key" form
if (Tools::getValue('choice') == 'get_key') {
// validate login
if (Tools::getValue('login')) {
EnvoimoinscherModel::updateConfig('EMC_LOGIN', Tools::getValue('login'));
} else {
$errors[] = $this->l('Please specify a login');
}
// validate password
if (Tools::getValue('password')) {
EnvoimoinscherModel::updateConfig('EMC_PASS', Tools::getValue('password'));
} else {
$errors[] = $this->l('Please enter your password');
}
// validate cgv
if (Tools::getValue('cgv') == false) {
$errors[] = $this->l('Please check the General Terms of Sale before proceeding');
}
if (!empty($errors)) {
return $this->displayError(
$this->l('The following errors have occurred:') . '
' .
implode('
', $errors) . '
'
);
}
}
// Save "get key" form info if user has already got an API key and has filled in the form nonetheless
if (Tools::getValue('choice') == 'proceed') {
// save login
if (Tools::getValue('login')) {
EnvoimoinscherModel::updateConfig('EMC_LOGIN', Tools::getValue('login'));
}
// save password
if (Tools::getValue('password')) {
EnvoimoinscherModel::updateConfig('EMC_PASS', Tools::getValue('password'));
}
}
if (Tools::getValue('choice') == 'get_key' || Tools::getValue('choice') == 'create') {
$config = EnvoimoinscherModel::getConfigData();
$options = array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER =>
array('Authorization: ' . $helper->encode($config['EMC_LOGIN'] . ':' . $config['EMC_PASS'])),
CURLOPT_CAINFO => dirname(__FILE__) . '/ca/ca-bundle.crt',
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_POST => true
);
if (Tools::getValue('choice') == 'create') {
$url = 'http://www.envoimoinscher.com/ajax/validate-inscription.txt.vtl';
$password = $helper->encryptPassword(pSQL(Tools::getValue('password')));
$confirm_password = $helper->encryptPassword(pSQL(Tools::getValue('confirm_password')));
$postfields = array(
'module' => 'prestashop',
'moduleEMC' => true,
'facturation.contact_civ' => Tools::getValue('contact_civ'),
'facturation.contact_nom' => pSQL(trim(Tools::getValue('contact_nom'))),
'facturation.contact_prenom' => pSQL(trim(Tools::getValue('contact_prenom'))),
'user.profession' => Tools::getValue('profession'),
'user.logiciel' => Tools::getValue('logiciel'),
'user.partner_code' => pSQL(trim(Tools::getValue('partner_code'))),
'facturation.url' => pSQL(trim(Tools::getValue('url'))),
'facturation.contact_email' => pSQL(trim(Tools::getValue('contact_email'))),
'facturation.contact_email2' => pSQL(trim(Tools::getValue('contact_email2'))),
'user.login' => pSQL(trim(Tools::getValue('login'))),
'user.password' => urlencode($password),
'user.confirm_password' => urlencode($confirm_password),
'facturation.contact_ste' => pSQL(trim(Tools::getValue('contact_ste'))),
'facturation.adresse1' => pSQL(trim(Tools::getValue('adresse1'))),
'facturation.adresse2' => pSQL(trim(Tools::getValue('adresse2'))),
'facturation.adresse3' => pSQL(trim(Tools::getValue('adresse3'))),
'facturation.pays_iso' => Tools::getValue('pz_iso'),
'facturation.codepostal' =>
pSQL(trim(Tools::getValue('contact_cp'))) . ' ' . pSQL(trim(Tools::getValue('contact_ville'))),
'facturation.contact_tel' => pSQL(trim(Tools::getValue('contact_tel'))),
'facturation.contact_stesiret' => pSQL(trim(Tools::getValue('contact_stesiret'))),
'facturation.contact_tvaintra' => pSQL(trim(Tools::getValue('contact_tvaintra'))),
'facturation.contact_locale' => Tools::getValue('contact_locale'),
'cgv' => Tools::getValue('cgv'),
'newsletterEmc' => Tools::getValue('newsletterEmc'),
'newsletterCom' => Tools::getValue('newsletterCom'),
);
if (Tools::isSubmit('contact_etat')) {
$postfields['facturation.contact_etat'] = Tools::getValue('contact_etat');
}
} else {
$url = 'http://ecommerce.envoimoinscher.com/ajax/validate-api-key.txt.vtl';
$postfields = array(
'facturation.logiciel' => Tools::getValue('logiciel'),
'user.login' => pSQL(Tools::getValue('login')),
'cgv' => Tools::getValue('cgv'),
);
}
$options[CURLOPT_URL] = $url;
$options[CURLOPT_POSTFIELDS] = http_build_query($postfields);
$req = curl_init();
curl_setopt_array($req, $options);
$result = curl_exec($req);
// Manage errors
$curl_info = curl_getinfo($req);
if (curl_errno($req) > 0) {
$errors[] = curl_error($req);
} elseif ($curl_info['http_code'] != '200' && $curl_info['http_code'] != '400'
&& $curl_info['http_code'] != '401') {
$message = 'There has been an error sending the request. The server could not respond correctly. ';
$message .= 'Please contact our technical assistance at informationAPI@boxtale.com (error: ';
$errors[] = $this->l($message) . $curl_info['http_code'] . ')';
}
curl_close($req);
if (!empty($errors)) {
return $this->displayError(
$this->l('The following errors have occurred:') . '