diff --git a/ajax/backend/shippingStatus/create.php b/ajax/backend/shippingStatus/create.php new file mode 100644 index 0000000000000000000000000000000000000000..1320b63b9b95e57a9817543d46cfc78f11c370a4 --- /dev/null +++ b/ajax/backend/shippingStatus/create.php @@ -0,0 +1,34 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_create + */ + +use QUI\ERP\Shipping\ShippingStatus\Factory; +use QUI\ERP\Shipping\ShippingStatus\Handler; +use QUI\Utils\Security\Orthos; + +/** + * Create a new shipping status + * + * @param int $id - ShippingStatus ID + * @param string $color - hex color code + * @param array $title - (multilignual) titel + * @param bool $notification - send auto-notification on status change + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_create', + function ($id, $color, $title, $notification) { + $id = (int)$id; + + Factory::getInstance()->createShippingStatus( + $id, + Orthos::clear($color), + Orthos::clearArray(\json_decode($title, true)) + ); + + Handler::getInstance()->setShippingStatusNotification($id, \boolval($notification)); + }, + ['id', 'color', 'title', 'notification'], + 'Permission::checkAdminUser' +); diff --git a/ajax/backend/shippingStatus/delete.php b/ajax/backend/shippingStatus/delete.php new file mode 100644 index 0000000000000000000000000000000000000000..91946c4abf373b5edb823e598510c2aa023f314f --- /dev/null +++ b/ajax/backend/shippingStatus/delete.php @@ -0,0 +1,21 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_delete + */ + +use QUI\ERP\Shipping\ShippingStatus\Handler; + +/** + * Delete a shipping status + * + * @param int $id + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_delete', + function ($id) { + Handler::getInstance()->deleteShippingStatus($id); + }, + ['id'], + 'Permission::checkAdminUser' +); diff --git a/ajax/backend/shippingStatus/get.php b/ajax/backend/shippingStatus/get.php new file mode 100644 index 0000000000000000000000000000000000000000..21ba9141aeef215b16d0c5186658cbb2e895e5eb --- /dev/null +++ b/ajax/backend/shippingStatus/get.php @@ -0,0 +1,19 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_get + */ + +use QUI\ERP\Shipping\ShippingStatus\Handler; + +/** + * Create a new shipping status + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_get', + function ($id) { + return Handler::getInstance()->getShippingStatus($id)->toArray(); + }, + ['id'], + 'Permission::checkAdminUser' +); diff --git a/ajax/backend/shippingStatus/getNextId.php b/ajax/backend/shippingStatus/getNextId.php new file mode 100644 index 0000000000000000000000000000000000000000..1fdb47d00b4163cb3dc22f70ef3abec8f61fd4f7 --- /dev/null +++ b/ajax/backend/shippingStatus/getNextId.php @@ -0,0 +1,19 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_getNextId + */ + +use QUI\ERP\Shipping\ShippingStatus\Factory; + +/** + * Return next available ID + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_getNextId', + function () { + return Factory::getInstance()->getNextId(); + }, + false, + 'Permission::checkAdminUser' +); diff --git a/ajax/backend/shippingStatus/getNotificationText.php b/ajax/backend/shippingStatus/getNotificationText.php new file mode 100644 index 0000000000000000000000000000000000000000..c5d8562473dc10211ad68bfc6c8fb5776859f20b --- /dev/null +++ b/ajax/backend/shippingStatus/getNotificationText.php @@ -0,0 +1,32 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_getNotificationText + */ + +use QUI\ERP\Shipping\ShippingStatus\Handler; +use QUI\ERP\Order\Handler as OrderHandler; + +/** + * Get status change notification text for a specific order + * + * @param int $id - Shipping Status ID + * @param int $orderId - Order ID + * @return string + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_getNotificationText', + function ($id, $orderId) { + try { + $Order = OrderHandler::getInstance()->get($orderId); + + return Handler::getInstance()->getShippingStatus($id)->getStatusChangeNotificationText($Order); + } catch (\Exception $Exception) { + QUI\System\Log::writeException($Exception); + + return ''; + } + }, + ['id', 'orderId'], + 'Permission::checkAdminUser' +); diff --git a/ajax/backend/shippingStatus/list.php b/ajax/backend/shippingStatus/list.php new file mode 100644 index 0000000000000000000000000000000000000000..0c2c0baaaa5bfb6340ee311682d97b6dabbae3d3 --- /dev/null +++ b/ajax/backend/shippingStatus/list.php @@ -0,0 +1,38 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_list + */ + +use QUI\ERP\Shipping\ShippingStatus\Handler; + +/** + * Returns shipping status list for a grid + * + * @return array + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_list', + function () { + $Grid = new QUI\Utils\Grid(); + $Handler = Handler::getInstance(); + + $list = $Handler->getShippingStatusList(); + $result = \array_map(function ($Status) { + /* @var $Status \QUI\ERP\Shipping\ShippingStatus\Status */ + return $Status->toArray(QUI::getLocale()); + }, $list); + + \usort($result, function ($a, $b) { + if ($a['id'] == $b['id']) { + return 0; + } + + return $a['id'] > $b['id'] ? 1 : -1; + }); + + return $Grid->parseResult($result, \count($result)); + }, + false, + 'Permission::checkAdminUser' +); diff --git a/ajax/backend/shippingStatus/update.php b/ajax/backend/shippingStatus/update.php new file mode 100644 index 0000000000000000000000000000000000000000..1d447c8679508189e03a52496a5ac83e4091609f --- /dev/null +++ b/ajax/backend/shippingStatus/update.php @@ -0,0 +1,34 @@ +<?php + +/** + * This file contains package_quiqqer_shipping_ajax_backend_shippingStatus_update + */ + +use QUI\ERP\Shipping\ShippingStatus\Handler; +use QUI\Utils\Security\Orthos; + +/** + * Update a shipping status + * + * @param int $id - Shipping Status ID + * @param string $color - hex color code + * @param array $title - (multilingual) title + * @param bool $notification - send auto-notification on status change + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_shipping_ajax_backend_shippingStatus_update', + function ($id, $color, $title, $notification) { + $id = (int)$id; + $Handler = Handler::getInstance(); + + $Handler->updateShippingStatus( + $id, + Orthos::clear($color), + Orthos::clearArray(\json_decode($title, true)) + ); + + $Handler->setShippingStatusNotification($id, \boolval($notification)); + }, + ['id', 'color', 'title', 'notification'], + 'Permission::checkAdminUser' +); diff --git a/bin/backend/ShippingStatus.js b/bin/backend/ShippingStatus.js new file mode 100644 index 0000000000000000000000000000000000000000..c1de3dbcbfc50cc65d3d287c67a9a9d4a878bafa --- /dev/null +++ b/bin/backend/ShippingStatus.js @@ -0,0 +1,13 @@ +/** + * @module package/quiqqer/shipping/bin/ShippingStatus + * + * Main instance of the shipping status handler + * + * @require package/quiqqer/shipping/bin/backend/classes/ShippingStatus + */ +define('package/quiqqer/shipping/bin/backend/ShippingStatus', [ + 'package/quiqqer/shipping/bin/backend/classes/ShippingStatus' +], function (ShippingStatus) { + "use strict"; + return new ShippingStatus(); +}); diff --git a/bin/backend/classes/ShippingStatus.js b/bin/backend/classes/ShippingStatus.js new file mode 100644 index 0000000000000000000000000000000000000000..010d3adc881b91e6ed795e9575f01335cd5d8e06 --- /dev/null +++ b/bin/backend/classes/ShippingStatus.js @@ -0,0 +1,161 @@ +/** + * @module package/quiqqer/shipping/bin/backend/classes/ShippingStatus + * @author www.pcsg.de (Henning Leutz) + */ +define('package/quiqqer/shipping/bin/backend/classes/ShippingStatus', [ + + 'qui/QUI', + 'qui/classes/DOM', + 'Ajax' + +], function (QUI, QUIDOM, QUIAjax) { + "use strict"; + + return new Class({ + + Extends: QUIDOM, + Type : 'package/quiqqer/shipping/bin/backend/classes/ShippingStatus', + + initialize: function (options) { + this.parent(options); + }, + + /** + * Return the processing status list for a grid + * + * @return {Promise} + */ + getList: function () { + return new Promise(function (resolve, reject) { + QUIAjax.get('package_quiqqer_shipping_ajax_backend_shippingStatus_list', resolve, { + 'package': 'quiqqer/shipping', + onError : reject + }); + }); + }, + + /** + * Return next available ID + * + * @return {Promise} + */ + getNextId: function () { + return new Promise(function (resolve, reject) { + QUIAjax.get('package_quiqqer_shipping_ajax_backend_shippingStatus_getNextId', resolve, { + 'package': 'quiqqer/shipping', + onError : reject + }); + }); + }, + + /** + * Create a new processing status + * + * @param {String|Number} id - Processing Status ID + * @param {String} color + * @param {Object} title - {de: '', en: ''} + * @param {Boolean} notification + * @return {Promise} + */ + createShippingStatus: function (id, color, title, notification) { + return new Promise(function (resolve, reject) { + QUIAjax.post('package_quiqqer_shipping_ajax_backend_shippingStatus_create', function (result) { + require([ + 'package/quiqqer/translator/bin/Translator' + ], function (Translator) { + Translator.refreshLocale().then(function () { + resolve(result); + }); + }); + }, { + 'package' : 'quiqqer/shipping', + id : id, + color : color, + title : JSON.encode(title), + notification: notification ? 1 : 0, + onError : reject + }); + }); + }, + + /** + * Delete a processing status + * + * @param {String|Number} id - Processing Status ID + * @return {Promise} + */ + deleteShippingStatus: function (id) { + return new Promise(function (resolve, reject) { + QUIAjax.post('package_quiqqer_shipping_ajax_backend_shippingStatus_delete', function () { + require([ + 'package/quiqqer/translator/bin/Translator' + ], function (Translator) { + Translator.refreshLocale().then(function () { + resolve(); + }); + }); + }, { + 'package': 'quiqqer/shipping', + id : id, + onError : reject + }); + }); + }, + + /** + * Return the status data + * + * @param {String|Number} id - Processing Status ID + * @return {Promise} + */ + getShippingStatus: function (id) { + return new Promise(function (resolve, reject) { + QUIAjax.post('package_quiqqer_shipping_ajax_backend_shippingStatus_get', resolve, { + 'package': 'quiqqer/shipping', + id : id, + onError : reject + }); + }); + }, + + /** + * Return the status data + * + * @param {String|Number} id - Processing Status ID + * @param {String} color + * @param {Object} title - {de: '', en: ''} + * @param {Boolean} notification + * @return {Promise} + */ + updateShippingStatus: function (id, color, title, notification) { + return new Promise(function (resolve, reject) { + QUIAjax.post('package_quiqqer_shipping_ajax_backend_shippingStatus_update', resolve, { + 'package' : 'quiqqer/shipping', + id : id, + color : color, + title : JSON.encode(title), + onError : reject, + notification: notification ? 1 : 0 + }); + }); + }, + + /** + * Get status change notification text for a specific shipping + * + * @param {Number} id - ShippingStatus ID + * @param {Number} shippingId - shipping ID + * @return {Promise} + */ + getNotificationText: function (id, shippingId) { + return new Promise(function (resolve, reject) { + QUIAjax.get('package_quiqqer_shipping_ajax_backend_shippingStatus_getNotificationText', resolve, { + 'package' : 'quiqqer/shipping', + id : id, + shippingId: shippingId, + onError : reject + }); + }); + } + }); +}); diff --git a/bin/backend/controls/settings/ShippingStatus.css b/bin/backend/controls/settings/ShippingStatus.css new file mode 100644 index 0000000000000000000000000000000000000000..13822df1f79c35f9bd73ca46c9ffff1b8940b683 --- /dev/null +++ b/bin/backend/controls/settings/ShippingStatus.css @@ -0,0 +1,27 @@ + +.quiqqer-shipping-shipping-status-window table { + border: none; +} + +.quiqqer-shipping-shipping-status-window td { + padding: 8px 0; +} + +.quiqqer-order-shipping-status-window [type="color"] { + padding: 0; + height: 31px; + border: none; +} + +.quiqqer-shipping-shipping-status-color { + display: block; + left: -5px; + line-height: 27px; + padding: 0 0 0 5px; + position: relative; + width: calc(100% + 5px); +} + +.quiqqer-shipping-shipping-status-window input[name="notification"] { + flex: 0; +} diff --git a/bin/backend/controls/settings/ShippingStatus.html b/bin/backend/controls/settings/ShippingStatus.html new file mode 100644 index 0000000000000000000000000000000000000000..68a0f95e3ebd0e183ecdb00d9edfa13cedef5838 --- /dev/null +++ b/bin/backend/controls/settings/ShippingStatus.html @@ -0,0 +1,51 @@ +<form> + <table class="data-table data-table-flexbox"> + <tbody> + <tr> + <td> + <label class="field-container"> + <span class="field-container-item" title=""> + {{labelTitle}} + </span> + <input name="title" data-qui="controls/lang/InputMultiLang"/> + </label> + </td> + </tr> + <tr> + <td> + <label class="field-container"> + <span class="field-container-item" title=""> + {{labelStatusNo}} + </span> + <input type="number" name="id" min="0" class="field-container-field"/> + </label> + </td> + </tr> + <tr> + <td> + <label class="field-container"> + <span class="field-container-item" title=""> + {{labelColor}} + </span> + <input type="color" name="color" class="field-container-field"/> + </label> + </td> + </tr> + <tr> + <td> + <label class="field-container"> + <span class="field-container-item" title=""> + {{labelNotification}} + </span> + <span class="field-container-field"> + <input type="checkbox" name="notification"/> + </span> + </label> + <div class="field-container-item-desc"> + {{{descNotification}}} + </div> + </td> + </tr> + </tbody> + </table> +</form> \ No newline at end of file diff --git a/bin/backend/controls/settings/ShippingStatus.js b/bin/backend/controls/settings/ShippingStatus.js new file mode 100644 index 0000000000000000000000000000000000000000..3d5adc9f6fe0cf67c789798ebf134f5db4e3443c --- /dev/null +++ b/bin/backend/controls/settings/ShippingStatus.js @@ -0,0 +1,431 @@ +/** + * @module package/quiqqer/shipping/bin/backend/controls/settings/ShippingStatus + * @author www.pcsg.de (Henning Leutz) + */ +define('package/quiqqer/shipping/bin/backend/controls/settings/ShippingStatus', [ + + 'qui/QUI', + 'qui/controls/Control', + 'qui/controls/windows/Confirm', + 'package/quiqqer/shipping/bin/backend/ShippingStatus', + 'controls/grid/Grid', + 'Locale', + 'Mustache', + + 'text!package/quiqqer/shipping/bin/backend/controls/settings/ShippingStatus.html', + 'css!package/quiqqer/shipping/bin/backend/controls/settings/ShippingStatus.css' + +], function (QUI, QUIControl, QUIConfirm, ShippingStatus, Grid, QUILocale, Mustache, template) { + "use strict"; + + var lg = 'quiqqer/shipping'; + + return new Class({ + + Extends: QUIControl, + Type : 'package/quiqqer/shipping/bin/backend/controls/settings/ShippingStatus', + + Binds: [ + '$onChange', + '$onImport', + 'refresh', + '$refreshButtonStatus', + 'openCreateDialog', + 'openDeleteDialog', + '$onEditClick', + '$onDeleteClick' + ], + + initialize: function (options) { + this.parent(options); + + this.$Elm = null; + this.$Input = null; + this.$Grid = null; + + this.addEvents({ + onImport: this.$onImport + }); + }, + + /** + * Refresh + */ + refresh: function () { + var self = this; + + ShippingStatus.getList().then(function (result) { + for (var i = 0, len = result.data.length; i < len; i++) { + result.data[i].colorNode = new Element('span', { + html : result.data[i].color, + 'class': 'quiqqer-shipping-shipping-status-color', + styles : { + backgroundColor: result.data[i].color + } + }); + + result.data[i].notificationStatus = new Element('span', { + html: result.data[i].notification ? + '<span class="fa fa-check"></span>' : + '<span class="fa fa-close"></span>' + }); + } + + self.$Grid.setData(result); + self.$refreshButtonStatus(); + }); + }, + + /** + * resize the grid + */ + resize: function () { + this.$Grid.setWidth( + this.$Elm.getSize().x + ); + }, + + /** + * event: on import + */ + $onImport: function () { + this.$Input = this.getElm(); + this.$Elm = new Element('div').wraps(this.$Input); + + this.$Elm.setStyles({ + width: '100%' + }); + + var w = this.$Elm.getSize().x; + + var Container = new Element('div', { + styles: { + height: 300, + width : w + } + }).inject(this.$Elm); + + + this.$Grid = new Grid(Container, { + height : 300, + width : w, + buttons : [{ + name : 'add', + text : QUILocale.get('quiqqer/system', 'add'), + events: { + onClick: this.openCreateDialog + } + }, { + type: 'separator' + }, { + name : 'edit', + text : QUILocale.get('quiqqer/system', 'edit'), + disabled: true, + events : { + onClick: this.$onEditClick + } + }, { + name : 'delete', + text : QUILocale.get('quiqqer/system', 'remove'), + disabled: true, + events : { + onClick: this.$onDeleteClick + } + }], + columnModel: [{ + header : QUILocale.get(lg, 'shippingStatus.grid.id'), + dataIndex: 'id', + dataType : 'integer', + width : 60 + }, { + header : QUILocale.get(lg, 'shippingStatus.grid.color'), + dataIndex: 'colorNode', + dataType : 'node', + width : 60 + }, { + header : QUILocale.get('quiqqer/system', 'title'), + dataIndex: 'title', + dataType : 'integer', + width : 200 + }, { + header : QUILocale.get(lg, 'shippingStatus.grid.notification'), + dataIndex: 'notificationStatus', + dataType : 'node', + width : 150 + }] + }); + + this.$Grid.addEvents({ + onRefresh : this.refresh, + onClick : this.$refreshButtonStatus, + onDblClick: this.$onEditClick + }); + + this.$Grid.refresh(); + this.resize(); + }, + + /** + * Refresh the grid button status (disabled/enabled) + */ + $refreshButtonStatus: function () { + var selected = this.$Grid.getSelectedIndices(); + + var Edit = this.$Grid.getButtons().filter(function (Button) { + return Button.getAttribute('name') === 'edit'; + })[0]; + + var Delete = this.$Grid.getButtons().filter(function (Button) { + return Button.getAttribute('name') === 'delete'; + })[0]; + + if (!selected.length) { + Edit.disable(); + Delete.disable(); + return; + } + + Edit.enable(); + Delete.enable(); + }, + + // region Dialogs + + /** + * Opens the add dialog + * - Create a Shipping Status + */ + openCreateDialog: function () { + var self = this; + + new QUIConfirm({ + icon : 'fa fa-plus', + title : QUILocale.get(lg, 'dialog.shippingStatus.create.title'), + maxHeight: 470, + maxWidth : 600, + autoclose: false, + events : { + onOpen: function (Win) { + var Content = Win.getContent(); + + Win.Loader.show(); + + var lgPrefix = 'dialog.shippingStatus.template.'; + + Content.addClass('quiqqer-shipping-shipping-status-window'); + Content.set('html', Mustache.render(template, { + labelTitle : QUILocale.get(lg, lgPrefix + 'labelTitle'), + labelStatusNo : QUILocale.get(lg, lgPrefix + 'labelStatusNo'), + labelColor : QUILocale.get(lg, lgPrefix + 'labelColor'), + labelNotification: QUILocale.get(lg, lgPrefix + 'labelNotification'), + descNotification : QUILocale.get(lg, lgPrefix + 'descNotification') + })); + + var Form = Content.getElement('form'); + + ShippingStatus.getNextId().then(function (nextId) { + Form.elements.id.value = nextId; + + return QUI.parse(Content); + }).then(function () { + Win.Loader.hide(); + }); + }, + + onSubmit: function (Win) { + Win.Loader.show(); + + var Form = Win.getContent().getElement('form'); + + require([ + 'qui/utils/Form', + 'package/quiqqer/shipping/bin/backend/ShippingStatus' + ], function (FormUtils, ShippingStatus) { + var data = FormUtils.getFormData(Form), + title = {}; + + try { + title = JSON.decode(data.title); + } catch (e) { + } + + ShippingStatus.createShippingStatus( + data.id, + data.color, + title, + data.notification.checked + ).then(function () { + return Win.close(); + }).then(function () { + self.refresh(); + }); + }); + } + } + }).open(); + }, + + /** + * Opens the dialog to edit a status + * + * @param {Number|String} statusId - ID of the Status + */ + openEditDialog: function (statusId) { + var self = this; + var data = this.$Grid.getData().filter(function (entry) { + return entry.id === statusId; + }); + + if (!data.length) { + return; + } + + data = data[0]; + + new QUIConfirm({ + icon : 'fa fa-edit', + title : QUILocale.get(lg, 'dialog.shippingStatus.edit.title'), + maxHeight: 470, + maxWidth : 600, + autoclose: false, + ok_button: { + text : QUILocale.get('quiqqer/quiqqer', 'edit'), + textimage: 'fa fa-edit' + }, + events : { + onOpen: function (Win) { + var Content = Win.getContent(); + + Win.Loader.show(); + + var lgPrefix = 'dialog.shippingStatus.template.'; + + Content.addClass('quiqqer-shipping-shipping-status-window'); + Content.set('html', Mustache.render(template, { + labelTitle : QUILocale.get(lg, lgPrefix + 'labelTitle'), + labelStatusNo : QUILocale.get(lg, lgPrefix + 'labelStatusNo'), + labelColor : QUILocale.get(lg, lgPrefix + 'labelColor'), + labelNotification: QUILocale.get(lg, lgPrefix + 'labelNotification'), + descNotification : QUILocale.get(lg, lgPrefix + 'descNotification') + })); + + var Form = Content.getElement('form'); + + ShippingStatus.getShippingStatus(data.id).then(function (details) { + Form.elements.id.value = details.id; + Form.elements.color.value = details.color; + Form.elements.title.value = JSON.encode(details.title); + Form.elements.notification.checked = details.notification; + + return QUI.parse(Content); + }).then(function () { + Win.Loader.hide(); + }); + }, + + onSubmit: function (Win) { + Win.Loader.show(); + + var Form = Win.getContent().getElement('form'); + + require([ + 'qui/utils/Form', + 'package/quiqqer/shipping/bin/backend/ShippingStatus' + ], function (FormUtils, ShippingStatus) { + var data = FormUtils.getFormData(Form), + title = {}; + + try { + title = JSON.decode(data.title); + } catch (e) { + } + + ShippingStatus.updateShippingStatus( + data.id, + data.color, + title, + data.notification + ).then(function () { + return Win.close(); + }).then(function () { + self.refresh(); + }); + }); + } + } + }).open(); + }, + + /** + * Opens the dialog to delete a status + * + * @param {Number|String} statusId - ID of the Status + */ + openDeleteDialog: function (statusId) { + var self = this; + var data = this.$Grid.getData().filter(function (entry) { + return entry.id === statusId; + }); + + if (!data.length) { + return; + } + + new QUIConfirm({ + icon : 'fa fa-trash', + texticon : 'fa fa-trash', + title : QUILocale.get(lg, 'dialog.shippingStatus.delete.title'), + text : QUILocale.get(lg, 'dialog.shippingStatus.delete.text'), + information: QUILocale.get(lg, 'dialog.shippingStatus.delete.information', { + id : data[0].id, + title: data[0].title + }), + maxHeight : 400, + maxWidth : 600, + autoclose : false, + ok_button : { + text : QUILocale.get('quiqqer/quiqqer', 'remove'), + textimage: 'fa fa-trash' + }, + events : { + onSubmit: function (Win) { + Win.Loader.show(); + + ShippingStatus.deleteShippingStatus(statusId).then(function () { + Win.close(); + self.refresh(); + }); + } + } + }).open(); + }, + + // endregion + + //region Buttons Events + + /** + * event : on edit click + */ + $onEditClick: function () { + var data = this.$Grid.getSelectedData(); + + if (data.length) { + this.openEditDialog(data[0].id); + } + }, + + /** + * event : on delete click + */ + $onDeleteClick: function () { + var data = this.$Grid.getSelectedData(); + + if (data.length) { + this.openDeleteDialog(data[0].id); + } + } + + // endregion + }); +}); diff --git a/locale.xml b/locale.xml index abe028a202a4e53edaa4e8cd4f9e8ed8582aa54b..26cb98b1a52230bf32bc86f3a1d958ef20afd948 100644 --- a/locale.xml +++ b/locale.xml @@ -247,7 +247,10 @@ <de><![CDATA[Jahre]]></de> <en><![CDATA[years]]></en> </locale> - + <locale name="shipping.settings.shippingStatus.title"> + <de><![CDATA[Versandstatus]]></de> + <en><![CDATA[Shipping status]]></en> + </locale> </groups> <groups name="quiqqer/shipping" datatype="php"> @@ -724,6 +727,82 @@ <en><![CDATA[Search shipping types]]></en> </locale> + <locale name="grid.shippingStatus"> + <de><![CDATA[Versandstatus]]></de> + <en><![CDATA[Shipping status]]></en> + </locale> + <locale name="shippingStatus.grid.id"> + <de><![CDATA[ID]]></de> + <en><![CDATA[ID]]></en> + </locale> + <locale name="shippingStatus.grid.color"> + <de><![CDATA[Farbe]]></de> + <en><![CDATA[Color]]></en> + </locale> + <locale name="shippingStatus.grid.notification"> + <de><![CDATA[Autom. Benachrichtigung]]></de> + <en><![CDATA[Auto notification]]></en> + </locale> + + <locale name="dialog.shippingStatus.create.title"> + <de><![CDATA[Versandstatus hinzufügen]]></de> + <en><![CDATA[Create shipping status]]></en> + </locale> + <locale name="dialog.shippingStatus.edit.title"> + <de><![CDATA[Versandstatus bearbeiten]]></de> + <en><![CDATA[Edit shipping status]]></en> + </locale> + + <locale name="dialog.shippingStatus.delete.title"> + <de><![CDATA[Versandstatus entfernen]]></de> + <en><![CDATA[Remove shipping status]]></en> + </locale> + <locale name="dialog.shippingStatus.delete.text"> + <de><![CDATA[Versandstatus wirklich entfernen?]]></de> + <en><![CDATA[Really remove shipping status?]]></en> + </locale> + <locale name="dialog.shippingStatus.delete.information" html="true"> + <de><![CDATA[ + Folgender Versandstatus wird entfernt:<br /> + <strong>#[id] - [title]</strong> + <br /><br /> + Der Versandstatus ist nicht wiederherstellbar. + ]]></de> + <en><![CDATA[ + The following shipping status will be removed: <br /> + <strong>#[id] - [title]</strong> + <br /><br /> + The shipping status is not recoverable. + ]]></en> + </locale> + <locale name="dialog.shippingStatus.template.labelTitle"> + <de><![CDATA[Titel]]></de> + <en><![CDATA[Title]]></en> + </locale> + <locale name="dialog.shippingStatus.template.labelStatusNo"> + <de><![CDATA[Status Nr.]]></de> + <en><![CDATA[Status no.]]></en> + </locale> + <locale name="dialog.shippingStatus.template.labelColor"> + <de><![CDATA[Farbe]]></de> + <en><![CDATA[Color]]></en> + </locale> + <locale name="dialog.shippingStatus.template.labelNotification"> + <de><![CDATA[Kunden benachrichtigen]]></de> + <en><![CDATA[Notify customer]]></en> + </locale> + <locale name="dialog.shippingStatus.template.descNotification" html="true"> + <de><![CDATA[ + Kunden sollen automatisch per E-Mail benachrichtigt werden, wenn der Versandstatus einer Bestellung + <b>automatisch</b> auf diesen Status geändert wird. Bei einer <b>manuellen Statusänderung</b> + wird vorher nochmal nachgefragt, ob eine Benachrichtigung erfolgen soll. + ]]></de> + <en><![CDATA[ + Customers should be automatically notified by e-mail when the status of an shipping status <b>automatically</b> + is changed to this status. In case of a <b>manual status change</b> you will be asked if you want + to send a notification.]]></en> + </locale> + </groups> <groups name="quiqqer/order"> @@ -737,4 +816,4 @@ <en><![CDATA[Please select a shipping method to proceed with the order process.]]></en> </locale> </groups> -</locales> \ No newline at end of file +</locales> diff --git a/settings.xml b/settings.xml index 21e2e1c28adfc005cb44cc1aedffbe6430147197..6a6fbe24cf0d966e9af7b296fcd636ba4065b108 100644 --- a/settings.xml +++ b/settings.xml @@ -17,7 +17,8 @@ </conf> <conf name="deliveryTimeDefault"> <type><![CDATA[string]]></type> - <defaultvalue><![CDATA[{"from":"","to":"","unit":"second","option":"immediately_available"}]]></defaultvalue> + <defaultvalue> + <![CDATA[{"from":"","to":"","unit":"second","option":"immediately_available"}]]></defaultvalue> </conf> </section> @@ -90,7 +91,8 @@ </text> <description> - <locale group="quiqqer/shipping" var="shipping.settings.deliveryTimeDefault.description"/> + <locale group="quiqqer/shipping" + var="shipping.settings.deliveryTimeDefault.description"/> </description> </input> </settings> @@ -143,6 +145,17 @@ </description> </input> </settings> + + <settings> + <title> + <locale group="quiqqer/shipping" var="shipping.settings.shippingStatus.title"/> + </title> + + <input type="hidden" + label="false" + data-qui="package/quiqqer/shipping/bin/backend/controls/settings/ShippingStatus" + /> + </settings> </category> </categories> </window> diff --git a/src/QUI/ERP/Shipping/ShippingStatus/Exception.php b/src/QUI/ERP/Shipping/ShippingStatus/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..6e8be21d5a7f158bfdadea11a9d94d864518d677 --- /dev/null +++ b/src/QUI/ERP/Shipping/ShippingStatus/Exception.php @@ -0,0 +1,18 @@ +<?php + +/** + * This file contains QUI\ERP\Shipping\ShippingStatus\Exception + */ + +namespace QUI\ERP\Shipping\ShippingStatus; + +use QUI; + +/** + * Class Exception + * + * @package QUI\ERP\Shipping\ShippingStatus + */ +class Exception extends QUI\Exception +{ +} diff --git a/src/QUI/ERP/Shipping/ShippingStatus/Factory.php b/src/QUI/ERP/Shipping/ShippingStatus/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..8c74eb8b3a89cd626132905a7ee64965dd248707 --- /dev/null +++ b/src/QUI/ERP/Shipping/ShippingStatus/Factory.php @@ -0,0 +1,97 @@ +<?php + +/** + * This file contains QUI\ERP\Shipping\ShippingStatus\Factory + */ + +namespace QUI\ERP\Shipping\ShippingStatus; + +use QUI; + +/** + * Class Factory + * - For shipping status creation + * + * @package QUI\ERP\Shipping\ShippingStatus\Factory + */ +class Factory extends QUI\Utils\Singleton +{ + /** + * Create a new shipping status + * + * @param string|integer $id - shipping ID + * @param string $color - color of the status + * @param array $title - title + * + * @throws Exception + * @throws QUI\Exception + * + * @todo permissions + */ + public function createShippingStatus($id, $color, array $title) + { + $list = Handler::getInstance()->getList(); + $id = (int)$id; + $data = []; + + if (isset($list[$id])) { + throw new Exception([ + 'quiqqer/shipping', + 'exception.shippingStatus.exists' + ]); + } + + // config + $Package = QUI::getPackage('quiqqer/shipping'); + $Config = $Package->getConfig(); + + $Config->setValue('shipping_status', $id, $color); + $Config->save(); + + // translations + if (\is_array($title)) { + $languages = QUI::availableLanguages(); + + foreach ($languages as $language) { + if (isset($title[$language])) { + $data[$language] = $title[$language]; + } + } + } + + // ShippingStatus title + $data['package'] = 'quiqqer/shipping'; + $data['datatype'] = 'php,js'; + $data['html'] = 1; + + QUI\Translator::addUserVar( + 'quiqqer/shipping', + 'shipping.status.'.$id, + $data + ); + + QUI\Translator::publish('quiqqer/shipping'); + + // Create translations for auto-notification + Handler::getInstance()->createNotificationTranslations($id); + Handler::getInstance()->refreshList(); + } + + /** + * Return a next ID to create a new Shipping Status + * + * @return int + */ + public function getNextId() + { + $list = Handler::getInstance()->getList(); + + if (!\count($list)) { + return 1; + } + + $max = \max(\array_keys($list)); + + return $max + 1; + } +} diff --git a/src/QUI/ERP/Shipping/ShippingStatus/Handler.php b/src/QUI/ERP/Shipping/ShippingStatus/Handler.php new file mode 100644 index 0000000000000000000000000000000000000000..6bc9c3c534bf52f6a8f22d7156775f84e65d157a --- /dev/null +++ b/src/QUI/ERP/Shipping/ShippingStatus/Handler.php @@ -0,0 +1,301 @@ +<?php + +/** + * This file contains QUI\ERP\Shipping\ShippingStatus\Handler + */ + +namespace QUI\ERP\Shipping\ShippingStatus; + +use QUI; +use QUI\ERP\Order\AbstractOrder; + +/** + * Class Handler + * - Shipping status management + * - Returns shipping status objects + * - Returns shipping status lists + * + * @package QUI\ERP\Shipping\ShippingStatus\Factory + */ +class Handler extends QUI\Utils\Singleton +{ + /** + * @var array + */ + protected $list = null; + + /** + * Return all shipping status entries from the config + * + * @return array + */ + public function getList() + { + if ($this->list !== null) { + return $this->list; + } + + try { + $Package = QUI::getPackage('quiqqer/shipping'); + $Config = $Package->getConfig(); + $result = $Config->getSection('shipping_status'); + } catch (QUI\Exception $Exception) { + QUI\System\Log::writeException($Exception); + + return []; + } + + if (!$result || !\is_array($result)) { + $this->list = []; + + return $this->list; + } + + $this->list = $result; + + return $result; + } + + /** + * Refresh the internal list + * + * @return array + */ + public function refreshList() + { + $this->list = null; + + return $this->getList(); + } + + /** + * Return the complete shipping_status status objects + * + * @return Status[] + */ + public function getShippingStatusList() + { + $list = $this->getList(); + $result = []; + + foreach ($list as $entry => $color) { + try { + $result[] = $this->getShippingStatus($entry); + } catch (Exception $Exception) { + } + } + + return $result; + } + + /** + * Return a shipping status + * + * @param $id + * @return Status|StatusUnknown + * + * @throws Exception + */ + public function getShippingStatus($id) + { + if ($id === 0) { + return new StatusUnknown(); + } + + return new Status($id); + } + + /** + * Delete / Remove a shipping status + * + * @param string|int $id + * + * @throws Exception + * @throws QUI\Exception + * + * @todo permissions + */ + public function deleteShippingStatus($id) + { + $Status = $this->getShippingStatus($id); + + // remove translation + QUI\Translator::delete( + 'quiqqer/shipping', + 'shipping.status.'.$Status->getId() + ); + + QUI\Translator::publish('quiqqer/shipping'); + + // update config + $Package = QUI::getPackage('quiqqer/shipping'); + $Config = $Package->getConfig(); + + $Config->del('shipping_status', $Status->getId()); + $Config->save(); + } + + /** + * Set auto-notification setting for a status + * + * @param int $id - ShippingStatus ID + * @param bool $notify - Auto-notification if an order is changed to the given status? + * @return void + * + * @throws Exception + * @throws QUI\Exception + */ + public function setShippingStatusNotification($id, $notify) + { + $Status = $this->getShippingStatus($id); + + // update config + $Package = QUI::getPackage('quiqqer/shipping'); + $Config = $Package->getConfig(); + + $Config->setValue('shipping_status_notification', $Status->getId(), $notify ? "1" : "0"); + $Config->save(); + } + + /** + * Update a shipping status + * + * @param int|string $id + * @param int|string $color + * @param array $title + * + * @throws QUI\Exception + * + * @todo permissions + */ + public function updateShippingStatus($id, $color, array $title) + { + $Status = $this->getShippingStatus($id); + + // update translation + $languages = QUI::availableLanguages(); + + $data = [ + 'package' => 'quiqqer/shipping', + 'datatype' => 'php,js', + 'html' => 1 + ]; + + foreach ($languages as $language) { + if (isset($title[$language])) { + $data[$language] = $title[$language]; + $data[$language.'_edit'] = $title[$language]; + } + } + + QUI\Translator::edit( + 'quiqqer/shipping', + 'shipping.status.'.$Status->getId(), + 'quiqqer/shipping', + $data + ); + + QUI\Translator::publish('quiqqer/shipping'); + + // update config + $Package = QUI::getPackage('quiqqer/shipping'); + $Config = $Package->getConfig(); + + $Config->setValue('shipping_status', $Status->getId(), $color); + $Config->save(); + } + + /** + * Create translations for status notification + * + * @param int $id + * @return void + */ + public function createNotificationTranslations($id) + { + $data = [ + 'package' => 'quiqqer/shipping', + 'datatype' => 'php,js', + 'html' => 1 + ]; + + // translations + $L = new QUI\Locale(); + $languages = QUI::availableLanguages(); + + foreach ($languages as $language) { + $L->setCurrent($language); + $data[$language] = $L->get('quiqqer/shipping', 'shipping.status.notification.template'); + } + + try { + // Check if translation already exists + $translation = QUI\Translator::get('quiqqer/shipping', 'shipping.status.notification.'.$id); + + if (!empty($translation)) { + return; + } + + // ShippingStatus notification messages + QUI\Translator::addUserVar( + 'quiqqer/shipping', + 'shipping.status.notification.'.$id, + $data + ); + + QUI\Translator::publish('quiqqer/shipping'); + } catch (\Exception $Exception) { + QUI\System\Log::writeException($Exception); + } + } + + /** + * Notify customer about an Order status change (via e-mail) + * + * @param AbstractOrder $Order + * @param int $statusId + * @param string $message (optional) - Custom notification message [default: default status change message] + * @return void + * + * @throws QUI\Exception + */ + public function sendStatusChangeNotification(AbstractOrder $Order, $statusId, $message = null) + { + $Customer = $Order->getCustomer(); + $customerEmail = $Customer->getAttribute('email'); + + if (empty($customerEmail)) { + QUI\System\Log::addWarning( + 'Status change notification for order #'.$Order->getPrefixedId().' cannot be sent' + .' because customer #'.$Customer->getId().' has no e-mail address.' + ); + + return; + } + + if (empty($message)) { + $Status = $this->getShippingStatus($statusId); + $message = $Status->getStatusChangeNotificationText($Order); + } + + $Mailer = new QUI\Mail\Mailer(); + /** @var QUI\Locale $Locale */ + $Locale = $Order->getCustomer()->getLocale(); + + $Mailer->setSubject( + $Locale->get('quiqqer/shipping', 'shipping.status.notification.subject', [ + 'orderNo' => $Order->getPrefixedId() + ]) + ); + + $Mailer->setBody($message); + $Mailer->addRecipient($customerEmail); + + try { + $Mailer->send(); + $Order->addStatusMail($message); + } catch (\Exception $Exception) { + QUI\System\Log::writeException($Exception); + } + } +} diff --git a/src/QUI/ERP/Shipping/ShippingStatus/Status.php b/src/QUI/ERP/Shipping/ShippingStatus/Status.php new file mode 100644 index 0000000000000000000000000000000000000000..18eb14316b3dccdf434ad389f7808cd5cb76dcb7 --- /dev/null +++ b/src/QUI/ERP/Shipping/ShippingStatus/Status.php @@ -0,0 +1,180 @@ +<?php + +/** + * This file contains QUI\ERP\Shipping\ShippingStatus\Status + */ + +namespace QUI\ERP\Shipping\ShippingStatus; + +use QUI; +use QUI\ERP\Order\AbstractOrder; + +/** + * Class Exception + * + * @package QUI\ERP\Shipping\ShippingStatus + */ +class Status +{ + /** + * @var int + */ + protected $id; + + /** + * @var string + */ + protected $color; + + /** + * @var bool + */ + protected $notification = false; + + /** + * Status constructor. + * + * @param int|\string $id - Shipping status id + * @throws Exception + */ + public function __construct($id) + { + $list = Handler::getInstance()->getList(); + + if (!isset($list[$id])) { + throw new Exception([ + 'quiqqer/shipping', + 'exception.shippingStatus.not.found' + ]); + } + + $this->id = (int)$id; + $this->color = $list[$id]; + + // notification + try { + $Package = QUI::getPackage('quiqqer/shipping'); + $Config = $Package->getConfig(); + $result = $Config->getSection('shipping_status_notification'); + } catch (QUI\Exception $Exception) { + QUI\System\Log::writeException($Exception); + } + + if (!empty($result[$id])) { + $this->notification = \boolval($result[$id]); + } + } + + //region Getter + + /** + * Return the status id + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Return the title + * + * @param null|QUI\Locale (optional) $Locale + * @return string + */ + public function getTitle($Locale = null) + { + if (!($Locale instanceof QUI\Locale)) { + $Locale = QUI::getLocale(); + } + + return $Locale->get('quiqqer/shipping', 'shipping.status.'.$this->id); + } + + /** + * Get status notification message + * + * @param AbstractOrder $Order - The order the status change applies to + * @param QUI\Locale $Locale (optional) - [default: QUI::getLocale()] + * @return string + */ + public function getStatusChangeNotificationText(AbstractOrder $Order, $Locale = null) + { + if (!($Locale instanceof QUI\Locale)) { + $Locale = QUI::getLocale(); + } + + $Customer = $Order->getCustomer(); + + return $Locale->get('quiqqer/shipping', 'shipping.status.notification.'.$this->id, [ + 'customerName' => $Customer->getName(), + 'orderNo' => $Order->getPrefixedId(), + 'orderDate' => $Locale->formatDate($Order->getCreateDate()), + 'orderStatus' => $this->getTitle($Locale) + ]); + } + + /** + * Return the status color + * + * @return string + */ + public function getColor() + { + return $this->color; + } + + /** + * Check if the customer has to be notified if this status is set to an order + * + * @return bool + */ + public function isAutoNotification() + { + return $this->notification; + } + + //endregion + + /** + * Status as array + * + * @param null|QUI\Locale $Locale - optional. if no locale, all translations would be returned + * @return array + */ + public function toArray($Locale = null) + { + $title = $this->getTitle($Locale); + + if ($Locale === null) { + $statusId = $this->getId(); + $title = []; + $statusChangeText = []; + + $Locale = QUI::getLocale(); + $languages = QUI::availableLanguages(); + + foreach ($languages as $language) { + $title[$language] = $Locale->getByLang( + $language, + 'quiqqer/shipping', + 'shipping.status.'.$statusId + ); + + $statusChangeText[$language] = $Locale->getByLang( + $language, + 'quiqqer/shipping', + 'shipping.status.notification.'.$statusId + ); + } + } + + return [ + 'id' => $this->getId(), + 'title' => $title, + 'color' => $this->getColor(), + 'notification' => $this->isAutoNotification() + ]; + } +} diff --git a/src/QUI/ERP/Shipping/ShippingStatus/StatusUnknown.php b/src/QUI/ERP/Shipping/ShippingStatus/StatusUnknown.php new file mode 100644 index 0000000000000000000000000000000000000000..ffac304c6a14eda949fc673353ad808a96c27bb6 --- /dev/null +++ b/src/QUI/ERP/Shipping/ShippingStatus/StatusUnknown.php @@ -0,0 +1,54 @@ +<?php + +/** + * This file contains QUI\ERP\Shipping\ShippingStatus\StatusUnknown + */ + +namespace QUI\ERP\Shipping\ShippingStatus; + +use QUI; + +/** + * Class Exception + * + * @package QUI\ERP\Shipping\ShippingStatus + */ +class StatusUnknown extends Status +{ + /** + * @var int + */ + protected $id = 0; + + /** + * @var string + */ + protected $color = '#999'; + + /** + * @var bool + */ + protected $notification = false; + + /** + * Status constructor + */ + public function __construct() + { + } + + /** + * Return the title + * + * @param null|QUI\Locale (optional) $Locale + * @return string + */ + public function getTitle($Locale = null) + { + if (!($Locale instanceof QUI\Locale)) { + $Locale = QUI::getLocale(); + } + + return $Locale->get('quiqqer/shipping', 'shipping.status.unknown'); + } +}