Files
bio-concept-labo/web/modules/btpartialshipment/btpartialshipment.php
2019-11-20 07:44:43 +01:00

1224 lines
59 KiB
PHP

<?php
/**
* Module Partial Shipment - Main file
*
* @author My Addons <contact@myaddons.io>
* @copyright 2017 My Addons
* @license myaddons.io
* @version 1.1.8
* @since File available since Release 1.0
*/
if (!defined('_PS_VERSION_')) {
exit;
}
class BtPartialShipment extends Module
{
public function __construct()
{
$this->author = 'MyAddons';
$this->tab = 'shipping_logistics';
$this->need_instance = 0;
$this->module_key = "8d245847e707d6117465cfd66851e1e3";
$this->author_address = '0xE4a7B4d225E2D9ACDf6d9e579EA04925912d32A0';
$this->name = 'btpartialshipment';
$this->version = '1.1.8';
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l('Manage partial shipment by order');
$this->description = $this->l('This module allows you to manage your partial shipments by orders and products.');
$this->confirmUninstall = $this->l('Are you sure you want to delete this module ?');
/* Retrocompatibility */
$this->initContext();
$this->css_path = $this->_path.'views/css/';
$this->js_path = $this->_path.'views/js/';
require_once _PS_MODULE_DIR_.'btpartialshipment/classes/PartialShipment.php';
require_once _PS_MODULE_DIR_.'btpartialshipment/classes/PartialShipmentDetail.php';
require_once _PS_MODULE_DIR_.'btpartialshipment/classes/HTMLTemplatePartialShipment.php';
}
/* Retrocompatibility 1.4/1.5 */
private function initContext()
{
$this->context = Context::getContext();
if (!$this->context->shop->id) {
$this->context->shop->id = 1;
}
}
public function install()
{
if (Shop::isFeatureActive()) {
Shop::setContext(Shop::CONTEXT_ALL);
}
$sql = '';
include(dirname(__FILE__).'/sql/install.php');
foreach ($sql as $s) {
if (!Db::getInstance()->execute($s)) {
return false;
}
}
if (!parent::install()
|| !$this->registerHook('displayAdminOrder')
|| !$this->registerHook('displayOrderDetail')
|| !$this->registerHook('displayBackOfficeHeader')
|| !$this->installOrderPartialStatus()
|| !$this->installOrderCompleteStatus()
|| !$this->installOrderRemainingStatus()
) {
return false;
}
return true;
}
private function installOrderPartialStatus()
{
if (!Configuration::get('BT_PARTIAL_SHIPMENT_STATE')) {
$order_state = new OrderState();
$order_state->name = array();
foreach (Language::getLanguages() as $language) {
switch (Tools::strtolower($language['iso_code'])) {
case 'fr':
$order_state->name[$language['id_lang']] = 'Expédition partielle';
break;
case 'it':
$order_state->name[$language['id_lang']] = 'Parzialmente Spedito';
break;
case 'es':
$order_state->name[$language['id_lang']] = 'Parcialmente Enviado';
break;
case 'pt':
$order_state->name[$language['id_lang']] = 'Enviado parcialmente';
break;
case 'de':
$order_state->name[$language['id_lang']] = 'Teilweise geliefert';
break;
case 'en':
$order_state->name[$language['id_lang']] = 'Partial shipment';
break;
case 'br':
$order_state->name[$language['id_lang']] = 'Enviado parcialmente';
break;
default:
$order_state->name[$language['id_lang']] = 'Partial shipment';
break;
}
}
$order_state->send_email = false;
$order_state->color = '#00d3c3';
$order_state->hidden = true;
$order_state->delivery = false;
$order_state->logable = true;
$order_state->invoice = false;
$order_state->paid = false;
if ($order_state->save()) {
if (version_compare(_PS_VERSION_, '1.5.4.1', '>')) {
Tools::copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
} else {
$this->copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
}
} else {
return false;
}
Configuration::updateValue('BT_PARTIAL_SHIPMENT_STATE', (int) $order_state->id);
return true;
} else {
$order_state = new OrderState((int) Configuration::get('BT_PARTIAL_SHIPMENT_STATE'));
if (!Validate::isLoadedObject($order_state)) {
$order_state = new OrderState();
$order_state->name = array();
foreach (Language::getLanguages() as $language) {
switch (Tools::strtolower($language['iso_code'])) {
case 'fr':
$order_state->name[$language['id_lang']] = 'Expédition partielle';
break;
case 'it':
$order_state->name[$language['id_lang']] = 'Parzialmente Spedito';
break;
case 'es':
$order_state->name[$language['id_lang']] = 'Parcialmente Enviado';
break;
case 'pt':
$order_state->name[$language['id_lang']] = 'Enviado parcialmente';
break;
case 'br':
$order_state->name[$language['id_lang']] = 'Enviado parcialmente';
break;
case 'de':
$order_state->name[$language['id_lang']] = 'Teilweise geliefert';
break;
case 'en':
$order_state->name[$language['id_lang']] = 'Partial shipment';
break;
default:
$order_state->name[$language['id_lang']] = 'Partial shipment';
break;
}
}
$order_state->send_email = false;
$order_state->color = '#00d3c3';
$order_state->hidden = true;
$order_state->delivery = false;
$order_state->logable = true;
$order_state->invoice = true;
if ($order_state->save()) {
if (version_compare(_PS_VERSION_, '1.5.4.1', '>')) {
Tools::copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
} else {
$this->copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
}
} else {
return false;
}
Configuration::updateValue('BT_PARTIAL_SHIPMENT_STATE', (int) $order_state->id);
return true;
}
return true;
}
}
private function installOrderCompleteStatus()
{
if (!Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE')) {
$order_state = new OrderState();
$order_state->name = array();
foreach (Language::getLanguages() as $language) {
switch (Tools::strtolower($language['iso_code'])) {
case 'fr':
$order_state->name[$language['id_lang']] = 'Expédition complète';
break;
case 'it':
$order_state->name[$language['id_lang']] = 'Completa spedizione';
break;
case 'es':
$order_state->name[$language['id_lang']] = 'Completa de envío';
break;
case 'pt':
$order_state->name[$language['id_lang']] = 'Envio completa';
break;
case 'br':
$order_state->name[$language['id_lang']] = 'Envio completa';
break;
case 'de':
$order_state->name[$language['id_lang']] = 'Kompletter Versand';
break;
case 'en':
$order_state->name[$language['id_lang']] = 'Complete shipment';
break;
default:
$order_state->name[$language['id_lang']] = 'Complete shipment';
break;
}
}
$order_state->send_email = false;
$order_state->color = '#c7ff65';
$order_state->hidden = true;
$order_state->delivery = false;
$order_state->logable = true;
$order_state->invoice = false;
$order_state->paid = false;
if ($order_state->save()) {
if (version_compare(_PS_VERSION_, '1.5.4.1', '>')) {
Tools::copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
} else {
$this->copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
}
} else {
return false;
}
Configuration::updateValue('BT_PARTIAL_SHIPMENT_COMPLETE', (int) $order_state->id);
return true;
} else {
$order_state = new OrderState((int) Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE'));
if (!Validate::isLoadedObject($order_state)) {
$order_state = new OrderState();
$order_state->name = array();
foreach (Language::getLanguages() as $language) {
switch (Tools::strtolower($language['iso_code'])) {
case 'fr':
$order_state->name[$language['id_lang']] = 'Expédition complète';
break;
case 'it':
$order_state->name[$language['id_lang']] = 'Completa spedizione';
break;
case 'es':
$order_state->name[$language['id_lang']] = 'Completa de envío';
break;
case 'pt':
$order_state->name[$language['id_lang']] = 'Envio completa';
break;
case 'br':
$order_state->name[$language['id_lang']] = 'Envio completa';
break;
case 'de':
$order_state->name[$language['id_lang']] = 'Kompletter Versand';
break;
case 'en':
$order_state->name[$language['id_lang']] = 'Complete shipment';
break;
default:
$order_state->name[$language['id_lang']] = 'Complete shipment';
break;
}
}
$order_state->send_email = false;
$order_state->color = '#c7ff65';
$order_state->hidden = true;
$order_state->delivery = false;
$order_state->logable = true;
$order_state->invoice = true;
if ($order_state->save()) {
if (version_compare(_PS_VERSION_, '1.5.4.1', '>')) {
Tools::copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
} else {
$this->copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
}
} else {
return false;
}
Configuration::updateValue('BT_PARTIAL_SHIPMENT_COMPLETE', (int) $order_state->id);
return true;
}
return true;
}
}
private function installOrderRemainingStatus()
{
if (!Configuration::get('BT_PARTIAL_REMAINING_STATE')) {
$order_state = new OrderState();
$order_state->name = array();
foreach (Language::getLanguages() as $language) {
switch (Tools::strtolower($language['iso_code'])) {
case 'fr':
$order_state->name[$language['id_lang']] = 'Reliquat de commande';
break;
case 'it':
$order_state->name[$language['id_lang']] = 'Resto dell\'ordine';
break;
case 'es':
$order_state->name[$language['id_lang']] = 'Pedido pendiente';
break;
case 'pt':
$order_state->name[$language['id_lang']] = 'Resto do pedido';
break;
case 'br':
$order_state->name[$language['id_lang']] = 'Resto do pedido';
break;
case 'de':
$order_state->name[$language['id_lang']] = 'Rest der Bestellung';
break;
case 'en':
$order_state->name[$language['id_lang']] = 'Remaining order (backorder)';
break;
default:
$order_state->name[$language['id_lang']] = 'Remaining order (backorder)';
break;
}
}
$order_state->send_email = false;
$order_state->color = '#F7DCF2';
$order_state->hidden = true;
$order_state->delivery = false;
$order_state->logable = true;
$order_state->invoice = false;
$order_state->paid = false;
if ($order_state->save()) {
if (version_compare(_PS_VERSION_, '1.5.4.1', '>')) {
Tools::copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
} else {
$this->copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
}
} else {
return false;
}
Configuration::updateValue('BT_PARTIAL_REMAINING_STATE', (int) $order_state->id);
return true;
} else {
$order_state = new OrderState((int) Configuration::get('BT_PARTIAL_REMAINING_STATE'));
if (!Validate::isLoadedObject($order_state)) {
$order_state = new OrderState();
$order_state->name = array();
foreach (Language::getLanguages() as $language) {
switch (Tools::strtolower($language['iso_code'])) {
case 'fr':
$order_state->name[$language['id_lang']] = 'Reliquat de commande';
break;
case 'it':
$order_state->name[$language['id_lang']] = 'Resto dell\'ordine';
break;
case 'es':
$order_state->name[$language['id_lang']] = 'Pedido pendiente';
break;
case 'pt':
$order_state->name[$language['id_lang']] = 'Resto do pedido';
break;
case 'br':
$order_state->name[$language['id_lang']] = 'Resto do pedido';
break;
case 'de':
$order_state->name[$language['id_lang']] = 'Rest der Bestellung';
break;
case 'en':
$order_state->name[$language['id_lang']] = 'Remaining order (backorder)';
break;
default:
$order_state->name[$language['id_lang']] = 'Remaining order (backorder)';
break;
}
}
$order_state->send_email = false;
$order_state->color = '#F7DCF2';
$order_state->hidden = true;
$order_state->delivery = false;
$order_state->logable = true;
$order_state->invoice = true;
if ($order_state->save()) {
if (version_compare(_PS_VERSION_, '1.5.4.1', '>')) {
Tools::copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
} else {
$this->copy(_PS_MODULE_DIR_.$this->name.'/logo.gif', dirname(__FILE__).'/../../img/os/'.(int) $order_state->id.'.gif');
}
} else {
return false;
}
Configuration::updateValue('BT_PARTIAL_REMAINING_STATE', (int) $order_state->id);
return true;
}
return true;
}
}
public function uninstall()
{
if (!parent::uninstall()) {
return false;
}
return true;
}
/*************************************************************************************************
DISPLAY BACK OFFICE MANAGEMENT
**************************************************************************************************/
/**
* Loads asset resources.
*/
public function loadAsset()
{
$css_compatibility = $js_compatibility = array();
/* Load CSS */
$css = array(
$this->css_path.'bootstrap-select.min.css',
$this->css_path.'DT_bootstrap.css',
$this->css_path.'fix.css',
);
if (version_compare(_PS_VERSION_, '1.6', '<')) {
$css_compatibility = array(
$this->css_path.'bootstrap.css',
$this->css_path.'bootstrap.extend.css',
$this->css_path.'bootstrap-responsive.min.css',
$this->css_path.'font-awesome.min.css',
$this->css_path.'back.1.5.css',
);
$css = array_merge($css_compatibility, $css);
}
$this->context->controller->addCSS($css, 'all');
unset($css, $css_compatibility);
$this->context->controller->addJquery();
/* Load JS */
$js = array(
$this->js_path.'bootstrap-select.min.js',
$this->js_path.'bootstrap-dialog.js',
$this->js_path.'jquery.autosize.min.js',
$this->js_path.'jquery.dataTables.js',
$this->js_path.'DT_bootstrap.js',
$this->js_path.'dynamic_table_init.js',
$this->js_path.'jscolor.js',
$this->js_path.'module.js',
);
if (version_compare(_PS_VERSION_, '1.6', '<')) {
$js_compatibility = array(
$this->js_path.'bootstrap.min.js',
);
$js = array_merge($js_compatibility, $js);
}
$this->context->controller->addJS($js);
/* Clean memory */
unset($js, $js_compatibility);
}
public function getContent()
{
$this->loadAsset();
/**
* If values have been submitted in the form, process.
*/
$smarty = $this->context->smarty;
$smarty->assign('module_dir', $this->_path);
$smarty->assign('update_msg', $this->postProcess());
$smarty->assign('bt_config_form', $this->renderForm());
$smarty->assign('version', $this->version);
if (Tools::isSubmit('btnSubmit')) {
$is_submit = 1;
} else {
$is_submit = 0;
}
$smarty->assign('is_submit', $is_submit);
return $this->display(__FILE__, 'views/templates/admin/configure.tpl');
}
private function postProcess()
{
if (Tools::isSubmit('submitBtModule')) {
$form_values = $this->getConfigFormValues();
$valid = true;
foreach (array_keys($form_values) as $key) {
if (!Configuration::updateValue($key, Tools::getValue($key))) {
$valid = false;
}
}
return $valid ? $this->displayConfirmation('Settings updated') : $this->displayError('Error on setttings update');
}
}
/**
* Create the form that will be displayed in the configuration of your module.
*/
protected function renderForm()
{
$helper = new HelperForm();
$helper->show_toolbar = false;
$helper->table = $this->table;
$helper->module = $this;
$helper->default_form_language = $this->context->language->id;
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0);
$helper->identifier = $this->identifier;
$helper->submit_action = 'submitBtModule';
$helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false)
.'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->tpl_vars = array(
'fields_value' => $this->getConfigFormValues(), /* Add values for your inputs */
'languages' => $this->context->controller->getLanguages(),
'id_language' => $this->context->language->id,
);
return $helper->generateForm(array($this->getConfigForm()));
}
/**
* Create the structure of your form.
*/
protected function getConfigForm()
{
$order_states = OrderState::getOrderStates($this->context->language->id);
array_unshift($order_states, array('id_order_state' => null, 'name' => $this->l('-- Select new status --')));
// 1.5 version doesn't include switch type
$bool_type = version_compare(_PS_VERSION_, '1.6', '<') ? 'radio' : 'switch';
return array(
'form' => array(
'legend' => array(
'title' => $this->l('Settings'),
'icon' => 'icon-cogs',
),
'input' => array(
array(
'type' => $bool_type,
'label' => $this->l('Send an email'),
'name' => 'BT_PARTIAL_SHIPMENT_SEND_EMAIL',
'is_bool' => true,
'class' => 't',
'desc' => $this->l('Send an email to your customer when you create partial shipment. This email contains delivery slip and tracking link.'),
'values' => array(
array(
'id' => 'active_on',
'value' => true,
'label' => $this->l('Enabled'),
),
array(
'id' => 'active_off',
'value' => false,
'label' => $this->l('Disabled'),
),
),
),
array(
'type' => 'select',
'label' => $this->l('New status (partial shipment):'),
'name' => 'BT_PARTIAL_SHIPMENT_STATE',
'required' => true,
'options' => array(
'query' => $order_states,
'id' => 'id_order_state',
'name' => 'name',
),
'desc' => $this->l('New status of your order when you create partial shipment without remaining order.'),
),
array(
'type' => 'select',
'label' => $this->l('New status (Complete shipment):'),
'name' => 'BT_PARTIAL_SHIPMENT_COMPLETE',
'required' => true,
'options' => array(
'query' => $order_states,
'id' => 'id_order_state',
'name' => 'name',
),
'desc' => $this->l('Update your order in this status if order is full shipment.'),
),
array(
'type' => $bool_type,
'label' => $this->l('Generate remaining order ?'),
'name' => 'BT_PARTIAL_GENERATE_REMAINING',
'is_bool' => true,
'class' => 't',
'desc' => $this->l('When you create partial shpiment do you want to generate remaining order by default. You can modifiy this information for each partial shipment.'),
'values' => array(
array(
'id' => 'active_on',
'value' => true,
'label' => $this->l('Enabled'),
),
array(
'id' => 'active_off',
'value' => false,
'label' => $this->l('Disabled'),
),
),
),
array(
'type' => 'select',
'label' => $this->l('Remaining order state:'),
'name' => 'BT_PARTIAL_REMAINING_STATE',
'required' => true,
'options' => array(
'query' => $order_states,
'id' => 'id_order_state',
'name' => 'name',
),
'desc' => $this->l('New status of your order when you create new order with state remaining order.'),
),
array(
'type' => $bool_type,
'label' => $this->l('Generate invoive ? (in general for B2B)'),
'name' => 'BT_PARTIAL_GENERATE_INVOICE',
'is_bool' => true,
'class' => 't',
'desc' => $this->l('If you chose to create remaining order do you want to create a new invoice. In general, this function is used for B2B (one order, one invoice). In B2C mode, there is one payment one invoice even if you create remaining order.'),
'values' => array(
array(
'id' => 'active_on',
'value' => true,
'label' => $this->l('Enabled'),
),
array(
'id' => 'active_off',
'value' => false,
'label' => $this->l('Disabled'),
),
),
),
),
'submit' => array(
'title' => $this->l('Save settings'),
),
),
);
}
/**
* Set values for the inputs.
*/
protected function getConfigFormValues()
{
return array(
'BT_PARTIAL_SHIPMENT_SEND_EMAIL' => Configuration::get('BT_PARTIAL_SHIPMENT_SEND_EMAIL'),
'BT_PARTIAL_SHIPMENT_STATE' => Configuration::get('BT_PARTIAL_SHIPMENT_STATE'),
'BT_PARTIAL_SHIPMENT_COMPLETE' => Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE'),
'BT_PARTIAL_REMAINING_STATE' => Configuration::get('BT_PARTIAL_REMAINING_STATE'),
'BT_PARTIAL_GENERATE_INVOICE' => Configuration::get('BT_PARTIAL_GENERATE_INVOICE'),
'BT_PARTIAL_GENERATE_REMAINING' => Configuration::get('BT_PARTIAL_GENERATE_REMAINING'),
);
}
public function hookDisplayAdminOrder($params)
{
if (!$this->active) {
return;
}
if (Tools::isSubmit('submitPartialShipment')) {
$this->processPartialShipment();
}
if (isset($params['id_order'])) {
$order = new Order((int)$params['id_order']);
if (Validate::isLoadedObject($order)) {
//We use this var to verify if there more than product to ship in this order
$shippableQuantity = 0;
$orderDetails = $order->getProducts();
if ($orderDetails) {
foreach ($orderDetails as &$orderDetail) {
if ($orderDetail['id_warehouse'] != 0) {
$warehouse = new Warehouse((int) $orderDetail['id_warehouse']);
if (Validate::isLoadedObject($warehouse)) {
$orderDetail['warehouse'] = $warehouse->name;
} else {
$orderDetail['warehouse'] = false;
}
} else {
$orderDetail['warehouse'] = false;
}
//We verify if this product order detail partial shipment
$shippedQuantity = PartialShipmentDetail::getQuantityShippiedByIdOrderDetail((int) $orderDetail['id_order_detail']);
$orderDetail['shippedQuantity'] = (int) $shippedQuantity;
$shippableQuantity += (int) $orderDetail['product_quantity'] - (int) $orderDetail['product_quantity_refunded'] - (int) $shippedQuantity;
$orderDetail['shippableQuantity'] = (int) $orderDetail['product_quantity'] - (int) $orderDetail['product_quantity_refunded'] - (int) $shippedQuantity;
if ($orderDetail['image'] != null) {
$name = 'product_mini_'.(int)$orderDetail['product_id'].(isset($orderDetail['product_attribute_id']) ? '_'.(int)$orderDetail['product_attribute_id'] : '').'.jpg';
// generate image cache, only for back office
$orderDetail['image_tag'] = ImageManager::thumbnail(_PS_IMG_DIR_.'p/'.$orderDetail['image']->getExistingImgPath().'.jpg', $name, 45, 'jpg');
if (file_exists(_PS_TMP_IMG_DIR_.$name)) {
$orderDetail['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name);
} else {
$orderDetail['image_size'] = false;
}
}
}
}
//We retrieve product partial shipment already exists for this order
$shipments = PartialShipment::getPartialShipmentByOrderId((int) $order->id);
if ($shipments) {
$partialShipment = array();
$i = 0;
foreach ($shipments as $shipment) {
$partialShipmentObj = new PartialShipment((int) $shipment['id_partial_shipment']);
if (Validate::isLoadedObject($partialShipmentObj)) {
$partialShipment[$i]['idPartial'] = $partialShipmentObj->id;
$partialShipment[$i]['trackingNumber'] = $partialShipmentObj->tracking_number;
$partialShipment[$i]['date'] = Tools::displayDate($partialShipmentObj->date_add);
$partialShipment[$i]['products'] = array();
$partialShipment[$i]['url'] = $this->getFrontUrl('order', (int) $partialShipmentObj->id);
$details = $partialShipmentObj->getPartialShipmentDetail();
if (is_array($details) && count($details) > 0) {
foreach ($details as &$detail) {
$orderDetailObj = new OrderDetail((int)$detail['id_order_detail']);
if (Validate::isLoadedObject($orderDetailObj)) {
$detail['product_name'] = $orderDetailObj->product_name;
}
}
}
$partialShipment[$i]['products'] = $details;
unset($details);
$i++;
}
}
} else {
if ($order->hasBeenShipped()) {
//We inform e-merchant with data
$partialShipment = array();
$partialShipment[0]['idPartial'] = $order->delivery_number;
//We retrieve order carrier data
$idOrderCarrier = (int)Db::getInstance()->getValue('
SELECT `id_order_carrier`
FROM `'._DB_PREFIX_.'order_carrier`
WHERE `id_order` = '.(int)$order->id);
if ($idOrderCarrier) {
$orderCarrier = new OrderCarrier((int) $idOrderCarrier);
if (Validate::isloadedObject($orderCarrier)) {
$partialShipment[0]['trackingNumber'] = $orderCarrier->tracking_number;
$partialShipment[0]['date'] = Tools::displayDate($orderCarrier->date_add);
$partialShipment[0]['products'] = array();
foreach ($orderDetails as $orderDetail) {
$partialShipment[0]['products'][] = array(
'product_name' => $orderDetail['product_name'],
'quantity' => $orderDetail['product_quantity'],
);
}
}
}
}
}
$this->context->smarty->assign(
array(
'orderDetails' => $orderDetails,
'order' => $order,
'id_order' => $order->id,
'shippableQuantity' => $shippableQuantity,
'partialShipment' => (isset($partialShipment) ? $partialShipment : false),
'generateRemaining' => Configuration::get('BT_PARTIAL_GENERATE_REMAINING'),
'generateInvoice' => Configuration::get('BT_PARTIAL_GENERATE_INVOICE'),
)
);
return $this->display(__FILE__, Tools::substr(_PS_VERSION_, 0, 3).'/admin_order.tpl');
} else {
return;
}
}
}
public function hookDisplayOrderDetail($params)
{
if (!$this->active) {
return;
}
$order = $params['order'];
if (Validate::isLoadedObject($order)) {
//We retrieve product partial shipment already exists for this order
$shipments = PartialShipment::getPartialShipmentByOrderId((int) $order->id);
//We retrieve carrier for this order
$carrier = new Carrier((int) $order->id_carrier);
if ($shipments) {
$partialShipment = array();
$i = 0;
foreach ($shipments as $shipment) {
$partialShipmentObj = new PartialShipment((int) $shipment['id_partial_shipment']);
if (Validate::isLoadedObject($partialShipmentObj)) {
$partialShipment[$i]['idPartial'] = $partialShipmentObj->id;
$partialShipment[$i]['trackingNumber'] = $partialShipmentObj->tracking_number;
$partialShipment[$i]['date'] = Tools::displayDate($partialShipmentObj->date_add);
$partialShipment[$i]['products'] = array();
$partialShipment[$i]['urlDelivery'] = $this->getFrontUrl('order', (int) $partialShipmentObj->id);
if (Validate::isLoadedObject($carrier)) {
$partialShipment[$i]['carrierUrl'] = $carrier->url;
}
$details = $partialShipmentObj->getPartialShipmentDetail();
if (is_array($details) && count($details) > 0) {
foreach ($details as &$detail) {
$orderDetailObj = new OrderDetail((int)$detail['id_order_detail']);
if (Validate::isLoadedObject($orderDetailObj)) {
$detail['product_name'] = $orderDetailObj->product_name;
}
}
}
$partialShipment[$i]['products'] = $details;
unset($details);
$i++;
}
}
}
if (isset($partialShipment)) {
$this->context->smarty->assign(
array(
'partialShipment' => (isset($partialShipment) ? $partialShipment : false),
)
);
return $this->display(__FILE__, Tools::substr(_PS_VERSION_, 0, 3).'/front_order_detail.tpl');
}
}
}
/**
* Add the CSS & JavaScript files you want to be loaded in the BO.
*/
public function hookDisplayBackOfficeHeader()
{
if (version_compare(_PS_VERSION_, '1.5.5.0', '>')) {
if ((isset(Context::getContext()->controller->controller_name)
&& preg_match('/AdminOrders/i', Context::getContext()->controller->controller_name))) {
$this->context->controller->addJquery();
$this->context->controller->addJS($this->js_path.'back.js');
$this->context->controller->addCSS($this->css_path.'back.css');
}
if (version_compare(_PS_VERSION_, '1.6', '<') && (isset(Context::getContext()->controller->controller_name)
&& preg_match('/AdminOrders/i', Context::getContext()->controller->controller_name))) {
$this->context->controller->addCSS($this->css_path.'back.1.5.css');
$this->context->controller->addJs($this->js_path.'bootstrap.min.js');
}
}
}
public function processPartialShipment()
{
if (!$this->active) {
return;
}
if (Tools::isSubmit('submitPartialShipment')) {
//We retrieve all field with shipped quantity
$qtyShipped = Tools::getValue('quantity_shipped');
$shippedProcess = false;
$partialShipment = false;
//Manage Partial Shipment with object
if (is_array($qtyShipped)) {
foreach ($qtyShipped as $key => $value) {
if ($value && $value > 0) {
$orderDetail = new OrderDetail((int) $key);
if (Validate::isLoadedObject($orderDetail)) {
//We verify if quantity Shipped <= as shippable quantity
$shippedQuantity = PartialShipmentDetail::getQuantityShippiedByIdOrderDetail((int) $orderDetail->id);
$shippableQty = (int) $orderDetail->product_quantity - (int) $orderDetail->product_quantity_refunded - (int) $shippedQuantity;
if ($shippableQty >= (int) $value) {
if (!$partialShipment || !Validate::isLoadedObject($partialShipment)) {
//We create Partial Shipment object
$partialShipment = new PartialShipment();
$partialShipment->tracking_number = pSQL(Tools::getValue('trackingNumber'));
$partialShipment->id_order = (int) $orderDetail->id_order;
$partialShipment->save();
}
if (Validate::isLoadedObject($partialShipment)) {
//We create partial Shipment Detail
$partialShipmentDetail = new PartialShipmentDetail();
$partialShipmentDetail->id_order_detail = (int) $orderDetail->id;
$partialShipmentDetail->id_partial_shipment = (int) $partialShipment->id;
$partialShipmentDetail->quantity = (int) $value;
$partialShipmentDetail->save();
$shippedProcess = true;
}
}
}
}
}
//We verify if order is full shipped
$order = new Order((int) Tools::getValue('id_order'));
$order->shipping_number = Tools::getValue('trackingNumber');
if (Validate::isLoadedObject($order) && $shippedProcess) {
//We use this var to verify if there more than product to ship in this order
$totalShippableQuantity = 0;
$totalQtyShipped = 0;
$orderDetails = $order->getProducts();
$carrier = new Carrier((int) $order->id_carrier);
if ($orderDetails) {
foreach ($orderDetails as &$orderDetail) {
//We verify if this product order detail partial shipment
$shippedQuantity = PartialShipmentDetail::getQuantityShippiedByIdOrderDetail((int) $orderDetail['id_order_detail']);
$totalQtyShipped += (int) $shippedQuantity;
$totalShippableQuantity += (int) $orderDetail['product_quantity'] - (int) $orderDetail['product_quantity_refunded'] - (int) $shippedQuantity;
}
}
if (Configuration::get('BT_PARTIAL_SHIPMENT_STATE') && $totalShippableQuantity > 0 && $order->current_state != Configuration::get('BT_PARTIAL_SHIPMENT_STATE') && !Tools::getValue('remainingOrder')) {
if ($order->current_state != Configuration::get('BT_PARTIAL_SHIPMENT_STATE')) {
//We Update status
$new_history = new OrderHistory();
$new_history->id_order = (int) $order->id;
$new_history->changeIdOrderState((int) Configuration::get('BT_PARTIAL_SHIPMENT_STATE'), (int) $order->id);
$new_history->add();
}
}
if ((Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE') && $totalShippableQuantity <= 0 && $order->current_state != Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE')) || Tools::getValue('remainingOrder')) {
if ($order->current_state != Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE')) {
//We Update status
$new_history = new OrderHistory();
$new_history->id_order = (int) $order->id;
$new_history->changeIdOrderState((int) Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE'), (int) $order->id);
$new_history->add();
}
}
}
//Manage inform customer
//We retrieve data of this order
$customer = new Customer((int) $order->id_customer);
if ($shippedProcess && Configuration::get('BT_PARTIAL_SHIPMENT_SEND_EMAIL') && Validate::isLoadedObject($order) && $order->current_state != Configuration::get('BT_PARTIAL_SHIPMENT_COMPLETE')) {
//We retrieve all order detail shipped in this process
if (isset($partialShipment) && Validate::isLoadedObject($partialShipment)) {
if (Validate::isLoadedObject($customer)) {
$iso = Language::getIsoById((int) $customer->id_lang);
switch ($iso) {
case 'fr':
$subject = $this->l('Votre commande est expédiée partiellement');
break;
case 'es':
$subject = $this->l('Su pedido se envía parcialmente');
break;
case 'it':
$subject = $this->l('Il vostro ordine viene spedito parzialmente');
break;
case 'pt':
$subject = $this->l('Sua ordem é enviada parcialmente');
break;
case 'de':
$subject = $this->l('Ihre Bestellung wird ausgeliefert teilweise');
break;
case 'en':
$subject = $this->l('You order was partialy shipped out');
break;
default:
$subject = $this->l('You order was partialy shipped out');
$iso = 'en';
break;
}
$template_vars = array(
'{followup}' => str_replace('@', $order->shipping_number, $carrier->url),
'{firstname}' => $customer->firstname,
'{lastname}' => $customer->lastname,
'{id_order}' => $order->id,
'{shipping_number}' => $order->shipping_number,
'{order_name}' => $order->getUniqReference(),
);
$template = 'partialshipment';
$txt_file = dirname(__FILE__).'/mails/'.$iso.'/'.$template.'.txt';
$html_file = dirname(__FILE__).'/mails/'.$iso.'/'.$template.'.html';
$file_attachement = array();
$pdf = new PDF((object)$partialShipment, 'PartialShipment', Context::getContext()->smarty);
$file_attachement[] = array(
'content' => $pdf->render(false),
'name' => 'BL_'.sprintf('%06d', (int) $partialShipment->id).'.pdf',
'mime' => 'application/pdf',
);
if (file_exists($txt_file) && file_exists($html_file)) {
Mail::Send(
(int) $order->id_lang,
$template,
$subject,
$template_vars,
$customer->email,
null,
Configuration::get('PS_SHOP_EMAIL'),
Configuration::get('PS_SHOP_NAME'),
$file_attachement,
null,
dirname(__FILE__).'/mails/'
);
}
}
}
} else {
$this->displayError('Error during partial shipment process.');
}
//We verify if you create remaining order
if ($partialShipment && Validate::isLoadedObject($partialShipment) && $shippedProcess) {
if (Tools::getValue('remainingOrder') && $totalShippableQuantity > 0) {
$newOrder = $partialShipment->cloneOrderObject();
if (Validate::isLoadedObject($newOrder)) {
if (Tools::getValue('generateNewInvoice')) {
$newOrder->invoice_number = 0;
$newOrder->save();
}
if (is_array($qtyShipped)) {
$validQtyShipped = false;
foreach ($qtyShipped as $key => $value) {
$orderDetail = new OrderDetail((int) $key);
if (Validate::isLoadedObject($orderDetail)) {
if ($orderDetail->product_quantity - $orderDetail->product_quantity_refunded > (int) $value) {
if ($partialShipment->modifyOrderDetail($newOrder, $orderDetail, (int) $value, Tools::getValue('generateNewInvoice'))) {
$validQtyShipped = true;
}
}
}
}
//We refresh order Object after modify origibal object
$order = new Order((int) $partialShipment->id_order);
$newOrder = new Order((int) $newOrder->id);
$total_discounts = $order->total_discounts;
$total_discounts_tax_incl = $order->total_discounts_tax_incl;
$total_discounts_tax_excl = $order->total_discounts_tax_excl;
if (isset($total_discounts) && $total_discounts) {
$order->total_discounts = round($total_discounts * $order->total_products_wt / ($order->total_products_wt + $newOrder->total_products_wt), 2);
$order->total_discounts_tax_incl = round($total_discounts_tax_incl * $order->total_products_wt / ($order->total_products_wt + $newOrder->total_products_wt), 2);
$order->total_discounts_tax_excl = round($total_discounts_tax_excl * $order->total_products / ($order->total_products + $newOrder->total_products), 2);
$newOrder->total_discounts = round($total_discounts - $order->total_discounts, 2);
$newOrder->total_discounts_tax_incl = round($total_discounts_tax_incl - $order->total_discounts_tax_incl, 2);
$newOrder->total_discounts_tax_excl = round($total_discounts_tax_excl - $order->total_discounts_tax_excl, 2);
$order->total_paid_tax_incl += $newOrder->total_discounts_tax_incl;
$order->total_paid_tax_excl += $newOrder->total_discounts_tax_excl;
$order->total_paid += $newOrder->total_discounts_tax_incl;
if ($order->total_paid_real > 0) {
$order->total_paid_real += $newOrder->total_discounts_tax_incl;
}
$order->save();
$newOrder->total_paid_tax_incl -= $newOrder->total_discounts_tax_incl;
$newOrder->total_paid_tax_excl -= $newOrder->total_discounts_tax_excl;
$newOrder->total_paid -= $newOrder->total_discounts_tax_incl;
if ($newOrder->total_paid_real > 0) {
$newOrder->total_paid_real -= $newOrder->total_discounts_tax_incl;
}
$newOrder->save();
}
//We fix Order Parent Order Invoice if you generate new invoice
if (Tools::getValue('generateNewInvoice')) {
$sql = 'SELECT `id_order_invoice`
FROM `'._DB_PREFIX_.'order_invoice`
WHERE number = '.(int) $order->invoice_number.'
ORDER BY `id_order` ASC';
$id_order_invoice = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
if ($id_order_invoice) {
$orderInvoice = new OrderInvoice((int) $id_order_invoice);
if (Validate::isLoadedObject($orderInvoice)) {
$orderInvoice->total_discount_tax_incl -= $newOrder->total_discounts_tax_incl;
$orderInvoice->total_discount_tax_excl -= $newOrder->total_discounts_tax_excl;
$orderInvoice->total_paid_tax_incl -= $newOrder->total_paid_tax_incl;
$orderInvoice->total_paid_tax_excl -= $newOrder->total_paid_tax_excl;
$orderInvoice->total_products -= $newOrder->total_products;
$orderInvoice->total_products_wt -= $newOrder->total_products_wt;
$orderInvoice->save();
}
}
}
if ($validQtyShipped) {
// Create new OrderHistory
$history = new OrderHistory();
$history->id_order = $newOrder->id;
$history->id_employee = (int) $this->context->employee->id;
if ($order->hasInvoice() && Tools::getValue('generateNewInvoice')) {
$newOrder->setInvoice(true);
$useExistingsPayment = true;
} else {
$useExistingsPayment = false;
}
$currentState = $newOrder->getCurrentOrderState();
if (Validate::isLoadedObject($currentState)) {
if ($currentState->id != (int) Configuration::get('BT_PARTIAL_REMAINING_STATE')) {
$history->changeIdOrderState(Configuration::get('BT_PARTIAL_REMAINING_STATE'), $newOrder, $useExistingsPayment);
$history->add();
}
}
}
}
} else {
$this->displayError('Error during during remaining order creation.');
}
}
}
//We update order_carrier
if (Tools::getValue('trackingNumber')) {
$id_order_carrier = (int)Db::getInstance()->getValue('
SELECT `id_order_carrier`
FROM `'._DB_PREFIX_.'order_carrier`
WHERE `id_order` = '.(int) $order->id);
if ($id_order_carrier) {
$order_carrier = new OrderCarrier((int) $id_order_carrier);
if (Validate::isloadedObject($order_carrier)) {
$order->shipping_number = Tools::getValue('trackingNumber');
$order->update();
// Update order_carrier
$order_carrier->tracking_number = pSQL(Tools::getValue('trackingNumber'));
if ($order_carrier->update()) {
Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order, 'customer' => $customer, 'carrier' => $carrier), null, false, true, false, (int) $order->id_shop);
}
}
}
}
} else {
$this->displayError('Error during partial shipment process.');
}
Tools::redirectAdmin('index.php?controller=AdminOrders&id_order='.
(int) Tools::getValue('id_order').'&vieworder&conf=4&token='.Tools::getValue('token'));
}
}
public function generatePartialPDF()
{
if (Tools::getValue('idPartialShipment')) {
$partialShipment = new PartialShipment((int) Tools::getValue('idPartialShipment'));
if (Validate::isLoadedObject($partialShipment)) {
$pdf = new PDF((object)$partialShipment, 'PartialShipment', Context::getContext()->smarty);
$pdf->render();
} else {
$this->displayError('Error with PartialShipment Object.');
}
} else {
$this->displayError('No delivery slip found.');
}
}
private function getFrontUrl($action, $idPartialShipment)
{
$token = Tools::getAdminToken('btpartialshipment');
$use_ssl = (bool)Configuration::get('PS_SSL_ENABLED');
$query = array(
'ajax' => true,
'action' => $action,
'idPartialShipment' => $idPartialShipment,
'token' => $token
);
return $this->context->link->getModuleLink($this->name, 'generateDeliverySlip', $query, $use_ssl);
}
}