From c8fdf32db130c4c452ac402ff37260496185ba41 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Tue, 23 Apr 2019 14:33:33 +0000 Subject: [PATCH] [FIX] point_of_sale: handle failed push of invoiceable order The use case is a bit complicated so brace yourself: OFFLINE - Make an order, invoiceble with a partner - Pay it, validate it - An error popup is shown => Before this commit, the payment screen was still on => After this commit, the receipt screen is shown proposing to print the invoice ONLINE - Make another order, non invoiceable. - Pay it, validate it - Both orders are now pushed to the server => Before this commit, it was still possible to click on "Back" and add some products. The result of this will be that the order in DB (server) would not have the newly added product, whereas the ticket would state that there was a new product => After this commit, we basically block the edition of a paid and validated order, even if the invoice printing failed OPW 1971028 closes odoo/odoo#32885 Signed-off-by: Lucas Perais (lpe) --- addons/point_of_sale/i18n/point_of_sale.pot | 9 +- addons/point_of_sale/static/src/js/screens.js | 122 ++++++++++++------ addons/point_of_sale/static/src/xml/pos.xml | 3 + 3 files changed, 93 insertions(+), 41 deletions(-) diff --git a/addons/point_of_sale/i18n/point_of_sale.pot b/addons/point_of_sale/i18n/point_of_sale.pot index a78f159c2e3..d74a276f550 100644 --- a/addons/point_of_sale/i18n/point_of_sale.pot +++ b/addons/point_of_sale/i18n/point_of_sale.pot @@ -2728,7 +2728,14 @@ msgstr "" #. module: point_of_sale #. openerp-web #: code:addons/point_of_sale/static/src/xml/pos.xml:716 -#: code:addons/point_of_sale/static/src/xml/pos.xml:1372 +#, python-format +msgid "Print Invoice" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:719 +#: code:addons/point_of_sale/static/src/xml/pos.xml:1375 #, python-format msgid "Print Receipt" msgstr "" diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 045f0be7718..a2b34025c08 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -178,6 +178,61 @@ var ScreenWidget = PosBaseWidget.extend({ } } }, + /** + * Handles the error response from the server when we push + * an invoiceable order + * Displays appropriates warnings and errors and + * proposes subsequent actions + * + * @private + * @param {PosModel} order: the order to consider, defaults to current order + * @param {Boolean} refresh_screens: whether or not displayed screens should refresh + * @param {Object} error: the error provided by Ajax + */ + _handleFailedPushForInvoice: function (order, refresh_screen, error) { + var self = this; + order = order || this.pos.get_order(); + this.invoicing = false; + order.finalized = false; + if (error.message === 'Missing Customer') { + this.gui.show_popup('confirm',{ + 'title': _t('Please select the Customer'), + 'body': _t('You need to select the customer before you can invoice an order.'), + confirm: function(){ + self.gui.show_screen('clientlist', null, refresh_screen); + }, + }); + } else if (error.message === 'Backend Invoice') { + this.gui.show_popup('confirm',{ + 'title': _t('Please print the invoice from the backend'), + 'body': _t('The order has been synchronized earlier. Please make the invoice from the backend for the order: ') + error.data.order.name, + confirm: function () { + this.gui.show_screen('receipt', null, refresh_screen); + }, + cancel: function () { + this.gui.show_screen('receipt', null, refresh_screen); + }, + }); + } else if (error.code < 0) { // XmlHttpRequest Errors + this.gui.show_popup('error',{ + 'title': _t('The order could not be sent'), + 'body': _t('Check your internet connection and try again.'), + cancel: function () { + this.gui.show_screen('receipt', {button_print_invoice: true}, refresh_screen); // refresh if necessary + }, + }); + } else if (error.code === 200) { // OpenERP Server Errors + this.gui.show_popup('error-traceback',{ + 'title': error.data.message || _t("Server Error"), + 'body': error.data.debug || _t('The server encountered an error while receiving your order.'), + }); + } else { // ??? + this.gui.show_popup('error',{ + 'title': _t("Unknown Error"), + 'body': _t("The order could not be sent to the server due to an unknown error"), + }); + } + }, }); /*--------------------------------------*\ @@ -1536,7 +1591,9 @@ var ReceiptScreenWidget = ScreenWidget.extend({ return this.pos.config.iface_print_auto && !this.pos.get_order()._printed; }, should_close_immediately: function() { - return this.pos.config.iface_print_via_proxy && this.pos.config.iface_print_skip_screen; + var order = this.pos.get_order(); + var invoiced_finalized = order.is_to_invoice() ? order.finalized : true; + return this.pos.config.iface_print_via_proxy && this.pos.config.iface_print_skip_screen && invoiced_finalized; }, lock_screen: function(locked) { this._locked = locked; @@ -1640,9 +1697,32 @@ var ReceiptScreenWidget = ScreenWidget.extend({ self.print(); } }); + var button_print_invoice = this.$('.button.print_invoice'); + button_print_invoice.click(function () { + var order = self.pos.get_order(); + var invoiced = self.pos.push_and_invoice_order(order); + self.invoicing = true; + + invoiced.fail(self._handleFailedPushForInvoice.bind(self, order, true)); // refresh + + invoiced.done(function(){ + self.invoicing = false; + self.gui.show_screen('receipt', {button_print_invoice: false}, true); // refresh + }); + }); + }, render_change: function() { + var self = this; this.$('.change-value').html(this.format_currency(this.pos.get_order().get_change())); + var order = this.pos.get_order(); + var order_screen_params = order.get_screen_data('params'); + var button_print_invoice = this.$('.button.print_invoice'); + if (order_screen_params && order_screen_params.button_print_invoice) { + button_print_invoice.show(); + } else { + button_print_invoice.hide(); + } }, render_receipt: function() { this.$('.pos-receipt-container').html(QWeb.render('PosTicket', this.get_receipt_render_env())); @@ -2067,45 +2147,7 @@ var PaymentScreenWidget = ScreenWidget.extend({ var invoiced = this.pos.push_and_invoice_order(order); this.invoicing = true; - invoiced.fail(function(error){ - self.invoicing = false; - order.finalized = false; - if (error.message === 'Missing Customer') { - self.gui.show_popup('confirm',{ - 'title': _t('Please select the Customer'), - 'body': _t('You need to select the customer before you can invoice an order.'), - confirm: function(){ - self.gui.show_screen('clientlist'); - }, - }); - } else if (error.message === 'Backend Invoice') { - self.gui.show_popup('confirm',{ - 'title': _t('Please print the invoice from the backend'), - 'body': _t('The order has been synchronized earlier. Please make the invoice from the backend for the order: ') + error.data.order.name, - confirm: function () { - this.gui.show_screen('receipt'); - }, - cancel: function () { - this.gui.show_screen('receipt'); - }, - }); - } else if (error.code < 0) { // XmlHttpRequest Errors - self.gui.show_popup('error',{ - 'title': _t('The order could not be sent'), - 'body': _t('Check your internet connection and try again.'), - }); - } else if (error.code === 200) { // OpenERP Server Errors - self.gui.show_popup('error-traceback',{ - 'title': error.data.message || _t("Server Error"), - 'body': error.data.debug || _t('The server encountered an error while receiving your order.'), - }); - } else { // ??? - self.gui.show_popup('error',{ - 'title': _t("Unknown Error"), - 'body': _t("The order could not be sent to the server due to an unknown error"), - }); - } - }); + invoiced.fail(this._handleFailedPushForInvoice.bind(this, order, false)); invoiced.done(function(){ self.invoicing = false; diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index b594d5f6b9d..12077862e10 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -712,6 +712,9 @@
+
Print Receipt