[IMP] stock_vertical_lift: filter notifications by screen

If the same user opens multiple shuttles operations on different screens,
notifications for a specific shuttle will be displayed on all of them,
regardless of the shuttle operation that triggered the notification.

This commit allows filtering notifications per screen, so that only
screens displaying shuttle operations related to the current notifications
will display them.

Notifications that are not shuttle-related are not filtered out.
This commit is contained in:
SilvioC2C
2024-02-16 14:35:47 +01:00
committed by Mmequignon
parent dfcbb4d9bb
commit 702c876a23
7 changed files with 147 additions and 8 deletions

View File

@@ -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")

View File

@@ -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):

View File

@@ -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):

View File

@@ -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 <host>/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 <host>/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

View File

@@ -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",
];
},
});
});

View File

@@ -15,6 +15,10 @@
type="text/javascript"
src="/stock_vertical_lift/static/src/js/vertical_lift.js"
/>
<script
type="text/javascript"
src="/stock_vertical_lift/static/src/js/web_client.js"
/>
</xpath>
</template>
</odoo>