diff --git a/stock_vertical_lift/models/vertical_lift_operation_base.py b/stock_vertical_lift/models/vertical_lift_operation_base.py index 139f4ff91..4516f5eb9 100644 --- a/stock_vertical_lift/models/vertical_lift_operation_base.py +++ b/stock_vertical_lift/models/vertical_lift_operation_base.py @@ -349,10 +349,20 @@ class VerticalLiftOperationBase(models.AbstractModel): channel = "notify_vertical_lift_screen" bus_message = { "action": "refresh", - "params": {"model": self._name, "id": self.id}, + "params": self._get_user_notification_params(), } self.env["bus.bus"].sendone(channel, bus_message) + def _get_user_notification_params(self): + return { + "model": self._name, + "id": self.id, + "shuttle_info": self._get_user_notification_params_shuttle_info(), + } + + def _get_user_notification_params_shuttle_info(self): + return self.shuttle_id._get_user_notification_params_shuttle_info() + class VerticalLiftOperationTransfer(models.AbstractModel): """Base model for shuttle pick and put operations""" @@ -416,7 +426,8 @@ class VerticalLiftOperationTransfer(models.AbstractModel): def on_barcode_scanned(self, barcode): self.ensure_one() self.env.user.notify_info( - "Scanned barcode: {}. Not implemented.".format(barcode) + "Scanned barcode: {}. Not implemented.".format(barcode), + params=self._get_user_notification_params(), ) @api.depends("current_move_line_id.product_id.packaging_ids") diff --git a/stock_vertical_lift/models/vertical_lift_operation_pick.py b/stock_vertical_lift/models/vertical_lift_operation_pick.py index 9e169207f..6abbc04da 100644 --- a/stock_vertical_lift/models/vertical_lift_operation_pick.py +++ b/stock_vertical_lift/models/vertical_lift_operation_pick.py @@ -62,7 +62,8 @@ class VerticalLiftOperationPick(models.Model): self.next_step() else: self.env.user.notify_warning( - _("No location found for barcode {}").format(barcode) + _("No location found for barcode {}").format(barcode), + params=self._get_user_notification_params(), ) def _domain_move_lines_to_do(self): diff --git a/stock_vertical_lift/models/vertical_lift_operation_put.py b/stock_vertical_lift/models/vertical_lift_operation_put.py index b19ff307f..a0a4261e1 100644 --- a/stock_vertical_lift/models/vertical_lift_operation_put.py +++ b/stock_vertical_lift/models/vertical_lift_operation_put.py @@ -70,7 +70,8 @@ class VerticalLiftOperationPut(models.Model): self.next_step() else: self.env.user.notify_warning( - _("No move line found for barcode {}").format(barcode) + _("No move line found for barcode {}").format(barcode), + params=self._get_user_notification_params(), ) def _scan_tray_type_action(self, barcode): @@ -85,11 +86,13 @@ class VerticalLiftOperationPut(models.Model): self.env.user.notify_warning( _('No free space for tray type "{}" in this shuttle.').format( tray_type.display_name - ) + ), + params=self._get_user_notification_params(), ) else: self.env.user.notify_warning( - _("No tray type found for barcode {}").format(barcode) + _("No tray type found for barcode {}").format(barcode), + params=self._get_user_notification_params(), ) def _find_tray_type(self, barcode): diff --git a/stock_vertical_lift/models/vertical_lift_shuttle.py b/stock_vertical_lift/models/vertical_lift_shuttle.py index f7fb3f836..18d8e1d8f 100644 --- a/stock_vertical_lift/models/vertical_lift_shuttle.py +++ b/stock_vertical_lift/models/vertical_lift_shuttle.py @@ -86,7 +86,11 @@ class VerticalLiftShuttle(models.Model): self.env["vertical.lift.command"].sudo().create(command_values) if self.hardware == "simulation": - self.env.user.notify_info(message=payload, title=_("Lift Simulation")) + self.env.user.notify_info( + message=payload, + title=_("Lift Simulation"), + params=self._get_user_notification_params(), + ) return True else: conn = self._hardware_get_server_connection() @@ -259,3 +263,40 @@ class VerticalLiftShuttle(models.Model): """ # XXX do we want to do something special in the notification? self._operation_for_mode()._send_notification_refresh() + + def _get_user_notification_params(self): + return { + "model": self._name, + "id": self.id, + "shuttle_info": self._get_user_notification_params_shuttle_info(), + } + + def _get_user_notification_params_shuttle_info(self): + """Returns a mapping between shuttle-related models and IDs + + Used by JS to filter notifications to be displayed: this mapping is + set on all shuttle-related notifications, and JS takes care of comparing + the current web page info (model and ID) with the mapping held by each + notification. + + IE: a notification is generated with this mapping: + { + "vertical.lift.shuttle": 1, + "vertical.lift.operation.inventory": 3, + "vertical.lift.operation.pick": 2, + "vertical.lift.operation.put": 4, + } + On web page /web#id=2&model=vertical.lift.operation.pick&view_type=form + the notification is displayed (form view with matching model and ID). + On web page /web#id=1&model=vertical.lift.operation.pick&view_type=form + the notification is not displayed (form view with matching model, but wrong ID). + """ + info = {self._name: self.id} + # Property ``_model_for_mode`` holds a mapping between shuttle mode and related + # shuttle mode specific models (``vertical.lift.operation.*``); most of the + # views on which shuttle notifications are triggered usually display one of + # these records, not a ``vertical.lift.shuttle`` one, therefore appending the + # shuttle ID to the notification itself may not be enough. + for model in self._model_for_mode.values(): + info[model] = self.env[model].search([("shuttle_id", "=", self.id)]).id + return info diff --git a/stock_vertical_lift/static/src/js/web_client.js b/stock_vertical_lift/static/src/js/web_client.js new file mode 100644 index 000000000..2f8c997bc --- /dev/null +++ b/stock_vertical_lift/static/src/js/web_client.js @@ -0,0 +1,78 @@ +odoo.define("stock_vertical_lift.WebClient", function (require) { + "use strict"; + + const WebClient = require("web.WebClient"); + // Web_notify.WebClient is needed to be loaded beforehand: we can't extend it + // directly, but we'll override its method ``bus_notification`` + require("web_notify.WebClient"); + + WebClient.include({ + /** + * Override method to filter out shuttle notifications that are not for the current device + * + * @override + **/ + bus_notification: function (notifications) { + const shuttle_notifications = notifications.filter((n) => + this.is_shuttle_notification(n) + ); + if (shuttle_notifications.length > 0) { + const filtered_shuttle_notifications = this.filter_shuttle_notifications( + shuttle_notifications + ); + // Notifications will be displayed if: + // 1) they're not shuttle-related + // 2) they're included in the filtered shuttle notifications + // NB: using ``filter`` allows keeping notifications' order + notifications = notifications.filter( + (n) => + !this.is_shuttle_notification(n) || + filtered_shuttle_notifications.indexOf(n) !== -1 + ); + } + this._super(notifications); + }, + + is_shuttle_notification: function (notification) { + const values = notification[1]; + return ( + !_.isUndefined(values.params) && + !_.isUndefined(values.params.shuttle_info) + ); + }, + + filter_shuttle_notifications: function (notifications) { + const filtered_notifications = []; + const url_hash = new URLSearchParams(window.location.hash.replace("#", "")); + const rec_model = url_hash.get("model"); + const rec_id = parseInt(url_hash.get("id"), 10); + const view_type = url_hash.get("view_type"); + // Check if this is a shuttle-related page displaying a form view with proper record ID + if ( + this._get_shuttle_models().indexOf(rec_model) !== -1 && + view_type === "form" && + !_.isUndefined(rec_id) && + rec_id > 0 + ) { + // Display notifications only for the proper shuttle + for (let i = 0; i < notifications.length; i++) { + const notif = notifications[i]; + const shuttle_info = notif[1].params.shuttle_info; + if (shuttle_info[rec_model] === rec_id) { + filtered_notifications.push(notif); + } + } + } + return filtered_notifications; + }, + + _get_shuttle_models: function () { + return [ + "vertical.lift.shuttle", + "vertical.lift.operation.inventory", + "vertical.lift.operation.pick", + "vertical.lift.operation.put", + ]; + }, + }); +}); diff --git a/stock_vertical_lift/views/stock_vertical_lift_templates.xml b/stock_vertical_lift/views/stock_vertical_lift_templates.xml index b31266889..641927765 100644 --- a/stock_vertical_lift/views/stock_vertical_lift_templates.xml +++ b/stock_vertical_lift/views/stock_vertical_lift_templates.xml @@ -15,6 +15,10 @@ type="text/javascript" src="/stock_vertical_lift/static/src/js/vertical_lift.js" /> +