From 17cb8a133b70138a85fc1696cb8d43fc63964b9e Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Mon, 26 Jan 2026 11:47:14 +0100 Subject: [PATCH 01/18] [FIX] shopfloor_mobile: fix duplicate title in "detail-product" component. The "Lots" title was incorrectly placed inside the for loop, making it appear at every iteration --- .../static/wms/src/components/detail/detail_product.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shopfloor_mobile/static/wms/src/components/detail/detail_product.js b/shopfloor_mobile/static/wms/src/components/detail/detail_product.js index fc3d1db0ca1..84736c8db47 100644 --- a/shopfloor_mobile/static/wms/src/components/detail/detail_product.js +++ b/shopfloor_mobile/static/wms/src/components/detail/detail_product.js @@ -136,9 +136,10 @@ Vue.component("detail-product", { - + Lots Date: Tue, 26 Aug 2025 16:25:45 +0200 Subject: [PATCH 02/18] [IMP] shopfloor_reception: Don't rely on result package to select a line When users don't use packages for receptions, we should not rely only on its presence on lines to not select them. So, rely also on line progress completed at 100% (after split) to select another one with same criteria --- shopfloor_reception/services/reception.py | 9 +- shopfloor_reception/tests/test_select_move.py | 87 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/shopfloor_reception/services/reception.py b/shopfloor_reception/services/reception.py index a79addf582f..49d146cc864 100644 --- a/shopfloor_reception/services/reception.py +++ b/shopfloor_reception/services/reception.py @@ -287,6 +287,8 @@ def _scan_line__find_or_create_line(self, picking, move, qty_done=1): """ unassigned_lines = self.env["stock.move.line"] for line in move.move_line_ids: + if line.progress == 100.0: + continue if line.shopfloor_user_id.id == self.env.uid: return self._scan_line__recover(picking, line, qty_done) elif not line.shopfloor_user_id: @@ -544,8 +546,11 @@ def _scan_line__by_lot(self, picking, lot): """ lines = picking.move_line_ids.filtered( lambda l: ( - lot == l.lot_id - or (lot.name == l.lot_name and lot.product_id == l.product_id) + ( + lot == l.lot_id + or (lot.name == l.lot_name and lot.product_id == l.product_id) + ) + and not l.progress == 100.0 and not l.result_package_id ) ) diff --git a/shopfloor_reception/tests/test_select_move.py b/shopfloor_reception/tests/test_select_move.py index a184443e0a4..ede6fffae32 100644 --- a/shopfloor_reception/tests/test_select_move.py +++ b/shopfloor_reception/tests/test_select_move.py @@ -45,6 +45,93 @@ def test_scan_product(self): }, ) + def test_scan_product_partial(self): + # Scan a line + # Set a partial quantity done + # Try to scan the product again + # The selected line should be the other one + picking = self._create_picking() + lot = self._create_lot() + self.assertFalse(picking.printed) + selected_move_line = picking.move_line_ids.filtered( + lambda l: l.product_id == self.product_a + ) + + # Activate INPUT location + selected_move_line.location_dest_id.sudo().active = True + + selected_move_line.lot_id = lot + response = self.service.dispatch( + "scan_line", + params={"picking_id": picking.id, "barcode": lot.name}, + ) + data = self.data.picking(picking) + + self.assertTrue(selected_move_line.picking_id.printed) + self.assert_response( + response, + next_state="set_quantity", + data={ + "picking": data, + "selected_move_line": self.data.move_lines(selected_move_line), + "confirmation_required": None, + }, + ) + + selected_move_line.shopfloor_user_id = self.env.uid + response = self.service.dispatch( + "set_quantity", + params={ + "picking_id": picking.id, + "selected_line_id": selected_move_line.id, + "quantity": 5.0, + }, + ) + + response = self.service.dispatch( + "process_without_pack", + params={ + "picking_id": picking.id, + "selected_line_id": selected_move_line.id, + "quantity": 5.0, + }, + ) + data = self.data.picking(picking) + self.assert_response( + response, + next_state="set_destination", + data={ + "picking": data, + "selected_move_line": self.data.move_lines(selected_move_line), + }, + ) + + response = self.service.dispatch( + "set_destination", + params={ + "picking_id": picking.id, + "selected_line_id": selected_move_line.id, + "location_name": "INPUT", + }, + ) + self.assert_response( + response, + next_state="select_move", + data=self._data_for_select_move(picking), + ) + lines = picking.move_line_ids.filtered(lambda l: l.product_id == self.product_a) + self.assertEqual(2, len(lines)) + previous_line = selected_move_line + + response = self.service.dispatch( + "scan_line", + params={"picking_id": picking.id, "barcode": lot.name}, + ) + + self.assertNotEqual( + previous_line.id, response["data"]["set_lot"]["selected_move_line"][0]["id"] + ) + def test_scan_packaging(self): picking = self._create_picking() self._add_package(picking) From ef1e2e98bf52e0076b6c2b7c7b1fe99b721a86aa Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Thu, 29 Jan 2026 12:42:39 +0100 Subject: [PATCH 03/18] [IMP] shopfloor_reception: use `shopfloor_unloaded` to determine if a line has been fully processed. --- shopfloor_reception/services/reception.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/shopfloor_reception/services/reception.py b/shopfloor_reception/services/reception.py index 49d146cc864..7ae246d5c81 100644 --- a/shopfloor_reception/services/reception.py +++ b/shopfloor_reception/services/reception.py @@ -287,7 +287,7 @@ def _scan_line__find_or_create_line(self, picking, move, qty_done=1): """ unassigned_lines = self.env["stock.move.line"] for line in move.move_line_ids: - if line.progress == 100.0: + if line.shopfloor_unloaded: continue if line.shopfloor_user_id.id == self.env.uid: return self._scan_line__recover(picking, line, qty_done) @@ -335,7 +335,7 @@ def _select_line__filter_lines_by_packaging__return(self, lines, packaging): return_line = fields.first( lines.filtered( lambda l: not l.package_id.product_packaging_id - and not l.result_package_id + and not l.shopfloor_unloaded and l.shopfloor_user_id.id in (False, self.env.uid) ) ) @@ -352,7 +352,7 @@ def _select_line__filter_lines_by_packaging(self, lines, packaging): return fields.first( lines.filtered( lambda l: l.package_id.product_packaging_id == packaging - and not l.result_package_id + and not l.shopfloor_unloaded and l.shopfloor_user_id.id in [False, self.env.uid] ) ) @@ -550,8 +550,7 @@ def _scan_line__by_lot(self, picking, lot): lot == l.lot_id or (lot.name == l.lot_name and lot.product_id == l.product_id) ) - and not l.progress == 100.0 - and not l.result_package_id + and not l.shopfloor_unloaded ) ) if not lines: @@ -573,7 +572,7 @@ def _scan_line__by_lot(self, picking, lot): def _scan_line__fallback(self, picking, barcode): # We might have lines with no lot, but with a lot_name. lines = picking.move_line_ids.filtered( - lambda l: l.lot_name == barcode and not l.result_package_id + lambda l: l.lot_name == barcode and not l.shopfloor_unloaded ) if not lines: return self._response_for_select_move( @@ -1385,7 +1384,11 @@ def process_without_pack(self, picking_id, selected_line_id, quantity): return self._response_for_set_destination(picking, selected_line) def _post_line(self, selected_line): + """ + Called when the product is unloaded at destination. + """ selected_line.reserved_uom_qty = selected_line.qty_done + selected_line.shopfloor_unloaded = True if ( selected_line.picking_id.is_shopfloor_created and self.work.menu.allow_return From 85b8ba5b3052f1a2ceb064ffa0c56e39f384f592 Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Thu, 29 Jan 2026 12:45:42 +0100 Subject: [PATCH 04/18] [FIX] shopfloor_reception: prevent concurrent operation theft Add a test case to verify that when multiple users are working on the same lot, one user cannot take the move line from another when scanning a lot. --- shopfloor_reception/tests/test_select_move.py | 30 +++++++++++++++++++ .../tests/test_set_destination.py | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/shopfloor_reception/tests/test_select_move.py b/shopfloor_reception/tests/test_select_move.py index ede6fffae32..ad0ded79d9e 100644 --- a/shopfloor_reception/tests/test_select_move.py +++ b/shopfloor_reception/tests/test_select_move.py @@ -180,6 +180,36 @@ def test_scan_lot(self): }, ) + def test_scan_lot_concurrent(self): + """ + If 2 operators work on the same lot, the second operator + should not steal the move line of the first. + """ + picking = self._create_picking() + lot = self._create_lot() + + service_u1 = self.service + res_u1 = service_u1.dispatch( + "scan_line", + params={ + "picking_id": picking.id, + "barcode": lot.name, + }, + ) + # User 2 starts working on the same move + service_u2 = self._get_service_for_user(self.shopfloor_manager) + res_u2 = service_u2.dispatch( + "scan_line", + params={ + "picking_id": picking.id, + "barcode": lot.name, + }, + ) + self.assertNotEqual( + res_u1["data"]["set_lot"]["selected_move_line"][0]["id"], + res_u2["data"]["set_lot"]["selected_move_line"][0]["id"], + ) + def test_scan_not_tracked_product(self): self.product_a.tracking = "none" picking = self._create_picking() diff --git a/shopfloor_reception/tests/test_set_destination.py b/shopfloor_reception/tests/test_set_destination.py index 9f962c9fdb4..b5b3909aba5 100644 --- a/shopfloor_reception/tests/test_set_destination.py +++ b/shopfloor_reception/tests/test_set_destination.py @@ -225,7 +225,7 @@ def test_auto_posting_full_two_lines(self): # One move remaining in the picking, for product b, still to be processed self.assertEqual(picking.move_ids.product_id, self.product_b) - def test_auto_posting_concurent_work(self): + def test_auto_posting_concurrent_work(self): """Check 2 users working on the same move. With the auto post line option On. From 9e27606527c72b27c7511a850d89437ee88a876c Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Thu, 5 Feb 2026 09:29:41 +0100 Subject: [PATCH 05/18] [FIX] shopfloor_reception: restrict line selection to "current user" or "no user". A condition on the lines filtered lines has been added so to ensure that 2 users working on the same move do not steal move lines from one another. --- shopfloor_reception/services/reception.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shopfloor_reception/services/reception.py b/shopfloor_reception/services/reception.py index 7ae246d5c81..05d670d8b24 100644 --- a/shopfloor_reception/services/reception.py +++ b/shopfloor_reception/services/reception.py @@ -551,6 +551,7 @@ def _scan_line__by_lot(self, picking, lot): or (lot.name == l.lot_name and lot.product_id == l.product_id) ) and not l.shopfloor_unloaded + and l.shopfloor_user_id.id in (False, self.env.uid) ) ) if not lines: @@ -572,7 +573,9 @@ def _scan_line__by_lot(self, picking, lot): def _scan_line__fallback(self, picking, barcode): # We might have lines with no lot, but with a lot_name. lines = picking.move_line_ids.filtered( - lambda l: l.lot_name == barcode and not l.shopfloor_unloaded + lambda l: l.lot_name == barcode + and not l.shopfloor_unloaded + and l.shopfloor_user_id.id in (False, self.env.uid) ) if not lines: return self._response_for_select_move( From c8c7ba602a8af99f507865ee6d1bde1f2a33c70e Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Fri, 27 Mar 2026 16:38:30 +0100 Subject: [PATCH 06/18] [FIX] stock_available_to_promise_release: fix Kanban counter layout The "Need Release" counter on the Picking Type Kanban view was inconsistent with standard Odoo counters. Additionally, the layout broke when the count reached 1,000 or more, causing the number to overflow the card boundaries. --- .../views/stock_picking_type_views.xml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/stock_available_to_promise_release/views/stock_picking_type_views.xml b/stock_available_to_promise_release/views/stock_picking_type_views.xml index 7ddb53aa7d7..50cded2a034 100644 --- a/stock_available_to_promise_release/views/stock_picking_type_views.xml +++ b/stock_available_to_promise_release/views/stock_picking_type_views.xml @@ -13,13 +13,11 @@ position="before" >
-
+ -
- + Need Release
From 52f3800b3736ff165ea768b0274043c9e278532e Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Mon, 16 Feb 2026 10:57:48 +0100 Subject: [PATCH 07/18] [REF] shopfloor_mobile_base: simplify date-picker-input component Refactor the DatePicker component to use standard Vue event bubbling instead of a global event hub and watchers. - Replace the 'date' watcher with a manual $emit on the '@change' event to prevent redundant event triggers and improve performance. - Remove the 'datepicker:newdate' event_hub listener as global broadcasting is unnecessary for this local UI component. - Remove the 'handler_to_update_date' prop, shifting the responsibility of date processing to the parent component. - Simplify the template and remove unused imports. --- .../src/components/datepicker/date_picker.js | 54 +++++++------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 5cc16c00ec9..8da2f4a0a37 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -3,48 +3,32 @@ * License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */ -import event_hub from "../../services/event_hub.js"; - export var DatePicker = Vue.component("date-picker-input", { - props: { - // Method passed from the parent to update the picker's date - // from outside as required. - handler_to_update_date: Function, - }, data: function () { return { date: "", }; }, - watch: { - date: function () { - this.$emit("date_picker_selected", this.date); - }, - }, - mounted() { - event_hub.$on("datepicker:newdate", (data) => { - this.date = this.handler_to_update_date(data); - }); - }, template: ` - - - + + + `, }); From 5f3b971647e84c33a9d351e6536c66fd9bf7dcee Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Mon, 16 Feb 2026 10:58:25 +0100 Subject: [PATCH 08/18] [IMP] shopfloor_mobile_base: bind user lang to locale props of date picker component --- .../static/wms/src/components/datepicker/date_picker.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 8da2f4a0a37..4874a99d179 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -9,6 +9,13 @@ export var DatePicker = Vue.component("date-picker-input", { date: "", }; }, + computed: { + userLocale: function () { + const lang = this.$root.user?.lang || "en-US"; + // Vuetify works with kebab-case (en-us instead of en_US) + return lang.replace("_", "-").toLowerCase(); + }, + }, template: ` `, From 96d5a0edb8c172f157f46aa3b6179a313dd1b71b Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Mon, 16 Feb 2026 11:10:47 +0100 Subject: [PATCH 09/18] [FIX] shopfloor_mobile_base: prevent date-picker menu from closing on year/month selection --- .../wms/src/components/datepicker/date_picker.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 4874a99d179..e8e5998ca5f 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -7,17 +7,27 @@ export var DatePicker = Vue.component("date-picker-input", { data: function () { return { date: "", + + // Control menu state manually to prevent closing during month/year navigation. + menu: false, }; }, computed: { userLocale: function () { const lang = this.$root.user?.lang || "en-US"; - // Vuetify works with kebab-case (en-us instead of en_US) return lang.replace("_", "-").toLowerCase(); }, }, + methods: { + onDateChange(newDate) { + this.menu = false; + this.$emit("dateChange", newDate); + }, + }, template: ` `, From 3b4db60046712e403db6bacd3dc6599cdc399e12 Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Mon, 16 Feb 2026 15:20:53 +0100 Subject: [PATCH 10/18] [IMP] shopfloor_mobile_base: date-picker - enables to enter date using keyboard - Use user locale for date input - Use input masking to auto add the separators - Prevent from entering invalid characters - Show input error message in case of invalid input - Reset input if date-picker is used instead --- .../src/components/datepicker/date_picker.js | 125 +++++++++++++++++- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index e8e5998ca5f..4639158bcb5 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -3,10 +3,34 @@ * License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */ +function maskString(input, mask, maskChar = "#") { + if (!input) return ""; + // 1. Sanitize: Remove existing separators so we only have raw data + // This prevents "2020-3" from becoming "2020--3" on double-processing + const cleanInput = input.replace(/[^a-zA-Z0-9]/g, ""); + + const characters = cleanInput.split(""); + let result = ""; + + for (const char of mask) { + if (characters.length === 0) break; + + if (char === maskChar) { + result += characters.shift(); + } else { + result += char; + } + } + + return result; +} + export var DatePicker = Vue.component("date-picker-input", { data: function () { return { - date: "", + date: "", // Iso format (YYYY-MM-DD) + dateInput: "", // Formatted display (DD/MM/YYYY or similar according to locale) + showInvalidDateInputMessage: false, // Control menu state manually to prevent closing during month/year navigation. menu: false, @@ -17,12 +41,101 @@ export var DatePicker = Vue.component("date-picker-input", { const lang = this.$root.user?.lang || "en-US"; return lang.replace("_", "-").toLowerCase(); }, + dateFormatter: function () { + return new Intl.DateTimeFormat(this.userLocale); + }, + dateFormat: function () { + const sample = new Date(2025, 10, 10); + const parts = this.dateFormatter.formatToParts(sample); + return parts + .map((p) => { + if (p.type === "day") return "dd"; + if (p.type === "month") return "MM"; + if (p.type === "year") return "yyyy"; + return p.value; + }) + .join(""); + }, + dateMask: function () { + const sample = new Date(2025, 10, 10); + return this.dateFormatter.format(sample).replace(/[0-9]/g, "#"); + }, }, methods: { onDateChange(newDate) { this.menu = false; + this.dateInput = ""; + this.showInvalidDateInputMessage = false; this.$emit("dateChange", newDate); }, + /** + * Forces a synchronization between the Vue component state and the native DOM input. + * * This bypasses Vue's reactivity optimization which may skip a DOM update if the + * internal data value remains unchanged after an invalid user input (e.g., typing + * past a character limit). By briefly clearing and then restoring the value + * during the next DOM update cycle, we ensure the rendered element + * accurately reflects the component's state. + * + * @private + * @returns {void} + */ + _force_dateInput_refresh() { + const backup = this.dateInput; + this.dateInput += "a"; + this.$nextTick(() => { + this.dateInput = backup; + }); + }, + onInput(newInput) { + this.showInvalidDateInputMessage = false; + + if (newInput === null) { + this.dateInput = ""; + return; + } + + const lastChar = newInput.slice(-1); + if ( + (!/[0-9]/.test(lastChar) && newInput.length > this.dateInput.length) || + newInput.length > this.dateMask.length + ) { + this._force_dateInput_refresh(); + return; + } + + const maskedValue = maskString(newInput.replace(/\D/g, ""), this.dateMask); + this.dateInput = maskedValue; + }, + validateAndSync() { + console.log("validate and sync"); + if ((this.dateInput?.length || 0) !== this.dateMask.length) { + this.showInvalidDateInputMessage = true; + return; + } + + const sep = this.dateMask.match(/[^#]/)[0]; + + const fmtParts = this.dateFormat.split(sep); + const yearIdx = fmtParts.indexOf("yyyy"); + const monthIdx = fmtParts.indexOf("MM"); + const dayIdx = fmtParts.indexOf("dd"); + + const parts = this.dateInput.split(sep); + // ↓ suppose 2000s in case of 2 digits year + const year = parts[yearIdx].padStart(4, "20"); + const month = parts[monthIdx].padStart(2, "0"); + const day = parts[dayIdx].padStart(2, "0"); + + const isoDate = `${year}-${month}-${day}`; + if (!isNaN(Date.parse(isoDate))) { + this.date = isoDate; + this.menu = false; + this.dateInput = ""; + this.$emit("dateChange", this.date); + } else { + this.showInvalidDateInputMessage = true; + } + }, }, template: ` Date: Tue, 17 Feb 2026 14:39:43 +0100 Subject: [PATCH 11/18] [IMP] shopfloor_mobile_base: date-picker - do not validate empty input --- .../static/wms/src/components/datepicker/date_picker.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 4639158bcb5..33370a9d8a0 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -107,8 +107,10 @@ export var DatePicker = Vue.component("date-picker-input", { this.dateInput = maskedValue; }, validateAndSync() { - console.log("validate and sync"); - if ((this.dateInput?.length || 0) !== this.dateMask.length) { + if (!this.dateInput) { + return; + } + if (this.dateInput.length !== this.dateMask.length) { this.showInvalidDateInputMessage = true; return; } From c34798f47a84b97dcb710df4b7718afe3f51eb12 Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Fri, 20 Feb 2026 15:28:34 +0100 Subject: [PATCH 12/18] [IMP] shopfloor_mobile_base: restrict date-picker trigger to icon click Changed the date-picker-input behavior to trigger the calendar popup only when the prepend icon is clicked, rather than on text field focus. This prevents the picker from obstructing the screen when users prefer to type the date manually Co-authored-by: Jacques-Etienne Baudoux --- .../static/wms/src/components/datepicker/date_picker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 33370a9d8a0..984e403a69d 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -155,8 +155,8 @@ export var DatePicker = Vue.component("date-picker-input", { :label="\`Select expiry date (\${dateFormat})\`" prepend-icon="mdi-calendar" v-bind="attrs" - v-on="on" clearable + @click:prepend="menu=true" @keyup.enter="validateAndSync" @blur="validateAndSync" /> From afee1756215992e95f98dba04b02dad3603f5a65 Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Wed, 25 Feb 2026 14:09:07 +0100 Subject: [PATCH 13/18] [FIX] shopfloor_mobile_base: allow to type 2 digits year in date picker input --- .../src/components/datepicker/date_picker.js | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 984e403a69d..5d127c8153f 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -107,27 +107,34 @@ export var DatePicker = Vue.component("date-picker-input", { this.dateInput = maskedValue; }, validateAndSync() { - if (!this.dateInput) { - return; - } - if (this.dateInput.length !== this.dateMask.length) { - this.showInvalidDateInputMessage = true; - return; - } + if (!this.dateInput) return; const sep = this.dateMask.match(/[^#]/)[0]; + const dateParts = this.dateInput.split(sep); const fmtParts = this.dateFormat.split(sep); - const yearIdx = fmtParts.indexOf("yyyy"); - const monthIdx = fmtParts.indexOf("MM"); - const dayIdx = fmtParts.indexOf("dd"); - const parts = this.dateInput.split(sep); - // ↓ suppose 2000s in case of 2 digits year - const year = parts[yearIdx].padStart(4, "20"); - const month = parts[monthIdx].padStart(2, "0"); - const day = parts[dayIdx].padStart(2, "0"); + if (dateParts.length !== fmtParts.length) { + this.showInvalidDateInputMessage = true; + return; + } + + let year, month, day; + for (let i = 0; i < dateParts.length; i++) { + switch (fmtParts[i]) { + case "dd": + day = dateParts[i]; + break; + case "MM": + month = dateParts[i]; + break; + default: + year = dateParts[i]; + } + } + // ↓ suppose 2000s in case of < 4 digits year + year = year.padStart(4, "20"); const isoDate = `${year}-${month}-${day}`; if (!isNaN(Date.parse(isoDate))) { this.date = isoDate; From d480c53539a891f2596e9b18e5758f281e891b46 Mon Sep 17 00:00:00 2001 From: Nicolas Delbovier Date: Mon, 30 Mar 2026 10:49:26 +0200 Subject: [PATCH 14/18] [FIX] shopfloor_mobile_base: prevent invalid date rollover in manual input Fixed a bug where invalid calendar dates (like Feb 29 in non-leap years) were accepted and converted to the next valid date (March 01). --- .../static/wms/src/components/datepicker/date_picker.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js index 5d127c8153f..d968e5e3f46 100644 --- a/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js +++ b/shopfloor_mobile_base/static/wms/src/components/datepicker/date_picker.js @@ -135,8 +135,15 @@ export var DatePicker = Vue.component("date-picker-input", { // ↓ suppose 2000s in case of < 4 digits year year = year.padStart(4, "20"); + const isoDate = `${year}-${month}-${day}`; - if (!isNaN(Date.parse(isoDate))) { + const dateTimestamp = Date.parse(isoDate); + const isDateValid = + !isNaN(dateTimestamp) && + // Ensure parts did not roll over (e.g. Feb 29 -> March 1) + new Date(dateTimestamp).toISOString().slice(0, 10) === isoDate; + + if (isDateValid) { this.date = isoDate; this.menu = false; this.dateInput = ""; From ea4c71100a388c17db1763283400e3f47e8987e0 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 9 Apr 2026 07:58:39 +0000 Subject: [PATCH 15/18] [BOT] post-merge updates --- README.md | 2 +- shopfloor_mobile/README.rst | 8 ++- shopfloor_mobile/__manifest__.py | 2 +- .../static/description/index.html | 50 +++++++++++-------- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 386dd19d096..fe079fb8b45 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ addon | version | maintainers | summary [shopfloor](shopfloor/) | 16.0.2.16.1 | guewen simahawk sebalix | manage warehouse operations with barcode scanners [shopfloor_base](shopfloor_base/) | 16.0.1.2.0 | guewen simahawk sebalix | Core module for creating mobile apps [shopfloor_batch_automatic_creation](shopfloor_batch_automatic_creation/) | 16.0.1.1.0 | guewen | Create batch transfers for Cluster Picking -[shopfloor_mobile](shopfloor_mobile/) | 16.0.1.4.0 | simahawk | Mobile frontend for WMS Shopfloor app +[shopfloor_mobile](shopfloor_mobile/) | 16.0.1.4.1 | simahawk | Mobile frontend for WMS Shopfloor app [shopfloor_mobile_base](shopfloor_mobile_base/) | 16.0.1.1.0 | simahawk | Mobile frontend for WMS Shopfloor app [shopfloor_mobile_base_auth_api_key](shopfloor_mobile_base_auth_api_key/) | 16.0.1.0.0 | | Provides authentication via API key to Shopfloor base mobile app [shopfloor_reception](shopfloor_reception/) | 16.0.1.6.6 | mmequignon JuMiSanAr | Reception scenario for shopfloor diff --git a/shopfloor_mobile/README.rst b/shopfloor_mobile/README.rst index 988e1881b27..420cb24069e 100644 --- a/shopfloor_mobile/README.rst +++ b/shopfloor_mobile/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ================ Shopfloor mobile ================ @@ -7,13 +11,13 @@ Shopfloor mobile !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:e2e8c5dda324092d44eb40ecd4e2bfd44696c59cdc3af9ded861ef7401f7d971 + !! source digest: sha256:f07e5aafb87420fa19f88d904f3718cfd8877b4730a036b454a4feb9d70900a8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwms-lightgray.png?logo=github diff --git a/shopfloor_mobile/__manifest__.py b/shopfloor_mobile/__manifest__.py index cce3b38b0a1..b7aaa54e73a 100644 --- a/shopfloor_mobile/__manifest__.py +++ b/shopfloor_mobile/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Shopfloor mobile", "summary": "Mobile frontend for WMS Shopfloor app", - "version": "16.0.1.4.0", + "version": "16.0.1.4.1", "depends": ["shopfloor", "shopfloor_mobile_base"], "author": "Camptocamp, BCIM, Akretion, Odoo Community Association (OCA)", "maintainers": ["simahawk"], diff --git a/shopfloor_mobile/static/description/index.html b/shopfloor_mobile/static/description/index.html index f437eee30bc..3b1e1642ee8 100644 --- a/shopfloor_mobile/static/description/index.html +++ b/shopfloor_mobile/static/description/index.html @@ -3,7 +3,7 @@ -Shopfloor mobile +README.rst -
-

Shopfloor mobile

+
+ + +Odoo Community Association + +
+

Shopfloor mobile

-

Beta License: AGPL-3 OCA/wms Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/wms Translate me on Weblate Try me on Runboat

Frontend for Shopfloor app.

The work is organized in scenario. A scenario represents a process in the warehouse (eg: receive, deliver). @@ -377,7 +382,7 @@

Shopfloor mobile

Each scenario is linked to a specific menu item which can be configured in the backend. Each scenario drives you through the work to do.

-

Tech details

+

Tech details

  • This frontend is built on top of VueJS and VuetifyJS and relies on shopfloor module that exposes REST API in Odoo @@ -404,18 +409,18 @@

    Tech details

-

Pre-requisites

+

Pre-requisites

  • Your Odoo instance is accessible via mobile device
  • You have an API Key configured
-

Start the app

+

Start the app

  • Go to “Inventory -> Configuration -> Shopfloor -> Shopfloor App”
  • In the login screen fill in your API key
  • @@ -423,7 +428,7 @@

    Start the app

-

Select a profile

+

Select a profile

Several profiles can be configured in the backend, you must choose one before starting.

    @@ -433,17 +438,17 @@

    Select a profile

    This will load all available menu items for the selected profile.

-

Change language

+

Change language

  • Go to “Settings -> Language”
  • Select a language
-

Customization

+

Customization

Please refer to shopfloor_mobile_custom_example.

-

Known issues / Roadmap

+

Known issues / Roadmap

  • Split module by scenario

  • @@ -483,14 +488,14 @@

    Known issues / Roadmap

-

Changelog

+

Changelog

-

13.0.1.0.0

+

13.0.1.0.0

First official version.

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -498,11 +503,11 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
  • BCIM
  • @@ -510,7 +515,7 @@

    Authors

-

Contributors

+

Contributors

-

Design

+

Design

-

Other credits

+

Other credits

Financial support

  • Cosanum
  • @@ -537,7 +542,7 @@

    Other credits

+
From f46298a907a1275a4c15bf587a82a3b0dad9ae4c Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 9 Apr 2026 08:20:14 +0000 Subject: [PATCH 16/18] [BOT] post-merge updates --- README.md | 2 +- stock_available_to_promise_release/README.rst | 2 +- stock_available_to_promise_release/__manifest__.py | 2 +- .../static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fe079fb8b45..321bf111763 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ addon | version | maintainers | summary [shopfloor_rest_log](shopfloor_rest_log/) | 16.0.1.0.0 | simahawk | Integrate rest_log into Shopfloor app [shopfloor_workstation](shopfloor_workstation/) | 16.0.1.0.0 | | Manage warehouse workstation with barcode scanners [shopfloor_workstation_mobile](shopfloor_workstation_mobile/) | 16.0.1.0.0 | | Shopfloor mobile app integration for workstation -[stock_available_to_promise_release](stock_available_to_promise_release/) | 16.0.3.8.2 | | Release Operations based on available to promise +[stock_available_to_promise_release](stock_available_to_promise_release/) | 16.0.3.8.3 | | Release Operations based on available to promise [stock_available_to_promise_release_block](stock_available_to_promise_release_block/) | 16.0.1.1.1 | | Block Release of Operations [stock_available_to_promise_release_dynamic_routing](stock_available_to_promise_release_dynamic_routing/) | 16.0.1.0.0 | jbaudoux | Glue between moves release and dynamic routing [stock_available_to_promise_release_exclude_location](stock_available_to_promise_release_exclude_location/) | 16.0.1.0.0 | | Exclude locations from available stock diff --git a/stock_available_to_promise_release/README.rst b/stock_available_to_promise_release/README.rst index 48b48bf8f91..0041f828642 100644 --- a/stock_available_to_promise_release/README.rst +++ b/stock_available_to_promise_release/README.rst @@ -11,7 +11,7 @@ Stock Available to Promise Release !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:a2c7d3a98fbb4bc85708fd746ece6b40695d865ff74d05fccbb4622ac019fe93 + !! source digest: sha256:543c66e12c249c9e0f83d9e4a5449c6915eea33005a226e38e78f54dedcda8da !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/stock_available_to_promise_release/__manifest__.py b/stock_available_to_promise_release/__manifest__.py index a6022e9dbf8..7dc337724e0 100644 --- a/stock_available_to_promise_release/__manifest__.py +++ b/stock_available_to_promise_release/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock Available to Promise Release", - "version": "16.0.3.8.2", + "version": "16.0.3.8.3", "summary": "Release Operations based on available to promise", "author": "Camptocamp, BCIM, Odoo Community Association (OCA)", "website": "https://github.com/OCA/wms", diff --git a/stock_available_to_promise_release/static/description/index.html b/stock_available_to_promise_release/static/description/index.html index 3619102b694..56ad583b27e 100644 --- a/stock_available_to_promise_release/static/description/index.html +++ b/stock_available_to_promise_release/static/description/index.html @@ -372,7 +372,7 @@

Stock Available to Promise Release

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:a2c7d3a98fbb4bc85708fd746ece6b40695d865ff74d05fccbb4622ac019fe93 +!! source digest: sha256:543c66e12c249c9e0f83d9e4a5449c6915eea33005a226e38e78f54dedcda8da !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: LGPL-3 OCA/wms Translate me on Weblate Try me on Runboat

Currently the reservation is performed by adding reserved quantities on quants, From 21632c2e0b6e0d4cb980b93e749e4387de21cc18 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 9 Apr 2026 08:39:59 +0000 Subject: [PATCH 17/18] [BOT] post-merge updates --- README.md | 2 +- shopfloor_mobile_base/README.rst | 8 ++- shopfloor_mobile_base/__manifest__.py | 2 +- .../static/description/index.html | 63 +++++++++++-------- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 321bf111763..c5ad5ef790c 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ addon | version | maintainers | summary [shopfloor_base](shopfloor_base/) | 16.0.1.2.0 | guewen simahawk sebalix | Core module for creating mobile apps [shopfloor_batch_automatic_creation](shopfloor_batch_automatic_creation/) | 16.0.1.1.0 | guewen | Create batch transfers for Cluster Picking [shopfloor_mobile](shopfloor_mobile/) | 16.0.1.4.1 | simahawk | Mobile frontend for WMS Shopfloor app -[shopfloor_mobile_base](shopfloor_mobile_base/) | 16.0.1.1.0 | simahawk | Mobile frontend for WMS Shopfloor app +[shopfloor_mobile_base](shopfloor_mobile_base/) | 16.0.1.2.0 | simahawk | Mobile frontend for WMS Shopfloor app [shopfloor_mobile_base_auth_api_key](shopfloor_mobile_base_auth_api_key/) | 16.0.1.0.0 | | Provides authentication via API key to Shopfloor base mobile app [shopfloor_reception](shopfloor_reception/) | 16.0.1.6.6 | mmequignon JuMiSanAr | Reception scenario for shopfloor [shopfloor_reception_mobile](shopfloor_reception_mobile/) | 16.0.1.1.2 | JuMiSanAr | Scenario for receiving products diff --git a/shopfloor_mobile_base/README.rst b/shopfloor_mobile_base/README.rst index fceb84d009f..9f4aa7e2fa1 100644 --- a/shopfloor_mobile_base/README.rst +++ b/shopfloor_mobile_base/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ================ Shopfloor mobile ================ @@ -7,13 +11,13 @@ Shopfloor mobile !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:2e8f1c7c3459a3f7c3c1435363dc14241853c9254c1f13a9ebbd4f4046ec1fbc + !! source digest: sha256:2c08161a08abf7cff95dc532ec79b00df4e8d71c06445e145a57b3ae5365d576 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwms-lightgray.png?logo=github diff --git a/shopfloor_mobile_base/__manifest__.py b/shopfloor_mobile_base/__manifest__.py index 3f4ff4ca9cc..0eecc85147e 100644 --- a/shopfloor_mobile_base/__manifest__.py +++ b/shopfloor_mobile_base/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Shopfloor mobile", "summary": "Mobile frontend for WMS Shopfloor app", - "version": "16.0.1.1.0", + "version": "16.0.1.2.0", "development_status": "Beta", "depends": ["shopfloor_base"], "author": "Camptocamp, BCIM, Akretion, Odoo Community Association (OCA)", diff --git a/shopfloor_mobile_base/static/description/index.html b/shopfloor_mobile_base/static/description/index.html index 694931af481..b4738a3e3db 100644 --- a/shopfloor_mobile_base/static/description/index.html +++ b/shopfloor_mobile_base/static/description/index.html @@ -3,15 +3,16 @@ -Shopfloor mobile +README.rst -

-

Shopfloor mobile

+
+ + +Odoo Community Association + +
+

Shopfloor mobile

-

Beta License: LGPL-3 OCA/wms Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/wms Translate me on Weblate Try me on Runboat

Base frontend for Shopfloor applications.

The work is organized in scenario. A scenario represents a process in the workplace (eg: for WMS -> receive, deliver). @@ -376,7 +382,7 @@

Shopfloor mobile

Each scenario is linked to a specific menu item which can be configured in the backend. Each scenario drives you through the work to do.

-

Tech details

+

Tech details

  • This frontend is built on top of VueJS and VuetifyJS and relies on shopfloor module that exposes REST API in Odoo @@ -403,18 +409,18 @@

    Tech details

-

Pre-requisites

+

Pre-requisites

  • Your Odoo instance is accessible via mobile device
  • You have an API Key configured
-

Start the app

+

Start the app

  • Go to “Inventory -> Configuration -> Shopfloor -> Shopfloor App”
  • In the login screen fill in your API key
  • @@ -422,7 +428,7 @@

    Start the app

-

Select a profile

+

Select a profile

Several profiles can be configured in the backend, you must choose one before starting.

    @@ -432,18 +438,18 @@

    Select a profile

    This will load all available menu items for the selected profile.

-

Change language

+

Change language

  • Go to “Settings -> Language”
  • Select a language
-

Customization

+

Customization

Please refer to shopfloor_mobile_custom_example.

-

Working environment

+

Working environment

You can control which running env is considerd by Odoo config or env vars.

For Odoo config: running_env or shopfloor_running_env.

For env var: RUNNING_ENV or SHOPFLOOR_RUNNING_ENV.

@@ -451,7 +457,7 @@

Working environment

Additionally, as specific key for Shopfloor is supported.

You don’t need `server_environment` module to use this feature.

-

Known issues / Roadmap

+

Known issues / Roadmap

  • Split module by scenario

  • @@ -497,14 +503,14 @@

    Known issues / Roadmap

-

Changelog

+

Changelog

-

13.0.1.0.0

+

13.0.1.0.0

First official version.

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -512,11 +518,11 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
  • BCIM
  • @@ -524,7 +530,7 @@

    Authors

-

Contributors

+

Contributors

-

Design

+

Design

-

Other credits

+

Other credits

Financial support

  • Cosanum
  • @@ -552,9 +558,11 @@

    Other credits

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

@@ -564,5 +572,6 @@

Maintainers

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
From 5c5644de2c7e8ed74a0ed8bcc184b606eea64302 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 9 Apr 2026 13:36:37 +0000 Subject: [PATCH 18/18] [BOT] post-merge updates --- README.md | 2 +- shopfloor_reception/README.rst | 2 +- shopfloor_reception/__manifest__.py | 2 +- shopfloor_reception/static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c5ad5ef790c..6a98a929f1d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ addon | version | maintainers | summary [shopfloor_mobile](shopfloor_mobile/) | 16.0.1.4.1 | simahawk | Mobile frontend for WMS Shopfloor app [shopfloor_mobile_base](shopfloor_mobile_base/) | 16.0.1.2.0 | simahawk | Mobile frontend for WMS Shopfloor app [shopfloor_mobile_base_auth_api_key](shopfloor_mobile_base_auth_api_key/) | 16.0.1.0.0 | | Provides authentication via API key to Shopfloor base mobile app -[shopfloor_reception](shopfloor_reception/) | 16.0.1.6.6 | mmequignon JuMiSanAr | Reception scenario for shopfloor +[shopfloor_reception](shopfloor_reception/) | 16.0.1.6.7 | mmequignon JuMiSanAr | Reception scenario for shopfloor [shopfloor_reception_mobile](shopfloor_reception_mobile/) | 16.0.1.1.2 | JuMiSanAr | Scenario for receiving products [shopfloor_reception_refund_return](shopfloor_reception_refund_return/) | 16.0.1.0.0 | mmequignon | Mark created return as to refund [shopfloor_rest_log](shopfloor_rest_log/) | 16.0.1.0.0 | simahawk | Integrate rest_log into Shopfloor app diff --git a/shopfloor_reception/README.rst b/shopfloor_reception/README.rst index d6f1ddb0f96..f425cbb9070 100644 --- a/shopfloor_reception/README.rst +++ b/shopfloor_reception/README.rst @@ -11,7 +11,7 @@ Shopfloor Reception !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:f8d87b75abf2f07115fe503fe887e2266295e7bc6e9e86e9818ff85ed88bff85 + !! source digest: sha256:f4ad59cbe1f5457c033cdeb6f33a81adc81c40e2ba2e87cf1b12c9ffbc9cf3e3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/shopfloor_reception/__manifest__.py b/shopfloor_reception/__manifest__.py index 3cd79d28e16..9949f22c53d 100644 --- a/shopfloor_reception/__manifest__.py +++ b/shopfloor_reception/__manifest__.py @@ -1,7 +1,7 @@ { "name": "Shopfloor Reception", "summary": "Reception scenario for shopfloor", - "version": "16.0.1.6.6", + "version": "16.0.1.6.7", "development_status": "Beta", "category": "Inventory", "website": "https://github.com/OCA/wms", diff --git a/shopfloor_reception/static/description/index.html b/shopfloor_reception/static/description/index.html index 6a9251b2515..5ff155b6605 100644 --- a/shopfloor_reception/static/description/index.html +++ b/shopfloor_reception/static/description/index.html @@ -372,7 +372,7 @@

Shopfloor Reception

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:f8d87b75abf2f07115fe503fe887e2266295e7bc6e9e86e9818ff85ed88bff85 +!! source digest: sha256:f4ad59cbe1f5457c033cdeb6f33a81adc81c40e2ba2e87cf1b12c9ffbc9cf3e3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/wms Translate me on Weblate Try me on Runboat

Shopfloor implementation of the reception scenario.