From 99fa3ec267dd1371a5f8c7a66fae39be45b29be6 Mon Sep 17 00:00:00 2001 From: fja-odoo Date: Thu, 5 Oct 2023 01:57:54 +0000 Subject: [PATCH] [FIX] point_of_sale: sync orders on pos closing Step to reproduce: - Open a pos session - Turn off the connection between the server and your POS instance - Create an order offline - Turn back on the connection between the server and your POS instance - Close the POS session Issue: The order created offline is not synced to the server Cause: The sync of the order has been implemented for the button to go back to the backend without closing but not for the closing session button. Solution: Make the synch mechanism common to both buttons. closes odoo/odoo#151016 X-original-commit: 4d57ce4c740d6a3350318b4dbcd49c9f2f0f104c Signed-off-by: Joseph Caburnay (jcb) --- .../app/navbar/closing_popup/closing_popup.js | 5 ++ .../screens/payment_screen/payment_screen.js | 20 +++--- .../static/src/app/store/pos_store.js | 71 ++++++++++--------- 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/addons/point_of_sale/static/src/app/navbar/closing_popup/closing_popup.js b/addons/point_of_sale/static/src/app/navbar/closing_popup/closing_popup.js index 150ceb53151..8c38025b033 100644 --- a/addons/point_of_sale/static/src/app/navbar/closing_popup/closing_popup.js +++ b/addons/point_of_sale/static/src/app/navbar/closing_popup/closing_popup.js @@ -159,6 +159,11 @@ export class ClosePosPopup extends AbstractAwaitablePopup { } async closeSession() { this.customerDisplay?.update({ closeUI: true }); + // If there are orders in the db left unsynced, we try to sync. + const syncSuccess = await this.pos.push_orders_with_closing_popup(); + if (!syncSuccess) { + return; + } if (this.pos.config.cash_control) { const response = await this.orm.call( "pos.session", diff --git a/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js b/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js index bb7bb46fde5..b302ff112c4 100644 --- a/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js +++ b/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js @@ -270,19 +270,14 @@ export class PaymentScreen extends Component { } this.currentOrder.finalized = true; - // 1. Save order to server. this.env.services.ui.block(); - const syncOrderResult = await this.pos.push_single_order(this.currentOrder); - this.env.services.ui.unblock(); - - if (syncOrderResult instanceof ConnectionLostError) { - this.pos.showScreen(this.nextScreen); - return; - } else if (!syncOrderResult) { - return; - } - + let syncOrderResult; try { + // 1. Save order to server. + syncOrderResult = await this.pos.push_single_order(this.currentOrder); + if (!syncOrderResult) { + return; + } // 2. Invoice. if (this.shouldDownloadInvoice() && this.currentOrder.is_to_invoice()) { if (syncOrderResult[0]?.account_move) { @@ -299,11 +294,14 @@ export class PaymentScreen extends Component { } } catch (error) { if (error instanceof ConnectionLostError) { + this.pos.showScreen(this.nextScreen); Promise.reject(error); return error; } else { throw error; } + } finally { + this.env.services.ui.unblock() } // 3. Post process. diff --git a/addons/point_of_sale/static/src/app/store/pos_store.js b/addons/point_of_sale/static/src/app/store/pos_store.js index dd387b69e5e..8eb21270225 100644 --- a/addons/point_of_sale/static/src/app/store/pos_store.js +++ b/addons/point_of_sale/static/src/app/store/pos_store.js @@ -1098,6 +1098,38 @@ export class PosStore extends Reactive { }); } + // To be used in the context of closing the POS + // Saves the order locally and try to send it to the backend. + // If there is an error show a popup + async push_orders_with_closing_popup (opts = {}) { + try { + await this.push_orders(opts); + return true; + } catch (error) { + console.warn(error); + const reason = this.failed + ? _t( + 'Some orders could not be submitted to ' + + 'the server due to configuration errors. ' + + 'You can exit the Point of Sale, but do ' + + 'not close the session before the issue ' + + 'has been resolved.' + ) + : _t( + 'Some orders could not be submitted to ' + + 'the server due to internet connection issues. ' + + 'You can exit the Point of Sale, but do ' + + 'not close the session before the issue ' + + 'has been resolved.' + ); + await this.env.services.popup.add(ConfirmPopup, { + title: _t('Offline Orders'), + body: reason, + }); + return false; + } + } + push_orders(opts = {}) { return this.pushOrderMutex.exec(() => this._flush_orders(this.db.get_orders(), opts)); } @@ -1118,10 +1150,7 @@ export class PosStore extends Reactive { } return server_ids; } catch (error) { - if (error instanceof ConnectionLostError) { - Promise.reject(error); - return error; - } else { + if (!(error instanceof ConnectionLostError)) { for (const order of orders) { const reactiveOrder = this.orders.find((o) => o.uid === order.id); reactiveOrder.finalized = false; @@ -1129,8 +1158,8 @@ export class PosStore extends Reactive { this.db.save_unpaid_order(reactiveOrder); } this.set_synch("connected"); - throw error; } + throw error; } finally { this._after_flush_orders(orders); } @@ -1801,35 +1830,9 @@ export class PosStore extends Reactive { } // If there are orders in the db left unsynced, we try to sync. - // If sync successful, close without asking. - // Otherwise, ask again saying that some orders are not yet synced. - try { - await this.push_orders(); - window.location = "/web#action=point_of_sale.action_client_pos_menu"; - } catch (error) { - console.warn(error); - const reason = this.failed - ? _t( - "Some orders could not be submitted to " + - "the server due to configuration errors. " + - "You can exit the Point of Sale, but do " + - "not close the session before the issue " + - "has been resolved." - ) - : _t( - "Some orders could not be submitted to " + - "the server due to internet connection issues. " + - "You can exit the Point of Sale, but do " + - "not close the session before the issue " + - "has been resolved." - ); - const { confirmed } = await this.popup.add(ConfirmPopup, { - title: _t("Offline Orders"), - body: reason, - }); - if (confirmed) { - window.location = "/web#action=point_of_sale.action_client_pos_menu"; - } + const syncSuccess = await this.push_orders_with_closing_popup(); + if (syncSuccess) { + window.location = '/web#action=point_of_sale.action_client_pos_menu'; } } async selectPartner() {