From 9644ca52fff9130491b7d5ee382d429ec6507450 Mon Sep 17 00:00:00 2001 From: "David Monnom (moda)" Date: Thu, 1 Dec 2022 08:50:28 +0000 Subject: [PATCH] [IMP] point_of_sale: display rescue session - Add link to see rescue session on each `pos_config` - Change error popup by a alert popup when closing a pos. Before the user wasn't notified when a rescue session isn't closed. The popup isn't an error but a notification that inform the user that the session is already closed and a rescue session was created. closes odoo/odoo#107000 Taskid: 2817110 Related: odoo/upgrade#4111 Signed-off-by: Trinh Jacky (trj) --- addons/point_of_sale/models/pos_config.py | 17 ++++---- addons/point_of_sale/models/pos_session.py | 11 ++++- .../static/src/js/Popups/AlertPopup.js | 17 ++++++++ .../static/src/js/Popups/ClosePosPopup.js | 41 +++++++++++++++---- .../static/src/xml/Popups/AlertPopup.xml | 18 ++++++++ .../views/point_of_sale_dashboard.xml | 10 +++-- 6 files changed, 94 insertions(+), 20 deletions(-) create mode 100644 addons/point_of_sale/static/src/js/Popups/AlertPopup.js create mode 100644 addons/point_of_sale/static/src/xml/Popups/AlertPopup.xml diff --git a/addons/point_of_sale/models/pos_config.py b/addons/point_of_sale/models/pos_config.py index 74a739515d0..bbab3b251a4 100644 --- a/addons/point_of_sale/models/pos_config.py +++ b/addons/point_of_sale/models/pos_config.py @@ -106,7 +106,7 @@ class PosConfig(models.Model): session_ids = fields.One2many('pos.session', 'config_id', string='Sessions') current_session_id = fields.Many2one('pos.session', compute='_compute_current_session', string="Current Session") current_session_state = fields.Char(compute='_compute_current_session') - number_of_opened_session = fields.Integer(string="Number of Opened Session", compute='_compute_current_session') + number_of_rescue_session = fields.Integer(string="Number of Rescue Session", compute='_compute_current_session') last_session_closing_cash = fields.Float(compute='_compute_last_session') last_session_closing_date = fields.Date(compute='_compute_last_session') pos_session_username = fields.Char(compute='_compute_current_session_user') @@ -213,13 +213,14 @@ class PosConfig(models.Model): """If there is an open session, store it to current_session_id / current_session_State. """ for pos_config in self: - opened_sessions = pos_config.session_ids.filtered(lambda s: not s.state == 'closed') - session = pos_config.session_ids.filtered(lambda s: not s.state == 'closed' and not s.rescue) + opened_sessions = pos_config.session_ids.filtered(lambda s: s.state != 'closed') + rescue_sessions = opened_sessions.filtered('rescue') + session = pos_config.session_ids.filtered(lambda s: s.state != 'closed' and not s.rescue) # sessions ordered by id desc - pos_config.number_of_opened_session = len(opened_sessions) pos_config.has_active_session = opened_sessions and True or False pos_config.current_session_id = session and session[0].id or False pos_config.current_session_state = session and session[0].state or False + pos_config.number_of_rescue_session = len(rescue_sessions) @api.depends('session_ids') def _compute_last_session(self): @@ -543,13 +544,13 @@ class PosConfig(models.Model): 'type': 'ir.actions.act_window', } - def open_opened_session_list(self): + def open_opened_rescue_session_form(self): + self.ensure_one() return { - 'name': _('Opened Sessions'), 'res_model': 'pos.session', - 'view_mode': 'tree,kanban,form', + 'view_mode': 'form', + 'res_id': self.session_ids.filtered(lambda s: s.state != 'closed' and s.rescue).id, 'type': 'ir.actions.act_window', - 'domain': [('state', '!=', 'closed'), ('config_id', '=', self.id)] } # All following methods are made to create data needed in POS, when a localisation diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index 0bebe549f71..1cfd0636359 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -494,7 +494,16 @@ class PosSession(models.Model): if any(order.state == 'draft' for order in self.order_ids): return {'successful': False, 'message': _("You cannot close the POS when orders are still in draft"), 'redirect': False} if self.state == 'closed': - return {'successful': False, 'message': _("This session is already closed."), 'redirect': True} + return { + 'successful': False, + 'type': 'alert', + 'title': 'Session already closed', + 'message': _("The session has been already closed by another User. " + "All sales completed in the meantime have been saved in a " + "Rescue Session, which can be reviewed anytime and posted " + "to Accounting from Point of Sale's dashboard."), + 'redirect': True + } if bank_payment_method_diffs: no_loss_account = self.env['account.journal'] no_profit_account = self.env['account.journal'] diff --git a/addons/point_of_sale/static/src/js/Popups/AlertPopup.js b/addons/point_of_sale/static/src/js/Popups/AlertPopup.js new file mode 100644 index 00000000000..a6acd64d4f7 --- /dev/null +++ b/addons/point_of_sale/static/src/js/Popups/AlertPopup.js @@ -0,0 +1,17 @@ +/** @odoo-module */ + +import AbstractAwaitablePopup from "@point_of_sale/js/Popups/AbstractAwaitablePopup"; +import Registries from "@point_of_sale/js/Registries"; +import { _lt } from "@web/core/l10n/translation"; + +export class AlertPopup extends AbstractAwaitablePopup {} + +AlertPopup.template = "AlertPopup"; +AlertPopup.defaultProps = { + confirmText: _lt("Ok"), + title: "", + body: "", + cancelKey: false, +}; + +Registries.Component.add(AlertPopup); diff --git a/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js b/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js index befc433b188..dc58a0ff984 100644 --- a/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js +++ b/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js @@ -132,11 +132,26 @@ class ClosePosPopup extends AbstractAwaitablePopup { return this.handleClosingError(response); } } - await this.rpc({ - model: "pos.session", - method: "update_closing_control_state_session", - args: [this.env.pos.pos_session.id, this.state.notes], - }); + + try { + await this.rpc({ + model: "pos.session", + method: "update_closing_control_state_session", + args: [this.env.pos.pos_session.id, this.state.notes], + }); + } catch (error) { + // We have to handle the error manually otherwise the validation check stops the script. + // In case of "rescue session", we want to display the next popup with "handleClosingError". + // FIXME + if ( + !error.message && + !error.message.data && + error.message.data.message !== "This session is already closed." + ) { + throw error; + } + } + try { const bankPaymentMethodDiffPairs = this.otherPaymentMethods .filter((pm) => pm.type == "bank") @@ -170,11 +185,23 @@ class ClosePosPopup extends AbstractAwaitablePopup { window.location = "/web#action=point_of_sale.action_client_pos_menu"; } } - this.closeSessionClicked = false; } + this.closeSessionClicked = false; } + async handleClosingError(response) { - await this.showPopup("ErrorPopup", { title: "Error", body: response.message }); + let popupType = ""; + let title = ""; + + if (response.type == "alert") { + popupType = "AlertPopup"; + title = response.title ? response.title : ""; + } else { + popupType = "ErrorPopup"; + title = "Error"; + } + + await this.showPopup(popupType, { title: title, body: response.message }); if (response.redirect) { window.location = "/web#action=point_of_sale.action_client_pos_menu"; } diff --git a/addons/point_of_sale/static/src/xml/Popups/AlertPopup.xml b/addons/point_of_sale/static/src/xml/Popups/AlertPopup.xml new file mode 100644 index 00000000000..3c2dd7a07ec --- /dev/null +++ b/addons/point_of_sale/static/src/xml/Popups/AlertPopup.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/addons/point_of_sale/views/point_of_sale_dashboard.xml b/addons/point_of_sale/views/point_of_sale_dashboard.xml index 2bfddd213c0..f7246b5986f 100644 --- a/addons/point_of_sale/views/point_of_sale_dashboard.xml +++ b/addons/point_of_sale/views/point_of_sale_dashboard.xml @@ -60,7 +60,7 @@ - +
@@ -149,9 +149,11 @@
- +