From 4d23e198d60fd945d71400b8e3be3d6bfa2ac091 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Tue, 25 Aug 2020 15:23:59 +0200 Subject: [PATCH 1/6] front: zone picking display picking types counter if empty --- shopfloor_mobile/static/wms/src/scenario/zone_picking.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shopfloor_mobile/static/wms/src/scenario/zone_picking.js b/shopfloor_mobile/static/wms/src/scenario/zone_picking.js index af63cf738e..3da215ec0e 100644 --- a/shopfloor_mobile/static/wms/src/scenario/zone_picking.js +++ b/shopfloor_mobile/static/wms/src/scenario/zone_picking.js @@ -221,10 +221,15 @@ export var ZonePicking = Vue.component("zone-picking", { }, manual_select_picking_type_fields: function() { return [ - {path: "lines_count", renderer: this.render_lines_count}, + { + path: "lines_count", + renderer: this.render_lines_count, + display_no_value: true, + }, { path: "priority_lines_count", renderer: this.render_priority_lines_count, + display_no_value: true, }, ]; }, From 792851acfce37a189c4f58e1400c194be60b2457 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Tue, 25 Aug 2020 15:29:41 +0200 Subject: [PATCH 2/6] front: fix marging below P in notifications --- shopfloor_mobile/static/wms/src/css/main.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shopfloor_mobile/static/wms/src/css/main.css b/shopfloor_mobile/static/wms/src/css/main.css index 3e96abe40f..aa7bed6eaf 100644 --- a/shopfloor_mobile/static/wms/src/css/main.css +++ b/shopfloor_mobile/static/wms/src/css/main.css @@ -352,7 +352,8 @@ ul.packaging span:first-child { padding-bottom: 5px; } -.notifications > .v-alert:last-child { +.notifications > .v-alert:last-child, +.notifications p:last-child { margin-bottom: 0; } From ee7d7769b5a0c546e23372ac503c1ef9337e5793 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 26 Aug 2020 07:46:34 +0200 Subject: [PATCH 3/6] bknd: improve exception tracing * store full traceback in log entry * return log entry URL to ease reporting --- shopfloor/services/service.py | 37 +++++++++++++++++++++++++++++---- shopfloor/services/validator.py | 1 + 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/shopfloor/services/service.py b/shopfloor/services/service.py index 10f9f088d9..877d561a45 100644 --- a/shopfloor/services/service.py +++ b/shopfloor/services/service.py @@ -1,3 +1,7 @@ +import traceback + +from werkzeug.urls import url_encode, url_join + from odoo import _, exceptions, registry from odoo.exceptions import MissingError from odoo.http import request @@ -15,6 +19,15 @@ def to_float(val): return None +class ShopfloorServiceDispatchException(Exception): + + rest_json_info = {} + + def __init__(self, message, log_entry_url): + super().__init__(message) + self.rest_json_info = {"log_entry_url": log_entry_url} + + class BaseShopfloorService(AbstractComponent): """Base class for REST services""" @@ -43,14 +56,30 @@ def _dispatch_with_db_logging(self, method_name, _id=None, params=None): try: result = super().dispatch(method_name, _id=_id, params=params) except Exception as err: + tb = traceback.format_exc() self.env.cr.rollback() with registry(self.env.cr.dbname).cursor() as cr: env = self.env(cr=cr) - self._log_call_in_db(env, request, _id, params, error=err) - raise - self._log_call_in_db(self.env, request, _id, params, result=result) + log_entry = self._log_call_in_db(env, request, _id, params, error=tb) + log_entry_url = self._get_log_entry_url(log_entry) + raise ShopfloorServiceDispatchException(str(err), log_entry_url) from err + + log_entry = self._log_call_in_db(self.env, request, _id, params, result=result) + log_entry_url = self._get_log_entry_url(log_entry) + result["log_entry_url"] = log_entry_url return result + def _get_log_entry_url(self, entry): + base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url") + url_params = { + "action": self.env.ref("shopfloor.action_shopfloor_log").id, + "view_type": "form", + "model": entry._name, + "id": entry.id, + } + url = "/web?#%s" % url_encode(url_params) + return url_join(base_url, url) + @property def _log_call_header_strip(self): return ("Cookie", "Api-Key") @@ -79,7 +108,7 @@ def _log_call_in_db(self, env, _request, _id, params, result=None, error=None): ) if not values: return - env["shopfloor.log"].sudo().create(values) + return env["shopfloor.log"].sudo().create(values) def _get(self, _id): domain = expression.normalize_domain(self._get_base_search_domain()) diff --git a/shopfloor/services/validator.py b/shopfloor/services/validator.py index 8bdf4d75cf..21c46847de 100644 --- a/shopfloor/services/validator.py +++ b/shopfloor/services/validator.py @@ -107,6 +107,7 @@ def _response_schema(self, data_schema=None, next_states=None): "required": False, "schema": {"body": {"type": "string", "required": True}}, }, + "log_entry_url": {"type": "string", "required": False}, } if not data_schema: data_schema = {} From 64bea5a33dc579bdd730d6c9201ced064b2f4eee Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 26 Aug 2020 07:48:01 +0200 Subject: [PATCH 4/6] bknd: zone picking fix typo raise/return on scan source --- shopfloor/services/zone_picking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shopfloor/services/zone_picking.py b/shopfloor/services/zone_picking.py index e95b00deed..baccf9dbd8 100644 --- a/shopfloor/services/zone_picking.py +++ b/shopfloor/services/zone_picking.py @@ -382,7 +382,7 @@ def _scan_source_location(self, zone_location, picking_type, location): move_line = self.env["stock.move.line"].search(domain) if len(move_line) == 1: return move_line - raise False + return False def _scan_source_package(self, zone_location, picking_type, package, order): move_lines = self._find_location_move_lines( From dec73b8bff18c44748c8217f288b895fed37250f Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 26 Aug 2020 07:49:49 +0200 Subject: [PATCH 5/6] front: app error display support url When the backend raises an exception, can provide a log entry URL. It's now displayed in the notification message. --- .../wms/src/components/userInformation/userInformation.js | 6 ++++++ shopfloor_mobile/static/wms/src/scenario/mixins.js | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/shopfloor_mobile/static/wms/src/components/userInformation/userInformation.js b/shopfloor_mobile/static/wms/src/components/userInformation/userInformation.js index d59a4a1d73..9f21184477 100644 --- a/shopfloor_mobile/static/wms/src/components/userInformation/userInformation.js +++ b/shopfloor_mobile/static/wms/src/components/userInformation/userInformation.js @@ -4,6 +4,9 @@ Vue.component("user-information", { template: `

+

+ +

`, computed: { @@ -14,6 +17,9 @@ Vue.component("user-information", { const msg = _.result(this.message, "body"); return msg ? msg.split("\n") : []; }, + support_url: function() { + return _.result(this.message, "support_url", ""); + }, }, }); diff --git a/shopfloor_mobile/static/wms/src/scenario/mixins.js b/shopfloor_mobile/static/wms/src/scenario/mixins.js index 1023a1bad4..9c667f9446 100644 --- a/shopfloor_mobile/static/wms/src/scenario/mixins.js +++ b/shopfloor_mobile/static/wms/src/scenario/mixins.js @@ -354,10 +354,11 @@ export var ScenarioBaseMixin = { if (error.description) { parts.push("\n" + error.description); } - parts.push("\nURL: " + error.response.url); this.set_message({ body: parts.join(" "), message_type: "error", + support_url: error.log_entry_url, + support_url_text: "View / share log entry", }); }, _state_bind_events: function() { From f6432af12aec729aa487f7324c20293831ab98a8 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 26 Aug 2020 08:17:33 +0200 Subject: [PATCH 6/6] bknd: add package name unique constrain --- shopfloor/models/stock_quant_package.py | 8 +++++++- shopfloor/tests/__init__.py | 1 + shopfloor/tests/test_misc.py | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 shopfloor/tests/test_misc.py diff --git a/shopfloor/models/stock_quant_package.py b/shopfloor/models/stock_quant_package.py index c3bc49511d..b768c06280 100644 --- a/shopfloor/models/stock_quant_package.py +++ b/shopfloor/models/stock_quant_package.py @@ -1,4 +1,4 @@ -from odoo import api, fields, models +from odoo import _, api, exceptions, fields, models class StockQuantPackage(models.Model): @@ -37,3 +37,9 @@ def _compute_reserved_move_lines(self): # destination_planned_move_line_ids # filter out done/cancel lines + + @api.constrains("name") + def _constrain_name_unique(self): + for rec in self: + if self.search_count([("name", "=", rec.name), ("id", "!=", rec.id)]): + raise exceptions.UserError(_("Package name must be unique!")) diff --git a/shopfloor/tests/__init__.py b/shopfloor/tests/__init__.py index b17bbc0db0..bfa6c153a4 100644 --- a/shopfloor/tests/__init__.py +++ b/shopfloor/tests/__init__.py @@ -50,3 +50,4 @@ from . import test_zone_picking_unload_single from . import test_zone_picking_unload_all from . import test_zone_picking_unload_set_destination +from . import test_misc diff --git a/shopfloor/tests/test_misc.py b/shopfloor/tests/test_misc.py new file mode 100644 index 0000000000..3e29f16b8b --- /dev/null +++ b/shopfloor/tests/test_misc.py @@ -0,0 +1,20 @@ +from odoo import exceptions +from odoo.tests.common import SavepointCase + + +class MiscTestCase(SavepointCase): + tracking_disable = True + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env( + context=dict(cls.env.context, tracking_disable=cls.tracking_disable) + ) + + def test_package_name_unique(self): + create = self.env["stock.quant.package"].create + create({"name": "GOOD_NAME"}) + with self.assertRaises(exceptions.UserError) as exc: + create({"name": "GOOD_NAME"}) + self.assertEqual(exc.exception.name, "Package name must be unique!")