diff --git a/pos_order_mgmt/README.rst b/pos_order_mgmt/README.rst index c1d40dc6..83839e3d 100644 --- a/pos_order_mgmt/README.rst +++ b/pos_order_mgmt/README.rst @@ -106,7 +106,10 @@ Contributors * David Vidal * Sylvain LE GAL (https://twitter.com/legalsylvain) +* Carlos Martínez * Pierrick Brun +* Iván Todorovich + Maintainers ~~~~~~~~~~~ diff --git a/pos_order_mgmt/models/pos_config.py b/pos_order_mgmt/models/pos_config.py index e2196a2b..ddd4d814 100644 --- a/pos_order_mgmt/models/pos_config.py +++ b/pos_order_mgmt/models/pos_config.py @@ -16,12 +16,20 @@ class PosConfig(models.Model): help='Allows to reprint already done orders in the frontend', oldname='iface_load_done_order', ) + iface_return_done_order = fields.Boolean( string='Return Done Orders', default=True, help='Allows to return already done orders in the frontend', oldname='iface_load_done_order', ) + + iface_copy_done_order = fields.Boolean( + string='Duplicate Done Orders', + default=True, + help='Allows to duplicate already done orders in the frontend', + ) + iface_load_done_order_max_qty = fields.Integer( string='Max. Done Orders Quantity To Load', default=10, diff --git a/pos_order_mgmt/models/pos_order.py b/pos_order_mgmt/models/pos_order.py index 59f0e612..11c43cdf 100644 --- a/pos_order_mgmt/models/pos_order.py +++ b/pos_order_mgmt/models/pos_order.py @@ -33,9 +33,10 @@ class PosOrder(models.Model): @api.model def _prepare_filter_query_for_pos(self, pos_session_id, query): return [ - '|', + '|', '|', ('name', 'ilike', query), ('pos_reference', 'ilike', query), + ('partner_id.display_name', 'ilike', query), ] @api.model @@ -57,8 +58,8 @@ class PosOrder(models.Model): condition += [('config_id', '=', config.id)] else: # Search globally by criteria - condition += self._prepare_filter_query_for_pos(pos_session_id, - query) + condition += self._prepare_filter_query_for_pos( + pos_session_id, query) field_names = self._prepare_fields_for_pos_list() return self.search_read( condition, field_names, limit=config.iface_load_done_order_max_qty) diff --git a/pos_order_mgmt/readme/CONTRIBUTORS.rst b/pos_order_mgmt/readme/CONTRIBUTORS.rst index bdac6f44..e49bf7b1 100644 --- a/pos_order_mgmt/readme/CONTRIBUTORS.rst +++ b/pos_order_mgmt/readme/CONTRIBUTORS.rst @@ -2,3 +2,4 @@ * Sylvain LE GAL (https://twitter.com/legalsylvain) * Carlos Martínez * Pierrick Brun +* Iván Todorovich diff --git a/pos_order_mgmt/static/src/js/widgets.js b/pos_order_mgmt/static/src/js/widgets.js index ce696308..18dbeb62 100644 --- a/pos_order_mgmt/static/src/js/widgets.js +++ b/pos_order_mgmt/static/src/js/widgets.js @@ -1,5 +1,6 @@ /* Copyright 2018 GRAP - Sylvain LE GAL Copyright 2018 Tecnativa - David Vidal + Copyright 2019 Druidoo - Ivan Todorovich License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). */ odoo.define('pos_order_mgmt.widgets', function (require) { "use strict"; @@ -56,7 +57,8 @@ odoo.define('pos_order_mgmt.widgets', function (require) { this.order_cache = new DomCache(); this.orders = []; this.unknown_products = []; - this.search_done_orders(); + this.search_query = false; + this.perform_search(); }, auto_back: true, @@ -77,24 +79,25 @@ odoo.define('pos_order_mgmt.widgets', function (require) { this.$('.back').click(function () { return self.gui.show_screen(self.gui.startup_screen); }); - if (self.orders.length === 0) { - this.search_done_orders(); - } - this.render_list(); - var search_timeout = null; + if (this.pos.config.iface_vkeyboard && this.chrome.widget.keyboard) { this.chrome.widget.keyboard.connect(this.$('.searchbox input')); } + + var search_timeout = null; this.$('.searchbox input').on('keyup', function (event) { + self.search_query = this.value; clearTimeout(search_timeout); - var query = this.value; search_timeout = setTimeout(function () { - self.perform_search(query, event.which === 13); + self.perform_search(); }, 70); }); + this.$('.searchbox .search-clear').click(function () { self.clear_search(); }); + + this.perform_search(); }, render_list: function () { @@ -126,34 +129,46 @@ odoo.define('pos_order_mgmt.widgets', function (require) { // button events. this.$('.order-list-return').off('click'); this.$('.order-list-reprint').off('click'); + this.$('.order-list-copy').off('click'); this.$('.order-list-return').click(function (event) { self.order_list_actions(event, 'return'); }); this.$('.order-list-reprint').click(function (event) { self.order_list_actions(event, 'print'); }); + this.$('.order-list-copy').click(function(event) { + self.order_list_actions(event, 'copy'); + }); }, order_list_actions: function (event, action) { - var dataset = event.target.parentNode.dataset; var self = this; + var order_data; + var dataset = event.target.parentNode.dataset; if (dataset.orderId) { - this.load_order(parseInt(dataset.orderId, 10), action); + self.load_order_data(parseInt(dataset.orderId, 10)) + .then(function(order_data) { + self.order_action(order_data, action); + }) } else { - var local_order = ''; - _.each(this.orders, function (order) { + _.each(this.orders, function (order_data) { if (order.uid === dataset.uid) { - order.return = action === 'return'; - local_order = self._prepare_order_from_order_data(order); + self.order_action(order_data, action); } }); - if (local_order) { - this['action_' + action](local_order); - } } }, - action_print: function (order) { + order_action: function(order_data, action) { + this.gui.back(); + this['action_' + action](order_data); + }, + + action_print: function (order_data) { + var order = this.load_order_from_data(order_data, true); + if (!order) return false; + // Restore the previous name + order.name = order_data.pos_reference || order_data.name; var receipt = order.export_for_printing(); // We store temporarily the current order so we can safely compute // taxes based on fiscal position @@ -178,26 +193,56 @@ odoo.define('pos_order_mgmt.widgets', function (require) { } }, - action_return: function (order) { + action_copy: function(order_data) { + // Remove payments from original data + order_data.statement_ids = false; + var order = this.load_order_from_data(order_data, true); + if (!order) { return false; } + // If previous order was invoiced, we need a refund too + order.set_to_invoice(order_data.origin_invoice_id); + order.formatted_validation_date = false; + order.trigger('change'); this.pos.get('orders').add(order); this.pos.set('selectedOrder', order); return order; }, - _prepare_order_from_order_data: function (order_data) { + action_return: function (order_data) { + //var order_data = _.cloneDeep(order_data); + // Remove payments from original data + order_data.statement_ids = false; + // Invert line quantities + var order_lines = order_data.line_ids || order_data.lines || []; + _.each(order_lines, function(line) { line.qty = -1 * line.qty }) + // Load from new data and change some stuff + var order = this.load_order_from_data(order_data); + if (!order) { return false; } + order.return = true; + order.name = _t("Refund ") + order.uid;; + order.origin_name = order_data.pos_reference || order.returned_order_id; + // If previous order was invoiced, we need a refund too + order.set_to_invoice(order_data.origin_invoice_id); + order.formatted_validation_date = false; + order.trigger('change'); + // Add to pos + this.pos.get('orders').add(order); + this.pos.set('selectedOrder', order); + return order; + }, + + _prepare_order_from_order_data: function (order_data, temporary) { var self = this; var order = new pos.Order({}, { pos: this.pos, - temporary: !order_data.return, + temporary: !!temporary, }); - // Set Generic Info - if (!order_data.return) { - order.name = order_data.pos_reference || order_data.name; - } + if (order_data.partner_id.length) { order_data.partner_id = order_data.partner_id[0]; } + order.set_client(this.pos.db.get_partner_by_id(order_data.partner_id)); + // Set fiscal position if (order_data.fiscal_position && this.pos.fiscal_positions) { var fiscal_positions = this.pos.fiscal_positions; @@ -206,23 +251,17 @@ odoo.define('pos_order_mgmt.widgets', function (require) { })[0]; order.trigger('change'); } + // Set order lines var orderLines = order_data.line_ids || order_data.lines || []; self._prepare_orderlines_from_order_data(order, order_data, orderLines); - if (order_data.return) { - order.return = true; - // A credit note should be emited if there was an invoice - order.set_to_invoice(order_data.origin_invoice_id); - // We'll refunded orders once they are synced - order.returned_order_id = order_data.id || order_data.name; - order.origin_name = order_data.pos_reference || order.returned_order_id; - order.trigger('change'); - return order; - } + if (order_data.returned_order_id) { order.origin_name = order_data.returned_order_id; } + order.formatted_validation_date = moment(order_data.date_order).format('YYYY-MM-DD HH:mm:ss'); + // Set Payment lines var paymentLines = order_data.statement_ids || []; _.each(paymentLines, function (paymentLine) { @@ -243,6 +282,7 @@ odoo.define('pos_order_mgmt.widgets', function (require) { }); return order; }, + _prepare_orderlines_from_order_data: function(order, order_data, orderLines) { var self = this; _.each(orderLines, function(line) { @@ -258,7 +298,7 @@ odoo.define('pos_order_mgmt.widgets', function (require) { // Create a new order line order.add_product(product, { price: line.price_unit, - quantity: order_data.return ? line.qty * -1 : line.qty, + quantity: line.qty, discount: line.discount, merge: false, }); @@ -266,36 +306,12 @@ odoo.define('pos_order_mgmt.widgets', function (require) { }); }, - load_order: function (order_id, action) { - this.unknown_products = []; + load_order_data: function(order_id) { var self = this; return this._rpc({ model: 'pos.order', method: 'load_done_order_for_pos', args: [order_id], - }).then(function (order_data) { - self.gui.back(); - var correct_order_print = true; - if (action === 'return') { - order_data.return = true; - } - var order = self._prepare_order_from_order_data(order_data); - // Forbid POS Order loading if some products are unknown - if (self.unknown_products.length > 0) { - self.gui.show_popup('error-traceback', { - 'title': _t('Unknown Products'), - 'body': _t('Unable to load some order lines because the ' + - 'products are not available in the POS cache.\n\n' + - 'Please check that lines :\n\n * ') + self.unknown_products.join("; \n *"), - }); - correct_order_print = false; - } - if (correct_order_print && action === 'print') { - self.action_print(order); - } - if (correct_order_print && action === 'return') { - self.action_return(order); - } }).fail(function (error, event) { if (parseInt(error.code, 10) === 200) { // Business Logic Error, not a connection problem @@ -310,10 +326,42 @@ odoo.define('pos_order_mgmt.widgets', function (require) { 'body': _t('Can not execute this action because the POS is currently offline'), }); } - event.preventDefault(); }); }, + load_order_from_data: function(order_data) { + var self = this; + this.unknown_products = []; + var order = self._prepare_order_from_order_data(order_data); + // Forbid POS Order loading if some products are unknown + if (self.unknown_products.length > 0) { + self.gui.show_popup('error-traceback', { + 'title': _t('Unknown Products'), + 'body': _t('Unable to load some order lines because the ' + + 'products are not available in the POS cache.\n\n' + + 'Please check that lines :\n\n * ') + self.unknown_products.join("; \n *"), + }); + return false; + } + return order; + }, + + /* deprecated */ + load_order: function (order_id) { + var self = this; + var done = new $.Deferred(); + this.load_order_data(order_id) + .then(function(order_data) { + self.gui.show_screen('orderlist'); + var order = self.load_order_from_data(order_data); + if (!order) { return done.fail(); } + done.resolve(order); + }).fail(function() { + done.fail(); + }); + return done; + }, + // Search Part search_done_orders: function (query) { var self = this; @@ -342,22 +390,18 @@ odoo.define('pos_order_mgmt.widgets', function (require) { }); }, - perform_search: function (query) { + perform_search: function() { var self = this; - this.search_done_orders(query) - .done(function () { - self.render_list(); - }); + return this.search_done_orders(self.search_query) + .done(function () { self.render_list(); }); }, clear_search: function () { var self = this; - this.search_done_orders() - .done(function () { - self.$('.searchbox input')[0].value = ''; - self.$('.searchbox input').focus(); - self.render_list(); - }); + self.$('.searchbox input')[0].value = ''; + self.$('.searchbox input').focus(); + self.search_query = false; + self.perform_search(); }, }); diff --git a/pos_order_mgmt/static/src/xml/pos.xml b/pos_order_mgmt/static/src/xml/pos.xml index 6eb9f3be..728d2762 100644 --- a/pos_order_mgmt/static/src/xml/pos.xml +++ b/pos_order_mgmt/static/src/xml/pos.xml @@ -58,6 +58,9 @@ + + + diff --git a/pos_order_mgmt/views/view_pos_config.xml b/pos_order_mgmt/views/view_pos_config.xml index fd1a35fa..aa5c540c 100644 --- a/pos_order_mgmt/views/view_pos_config.xml +++ b/pos_order_mgmt/views/view_pos_config.xml @@ -33,6 +33,17 @@ +
+
+ +
+
+
+