From 85af384fe26d91cd0081511f8462c1d2e5adfd7d Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Fri, 23 Jun 2023 20:25:52 +0200 Subject: [PATCH 001/133] sh_delivery_shipment: add location filter After scanning a dock. This change allows to scan a location from where to work from. When a location has been scanned the user will be presented with a list of what can be added to the truck. --- .../docs/delivery_shipment_diag_seq.plantuml | 8 +- .../docs/delivery_shipment_diag_seq.png | Bin 71530 -> 73261 bytes .../services/delivery_shipment.py | 197 ++++++++++++++---- shopfloor_delivery_shipment/tests/__init__.py | 1 + .../tests/test_delivery_shipment_base.py | 15 +- ...elivery_shipment_scan_document_location.py | 150 +++++++++++++ ...delivery_shipment_scan_document_product.py | 2 + 7 files changed, 326 insertions(+), 47 deletions(-) create mode 100644 shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_location.py diff --git a/shopfloor_delivery_shipment/docs/delivery_shipment_diag_seq.plantuml b/shopfloor_delivery_shipment/docs/delivery_shipment_diag_seq.plantuml index e1aff5adc1..fe965b04f0 100644 --- a/shopfloor_delivery_shipment/docs/delivery_shipment_diag_seq.plantuml +++ b/shopfloor_delivery_shipment/docs/delivery_shipment_diag_seq.plantuml @@ -30,14 +30,14 @@ scan_dock -> scan_dock: **/scan_dock(barcode)**\n(asking for confirmation to cre scan_dock -> scan_document: **/scan_dock(barcode, confirmation=True)** == /scan_document == -scan_document -> scan_document: **/scan_document**(shipment_advice_id, barcode, picking_id=None) -scan_document -> loading_list: **/scan_document**(shipment_advice_id, barcode, picking_id=None) +scan_document -> scan_document: **/scan_document**(shipment_advice_id, barcode, picking_id=None, location_id=None) +scan_document -> loading_list: **/scan_document**(shipment_advice_id, barcode, picking_id=None, location_id=None) == /unload_move_line == -scan_document -> scan_document: **/unload_move_line**(shipment_advice_id, move_line_id) +scan_document -> scan_document: **/unload_move_line**(shipment_advice_id, move_line_id, location_id=None) == /unload_package_level == -scan_document -> scan_document: **/unload_package_level**(shipment_advice_id, package_level_id) +scan_document -> scan_document: **/unload_package_level**(shipment_advice_id, package_level_id, location_id=None) == /loading_list == scan_document -> loading_list: **/loading_list**(shipment_advice_id) diff --git a/shopfloor_delivery_shipment/docs/delivery_shipment_diag_seq.png b/shopfloor_delivery_shipment/docs/delivery_shipment_diag_seq.png index f5e72d9ac2703b11191f3bef818794c9da64a555..59afb9539c628bc26b89ea2b1a75b86a2bfb639e 100644 GIT binary patch literal 73261 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 z%0D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 J{?+~2{{e(^M$!NP diff --git a/shopfloor_delivery_shipment/services/delivery_shipment.py b/shopfloor_delivery_shipment/services/delivery_shipment.py index dd6c241f07..506aa6e3d2 100644 --- a/shopfloor_delivery_shipment/services/delivery_shipment.py +++ b/shopfloor_delivery_shipment/services/delivery_shipment.py @@ -56,6 +56,9 @@ def scan_dock(self, barcode, confirmation=False): without planned moves) * scan_dock: no shipment advice found """ + if not barcode: + # End point called with the back button + return self._response_for_scan_dock() search = self._actions_for("search") dock = search.dock_from_scan(barcode) if dock: @@ -74,15 +77,17 @@ def scan_dock(self, barcode, confirmation=False): return self._response_for_scan_document(shipment_advice) return self._response_for_scan_dock(message=self.msg_store.barcode_not_found()) - def scan_document(self, shipment_advice_id, barcode, picking_id=None): - """Scan an operation, a package, a product or a lot. + def scan_document( + self, shipment_advice_id, barcode, picking_id=None, location_id=None + ): + """Scan an operation or location; a package, a product or a lot. - If an operation is scanned, reload the screen with the related planned - content or full content of this operation for this shipment advice. + If an operation or a location is scanned, reload the screen with the related planned + content or full content of this operation/location for this shipment advice. If a package, a product or a lot is scanned, it will be loaded in the current shipment advice and the screen will be reloaded with the related - operation listing its planned or full content. + current location or operation listing its planned or full content. If all the planned content (if any) has been loaded, redirect the user to the next state 'loading_list'. @@ -112,7 +117,18 @@ def scan_document(self, shipment_advice_id, barcode, picking_id=None): return self._response_for_scan_document( shipment_advice, message=message ) + location = None + if location_id: + # Filtering location the user is working from. + location = self.env["stock.location"].browse(location_id).exists() + if not barcode: + # End point called with the back button + return self._response_for_scan_document(shipment_advice, picking, location) search = self._actions_for("search") + # Look for a location + scanned_location = search.location_from_scan(barcode) + if scanned_location: + return self._scan_location(shipment_advice, scanned_location) # Look for an operation scanned_picking = search.picking_from_scan(barcode) if scanned_picking: @@ -120,7 +136,9 @@ def scan_document(self, shipment_advice_id, barcode, picking_id=None): # Look for a package scanned_package = search.package_from_scan(barcode) if scanned_package: - return self._scan_package(shipment_advice, scanned_package) + return self._scan_package( + shipment_advice, scanned_package, picking, location + ) # Look for a lot (restricted to the relevant products as a lot number # can be shared by different products) move_lines = self.env["stock.move.line"].search( @@ -128,17 +146,29 @@ def scan_document(self, shipment_advice_id, barcode, picking_id=None): ) scanned_lot = search.lot_from_scan(barcode, products=move_lines.product_id) if scanned_lot: - return self._scan_lot(shipment_advice, scanned_lot) + return self._scan_lot(shipment_advice, scanned_lot, picking, location) scanned_product = search.product_from_scan(barcode) if not scanned_product: packaging = search.packaging_from_scan(barcode) scanned_product = packaging.product_id if scanned_product: - return self._scan_product(shipment_advice, scanned_product, picking) + return self._scan_product( + shipment_advice, scanned_product, picking, location + ) return self._response_for_scan_document( - shipment_advice, picking, message=self.msg_store.barcode_not_found() + shipment_advice, + picking, + location=location, + message=self.msg_store.barcode_not_found(), ) + def _scan_location(self, shipment_advice, location): + """Return the planned or available content of the scanned location.""" + if not self.is_src_location_valid(location): + message = self.msg_store.location_not_allowed() + return self._response_for_scan_document(shipment_advice, message=message) + return self._response_for_scan_document(shipment_advice, location=location) + def _scan_picking(self, shipment_advice, picking): """Return the planned or available content of the scanned delivery for the current shipment advice. @@ -161,7 +191,7 @@ def _scan_picking(self, shipment_advice, picking): ) return self._response_for_scan_document(shipment_advice, picking) - def _scan_package(self, shipment_advice, package): + def _scan_package(self, shipment_advice, package, picking, location): """Load the package in the shipment advice. Find the package level or move line (of the planned shipment advice in @@ -174,7 +204,9 @@ def _scan_package(self, shipment_advice, package): message = self._check_picking_status(move_lines.picking_id, shipment_advice) if message: return self._response_for_scan_document( - shipment_advice, message=message + shipment_advice, + location=location, + message=message, ) # Check that the product isn't already loaded package_level = move_lines.package_level_id @@ -182,6 +214,7 @@ def _scan_package(self, shipment_advice, package): return self._response_for_scan_document( shipment_advice, move_lines.picking_id, + location=location, message=self.msg_store.package_already_loaded_in_shipment( package, shipment_advice ), @@ -191,17 +224,26 @@ def _scan_package(self, shipment_advice, package): return self._response_for_scan_document_or_loading_list( shipment_advice, move_lines.picking_id, + location=location, ) - message = self.msg_store.unable_to_load_package_in_shipment( - package, shipment_advice - ) - if shipment_advice.planned_move_ids: + message = None + if location: + message = self.msg_store.package_not_found_in_location(package, location) + elif picking: + message = self.msg_store.package_not_found_in_picking(package, picking) + elif shipment_advice.planned_move_ids: message = self.msg_store.package_not_planned_in_shipment( package, shipment_advice ) - return self._response_for_scan_document(shipment_advice, message=message) + else: + message = self.msg_store.unable_to_load_package_in_shipment( + package, shipment_advice + ) + return self._response_for_scan_document( + shipment_advice, picking, location, message + ) - def _scan_lot(self, shipment_advice, lot): + def _scan_lot(self, shipment_advice, lot, picking, location): """Load the lot in the shipment advice. Find the first move line (of the planned shipment advice in @@ -214,7 +256,7 @@ def _scan_lot(self, shipment_advice, lot): message = self._check_picking_status(move_lines.picking_id, shipment_advice) if message: return self._response_for_scan_document( - shipment_advice, message=message + shipment_advice, location=location, message=message ) # Check that the lot doesn't belong to a package package_levels_not_loaded = move_lines.package_level_id.filtered( @@ -227,6 +269,7 @@ def _scan_lot(self, shipment_advice, lot): message=self.msg_store.lot_owned_by_packages( package_levels_not_loaded.package_id ), + location=location, ) # Check that the lot isn't already loaded if move_lines._is_loaded_in_shipment(): @@ -236,19 +279,29 @@ def _scan_lot(self, shipment_advice, lot): message=self.msg_store.lot_already_loaded_in_shipment( lot, shipment_advice ), + location=location, ) # Load the lot move_lines._load_in_shipment(shipment_advice) return self._response_for_scan_document_or_loading_list( - shipment_advice, - move_lines.picking_id, + shipment_advice, move_lines.picking_id, location=location ) - message = self.msg_store.unable_to_load_lot_in_shipment(lot, shipment_advice) - if shipment_advice.planned_move_ids: + message = None + if location: + message = self.msg_store.lot_not_found_in_location(lot, location) + elif picking: + message = self.msg_store.lot_not_found_in_picking(lot, picking) + elif shipment_advice.planned_move_ids: message = self.msg_store.lot_not_planned_in_shipment(lot, shipment_advice) - return self._response_for_scan_document(shipment_advice, message=message) + else: + message = self.msg_store.unable_to_load_lot_in_shipment( + lot, shipment_advice + ) + return self._response_for_scan_document( + shipment_advice, picking, location, message + ) - def _scan_product(self, shipment_advice, product, picking): + def _scan_product(self, shipment_advice, product, picking, location): """Load the product in the shipment advice. Find the first move line (of the planned shipment advice in @@ -317,16 +370,24 @@ def _scan_product(self, shipment_advice, product, picking): shipment_advice, move_lines.picking_id, ) - message = self.msg_store.unable_to_load_product_in_shipment( - product, shipment_advice - ) - if shipment_advice.planned_move_ids: + message = None + if location: + message = self.msg_store.product_not_found_in_location_or_transfer( + product, location, picking + ) + elif shipment_advice.planned_move_ids: message = self.msg_store.product_not_planned_in_shipment( product, shipment_advice ) - return self._response_for_scan_document(shipment_advice, message=message) + else: + message = self.msg_store.unable_to_load_product_in_shipment( + product, shipment_advice + ) + return self._response_for_scan_document( + shipment_advice, picking, location, message + ) - def unload_move_line(self, shipment_advice_id, move_line_id): + def unload_move_line(self, shipment_advice_id, move_line_id, location_id=None): """Unload a move line from a shipment advice. Transitions: @@ -341,11 +402,19 @@ def unload_move_line(self, shipment_advice_id, move_line_id): return self._response_for_scan_dock( message=self.msg_store.record_not_found() ) + location = None + if location_id: + # Filtering location the user is working from. + location = self.env["stock.location"].browse(location_id).exists() # Unload the move line move_line._unload_from_shipment() - return self._response_for_scan_document(shipment_advice, move_line.picking_id) + return self._response_for_scan_document( + shipment_advice, move_line.picking_id, location=location + ) - def unload_package_level(self, shipment_advice_id, package_level_id): + def unload_package_level( + self, shipment_advice_id, package_level_id, location_id=None + ): """Unload a package level from a shipment advice. Transitions: @@ -362,10 +431,14 @@ def unload_package_level(self, shipment_advice_id, package_level_id): return self._response_for_scan_dock( message=self.msg_store.record_not_found() ) + location = None + if location_id: + # Filtering location the user is working from. + location = self.env["stock.location"].browse(location_id).exists() # Unload the package level package_level._unload_from_shipment() return self._response_for_scan_document( - shipment_advice, package_level.picking_id + shipment_advice, package_level.picking_id, location=location ) def loading_list(self, shipment_advice_id): @@ -413,11 +486,21 @@ def _response_for_scan_dock(self, message=None, confirmation_required=False): data = {"confirmation_required": confirmation_required} return self._response(next_state="scan_dock", data=data, message=message) - def _response_for_scan_document(self, shipment_advice, picking=None, message=None): + def _response_for_scan_document( + self, shipment_advice, picking=None, location=None, message=None + ): data = { "shipment_advice": self.data.shipment_advice(shipment_advice), } - if picking: + # The filter on location takes priority on the picking filter + if location: + data.update( + location=self.data.location(location), + content=self._data_for_content_to_load_from_picking( + shipment_advice, location=location + ), + ) + elif picking: data.update( picking=self.data.picking(picking), content=self._data_for_content_to_load_from_picking( @@ -439,7 +522,7 @@ def _response_for_loading_list(self, shipment_advice, message=None): return self._response(next_state="loading_list", data=data, message=message) def _response_for_scan_document_or_loading_list( - self, shipment_advice, picking, message=None + self, shipment_advice, picking, message=None, location=None ): """Route on 'scan_document' or 'loading_list' states. @@ -454,7 +537,7 @@ def _response_for_scan_document_or_loading_list( message=self.msg_store.shipment_planned_content_fully_loaded(), ) return self._response_for_scan_document( - shipment_advice, picking, message=message + shipment_advice, picking, location=location, message=message ) def _response_for_validate(self, shipment_advice, message=None): @@ -503,7 +586,9 @@ def _data_for_content_to_load_from_pickings(self, shipment_advice): move_lines = self.env["stock.move.line"].search(domain) return self._prepare_data_for_content(move_lines) - def _data_for_content_to_load_from_picking(self, shipment_advice, picking): + def _data_for_content_to_load_from_picking( + self, shipment_advice, picking=None, location=None + ): """Return a dictionary where keys are source locations and values are dictionaries listing package_levels and move_lines loaded or to load. @@ -520,9 +605,12 @@ def _data_for_content_to_load_from_picking(self, shipment_advice, picking): } """ # Grab move lines to sort, restricted to the current delivery - move_lines = self._find_move_lines_to_process_from_picking( - shipment_advice, picking - ) + if picking: + move_lines = self._find_move_lines_to_process_from_picking( + shipment_advice, picking + ) + elif location: + move_lines = self._find_move_lines_from_location(shipment_advice, location) return self._prepare_data_for_content(move_lines) def _prepare_data_for_content(self, move_lines): @@ -615,6 +703,13 @@ def _create_shipment_advice_from_dock(self, dock): shipment_advice.action_in_progress() return shipment_advice + def _find_move_lines_from_location(self, shipment_advice, location): + """Returns the move line corresponding to `location` for the given shipment.""" + location.ensure_one() + domain = self._find_move_lines_domain(shipment_advice) + domain.append(("location_id", "child_of", location.id)) + return self.env["stock.move.line"].search(domain) + def _find_move_lines_to_process_from_picking(self, shipment_advice, picking): """Returns the moves to load or unload for the given shipment and delivery. @@ -763,6 +858,12 @@ def scan_document(self): "nullable": True, "type": "integer", }, + "location_id": { + "coerce": to_int, + "required": False, + "nullable": True, + "type": "integer", + }, } def unload_move_line(self): @@ -773,6 +874,12 @@ def unload_move_line(self): "type": "integer", }, "move_line_id": {"coerce": to_int, "required": True, "type": "integer"}, + "location_id": { + "coerce": to_int, + "required": False, + "nullable": True, + "type": "integer", + }, } def unload_package_level(self): @@ -787,6 +894,12 @@ def unload_package_level(self): "required": True, "type": "integer", }, + "location_id": { + "coerce": to_int, + "required": False, + "nullable": True, + "type": "integer", + }, } def loading_list(self): @@ -850,6 +963,7 @@ def _schema_scan_dock(self): def _schema_scan_document(self): shipment_schema = self.schemas.shipment_advice() picking_schema = self.schemas.picking() + location_schema = self.schemas.location() return { "shipment_advice": { "type": "dict", @@ -863,6 +977,7 @@ def _schema_scan_document(self): # TODO # "schema": shipment_schema, }, + "location": {"type": "dict", "nullable": True, "schema": location_schema}, } @property diff --git a/shopfloor_delivery_shipment/tests/__init__.py b/shopfloor_delivery_shipment/tests/__init__.py index c683ac5e20..45ea6e1c19 100644 --- a/shopfloor_delivery_shipment/tests/__init__.py +++ b/shopfloor_delivery_shipment/tests/__init__.py @@ -2,6 +2,7 @@ from . import test_delivery_shipment_scan_dock from . import test_delivery_shipment_scan_document_picking from . import test_delivery_shipment_scan_document_package +from . import test_delivery_shipment_scan_document_location from . import test_delivery_shipment_scan_document_lot from . import test_delivery_shipment_scan_document_product from . import test_delivery_shipment_unload diff --git a/shopfloor_delivery_shipment/tests/test_delivery_shipment_base.py b/shopfloor_delivery_shipment/tests/test_delivery_shipment_base.py index 34138601e4..d62b34d617 100644 --- a/shopfloor_delivery_shipment/tests/test_delivery_shipment_base.py +++ b/shopfloor_delivery_shipment/tests/test_delivery_shipment_base.py @@ -103,14 +103,25 @@ def assert_response_scan_dock( ) def assert_response_scan_document( - self, response, shipment_advice, picking=None, lines_to_load=None, message=None + self, + response, + shipment_advice, + picking=None, + lines_to_load=None, + location=None, + message=None, ): content = self.service._data_for_content_to_load_from_pickings(shipment_advice) data = { "shipment_advice": self._data_for_shipment_advice(shipment_advice), "content": content, } - if picking: + if location: + data["location"] = self.service.data.location(location) + data["content"] = self.service._data_for_content_to_load_from_picking( + shipment_advice, location=location + ) + elif picking: data["picking"] = self.service.data.picking(picking) data["content"] = self.service._data_for_content_to_load_from_picking( shipment_advice, picking diff --git a/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_location.py b/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_location.py new file mode 100644 index 0000000000..021ab7170d --- /dev/null +++ b/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_location.py @@ -0,0 +1,150 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from .test_delivery_shipment_base import DeliveryShipmentCommonCase + + +class DeliveryShipmentScanDocumentLocationCase(DeliveryShipmentCommonCase): + """Tests for '/scan_document' endpoint when scanning a location to work from.""" + + @classmethod + def setUpClassBaseData(cls, *args, **kwargs): + super().setUpClassBaseData(*args, **kwargs) + cls.location = cls.menu.picking_type_ids.default_location_src_id + cls.sublocation = cls.env.ref("stock.stock_location_14") + cls.badlocation = cls.env.ref("stock.stock_location_customers") + # Create a transfer from the sublocation + cls.pick_subloc = cls._create_picking( + cls.picking_type, + lines=[(cls.product_a, 10), (cls.product_b, 5), (cls.product_c, 7)], + ) + # Clearing stock in parent location insuring goods are taken from sublocation + cls._update_qty_in_location(cls.location, cls.product_a, 0) + cls._fill_stock_for_moves( + cls.pick_subloc.move_lines[0], location=cls.sublocation + ) + cls._fill_stock_for_moves( + cls.pick_subloc.move_lines[1], in_package=True, location=cls.sublocation + ) + cls._fill_stock_for_moves( + cls.pick_subloc.move_lines[2], in_lot=True, location=cls.sublocation + ) + cls.pick_subloc.action_assign() + assert cls.pick_subloc.state == "assigned" + + def test_scan_document_location_ok_to_work_from(self): + """Scan a location allowed per the menu transfer type.""" + self._plan_records_in_shipment(self.shipment, self.picking1.move_lines) + response = self.service.dispatch( + "scan_document", + params={ + "shipment_advice_id": self.shipment.id, + "barcode": self.sublocation.barcode, + }, + ) + self.assert_response_scan_document( + response, + self.shipment, + location=self.sublocation, + ) + + def test_scan_document_location_not_ok_to_work_from(self): + """Scan a location not allowed per the menus transfer type.""" + self._plan_records_in_shipment(self.shipment, self.picking1.move_lines) + response = self.service.dispatch( + "scan_document", + params={ + "shipment_advice_id": self.shipment.id, + "barcode": self.badlocation.barcode, + }, + ) + self.assert_response_scan_document( + response, + self.shipment, + message=self.service.msg_store.location_not_allowed(), + ) + + def test_scan_document_package_after_location(self): + """Scan a package when filtereing on a location. + + The filtering should stay on the location and not be on the related picking + """ + self._plan_records_in_shipment(self.shipment, self.pick_subloc.move_lines) + package_level = self.pick_subloc.package_level_ids + scanned_package = package_level.package_id + response = self.service.dispatch( + "scan_document", + params={ + "shipment_advice_id": self.shipment.id, + "barcode": scanned_package.name, + "location_id": self.sublocation.id, + }, + ) + self.assert_response_scan_document( + response, + self.shipment, + location=self.sublocation, + ) + + def test_scan_document_lot_after_location(self): + """Scan a lot when filtereing on a location. + + The filtering should stay on the location and not be on the related picking. + """ + self._plan_records_in_shipment(self.shipment, self.pick_subloc.move_lines) + scanned_lot = self.pick_subloc.move_line_ids.lot_id + response = self.service.dispatch( + "scan_document", + params={ + "shipment_advice_id": self.shipment.id, + "barcode": scanned_lot.name, + "location_id": self.sublocation.id, + }, + ) + self.assert_response_scan_document( + response, + self.shipment, + location=self.sublocation, + ) + + def test_unload_package_keep_location(self): + """Check the filtered location is kept when unloading a package.""" + package_level = self.pick_subloc.package_level_ids + # Load the package level at first + package_level._load_in_shipment(self.shipment) + # Then unload it + response = self.service.dispatch( + "unload_package_level", + params={ + "shipment_advice_id": self.shipment.id, + "package_level_id": package_level.id, + "location_id": self.sublocation.id, + }, + ) + self.assert_response_scan_document( + response, + self.shipment, + location=self.sublocation, + ) + + def test_unload_move_line_keep_location(self): + """Check the filtered location is kept when unloading a move line.""" + move_line = self.picking1.move_lines.filtered( + lambda m: m.product_id == self.product_c + ).move_line_ids + # Load the move line at first + move_line._load_in_shipment(self.shipment) + # Then unload it + response = self.service.dispatch( + "unload_move_line", + params={ + "shipment_advice_id": self.shipment.id, + "move_line_id": move_line.id, + "location_id": self.sublocation.id, + }, + ) + self.assert_response_scan_document( + response, + self.shipment, + move_line.picking_id, + location=self.sublocation, + ) diff --git a/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_product.py b/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_product.py index 11618012aa..e6ef1abc59 100644 --- a/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_product.py +++ b/shopfloor_delivery_shipment/tests/test_delivery_shipment_scan_document_product.py @@ -51,6 +51,7 @@ def test_scan_document_shipment_planned_product_not_planned(self): self.assert_response_scan_document( response, self.shipment, + picking=self.picking1, message=self.service.msg_store.product_not_planned_in_shipment( scanned_product, self.shipment ), @@ -213,6 +214,7 @@ def test_scan_document_shipment_not_planned_product_planned(self): self.assert_response_scan_document( response, self.shipment, + picking=self.picking1, message=self.service.msg_store.unable_to_load_product_in_shipment( scanned_product, self.shipment ), From 352f41a8deeb1e2a6be970dee6fd43f4240a3755 Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Mon, 26 Jun 2023 14:38:07 +0200 Subject: [PATCH 002/133] sh_delivery_shipment_mobile: add location filter --- .../services/delivery_shipment.py | 42 +++++++++-- .../wms/src/scenario/delivery_shipment.js | 70 +++++++++++++++---- 2 files changed, 91 insertions(+), 21 deletions(-) diff --git a/shopfloor_delivery_shipment/services/delivery_shipment.py b/shopfloor_delivery_shipment/services/delivery_shipment.py index 506aa6e3d2..5fa7764756 100644 --- a/shopfloor_delivery_shipment/services/delivery_shipment.py +++ b/shopfloor_delivery_shipment/services/delivery_shipment.py @@ -198,7 +198,9 @@ def _scan_package(self, shipment_advice, package, picking, location): priority if any) corresponding to the scanned package and load it. If no content is found an error will be returned. """ - move_lines = self._find_move_lines_from_package(shipment_advice, package) + move_lines = self._find_move_lines_from_package( + shipment_advice, package, picking, location + ) if move_lines: # Check transfer status message = self._check_picking_status(move_lines.picking_id, shipment_advice) @@ -250,7 +252,9 @@ def _scan_lot(self, shipment_advice, lot, picking, location): priority if any) corresponding to the scanned lot and load it. If no move line is found an error will be returned. """ - move_lines = self._find_move_lines_from_lot(shipment_advice, lot) + move_lines = self._find_move_lines_from_lot( + shipment_advice, lot, picking, location + ) if move_lines: # Check transfer status message = self._check_picking_status(move_lines.picking_id, shipment_advice) @@ -314,7 +318,7 @@ def _scan_product(self, shipment_advice, product, picking, location): message=self.msg_store.scan_operation_first(), ) move_lines = self._find_move_lines_from_product( - shipment_advice, product, picking + shipment_advice, product, picking, location ) if move_lines: # Check transfer status @@ -740,17 +744,35 @@ def _find_move_lines_domain(self, shipment_advice): shipment_picking_type_ids=self.picking_types.ids )._find_move_lines_domain() # Defined in `shipment_advice` - def _find_move_lines_from_package(self, shipment_advice, package): + def _find_move_lines_from_package( + self, shipment_advice, package, picking, location + ): """Returns the move line corresponding to `package` for the given shipment.""" domain = self._find_move_lines_domain(shipment_advice) # FIXME should we check also result package here? domain.append(("package_id", "=", package.id)) + if location: + domain.append( + ("location_id", "child_of", location.id), + ) + if picking: + domain.append( + ("picking_id", "=", picking.id), + ) return self.env["stock.move.line"].search(domain) - def _find_move_lines_from_lot(self, shipment_advice, lot): + def _find_move_lines_from_lot(self, shipment_advice, lot, picking, location): """Returns the move line corresponding to `lot` for the given shipment.""" domain = self._find_move_lines_domain(shipment_advice) domain.append(("lot_id", "=", lot.id)) + if location: + domain.append( + ("location_id", "child_of", location.id), + ) + if picking: + domain.append( + ("picking_id", "=", picking.id), + ) return self.env["stock.move.line"].search(domain) def _find_move_lines_from_product( @@ -758,6 +780,7 @@ def _find_move_lines_from_product( shipment_advice, product, picking, + location, in_package_not_loaded=False, in_lot=False, ): @@ -766,8 +789,15 @@ def _find_move_lines_from_product( """ domain = self._find_move_lines_domain(shipment_advice) domain.extend( - [("product_id", "=", product.id), ("picking_id", "=", picking.id)] + [ + ("product_id", "=", product.id), + ("picking_id", "=", picking.id), + ] ) + if location: + domain.append( + ("location_id", "child_of", location.id), + ) if in_package_not_loaded: domain.append( ("package_level_id", "!=", False), diff --git a/shopfloor_delivery_shipment_mobile/static/wms/src/scenario/delivery_shipment.js b/shopfloor_delivery_shipment_mobile/static/wms/src/scenario/delivery_shipment.js index 0510737f94..4b53240eb8 100644 --- a/shopfloor_delivery_shipment_mobile/static/wms/src/scenario/delivery_shipment.js +++ b/shopfloor_delivery_shipment_mobile/static/wms/src/scenario/delivery_shipment.js @@ -49,11 +49,19 @@ const DeliveryShipment = { :card_color="utils.colors.color_for('screen_step_done')" /> + + @@ -152,6 +160,18 @@ const DeliveryShipment = { } return data.picking; }, + filter_location: function (from_state = "") { + var data = {}; + if (from_state) { + data = this.state_get_data(from_state); + } else { + data = this.state.data; + } + if (_.isEmpty(data.location)) { + return {}; + } + return data.location; + }, pickings: function () { if (this.filter_state === "dock" && !_.isEmpty(this.state.data.on_dock)) { return this.state.data.on_dock; @@ -264,6 +284,7 @@ const DeliveryShipment = { this.odoo.call("unload_move_line", { shipment_advice_id: this.shipment().id, move_line_id: line.id, + location_id: this.filter_location().id, }) ); }, @@ -272,6 +293,7 @@ const DeliveryShipment = { this.odoo.call("unload_package_level", { shipment_advice_id: this.shipment().id, package_level_id: pack.id, + location_id: this.filter_location().id, }) ); }, @@ -412,27 +434,40 @@ const DeliveryShipment = { }, scan_document: { display_info: { - title: "Scan some shipment's content", + title: "Scan some shipment's content or a location", scan_placeholder: () => { if (_.isEmpty(this.picking())) { - return "Scan a lot, a pack or an operation"; + return "Scan a lot, a pack, an operation or a location"; } else { - return "Scan a lot, a product, a pack or an operation"; + return "Scan a lot, a product, a pack, an operation or a location"; } }, }, on_scan: (scanned) => { - this.wait_call( - this.odoo.call("scan_document", { - barcode: scanned.text, - shipment_advice_id: this.shipment().id, - picking_id: this.picking().id, - }) - ); + const data = { + barcode: scanned.text, + shipment_advice_id: this.shipment().id, + picking_id: this.picking().id, + location_id: this.filter_location().id, + }; + this.wait_call(this.odoo.call("scan_document", data)); }, on_back: () => { - this.state_to("init"); - this.reset_notification(); + if ( + _.isEmpty(this.filter_location()) && + _.isEmpty(this.picking()) + ) { + // No filtering back to scan_dock + this.wait_call(this.odoo.call("scan_dock", {barcode: ""})); + } else { + // Stay on scan_document but without filtering + this.wait_call( + this.odoo.call("scan_document", { + barcode: "", + shipment_advice_id: this.shipment().id, + }) + ); + } }, on_go2loading_list: () => { this.wait_call( @@ -451,8 +486,13 @@ const DeliveryShipment = { this.state_set_data({filter_name: scanned.text}); }, on_back: () => { - this.state_to("scan_document"); - this.reset_notification(); + const data = { + barcode: "", + shipment_advice_id: this.shipment().id, + picking_id: this.picking("scan_document").id, + location_id: this.filter_location("scan_document").id, + }; + this.wait_call(this.odoo.call("scan_document", data)); }, on_back2picking: (picking) => { this.wait_call( From 561dd2bb7a82c8f9c4d3c0b022d289a51c2a8e3b Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Fri, 7 Jul 2023 09:03:03 +0200 Subject: [PATCH 003/133] shopfloor: add some error messages --- shopfloor/actions/message.py | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/shopfloor/actions/message.py b/shopfloor/actions/message.py index b03987d6a6..cbe407dd62 100644 --- a/shopfloor/actions/message.py +++ b/shopfloor/actions/message.py @@ -429,6 +429,16 @@ def product_not_found_in_pickings(self): "body": _("No transfer found for this product."), } + def product_not_found_in_location_or_transfer(self, product, location, picking): + return { + "message_type": "error", + "body": _( + "Product {} not found in location {} or transfer {}.".format( + product.name, location.name, picking.name + ) + ), + } + def x_not_found_or_already_in_dest_package(self, message_code): return { "message_type": "warning", @@ -508,6 +518,20 @@ def lot_not_found_in_pickings(self): "body": _("No transfer found for this lot."), } + def lot_not_found_in_location(self, lot, location): + return { + "message_type": "error", + "body": _("Lot {} not found in location {}").format( + lot.name, location.name + ), + } + + def lot_not_found_in_picking(self, lot, picking): + return { + "message_type": "error", + "body": _("Lot {} not found in transfer {}").format(lot.name, picking.name), + } + def batch_transfer_complete(self): return { "message_type": "success", @@ -716,6 +740,22 @@ def package_change_error(self, package, error_msg): "body": _("Package {} cannot be used: {} ").format(package.name, error_msg), } + def package_not_found_in_location(self, package, location): + return { + "message_type": "error", + "body": _("Package {} not found in location {}").format( + package.name, location.name + ), + } + + def package_not_found_in_picking(self, package, picking): + return { + "message_type": "error", + "body": _("Package {} not found in transfer {}").format( + package.name, picking.name + ), + } + def cannot_change_lot_already_picked(self, lot): return { "message_type": "error", From 8663d3e57687291b4b9ba11253c8a5824660e354 Mon Sep 17 00:00:00 2001 From: JuMiSanAr Date: Thu, 27 Jul 2023 09:47:34 +0200 Subject: [PATCH 004/133] shopfloor: prevent splitting line if negative demand --- shopfloor/models/stock_move_line.py | 1 + 1 file changed, 1 insertion(+) diff --git a/shopfloor/models/stock_move_line.py b/shopfloor/models/stock_move_line.py index 3199389140..5ebdb924a4 100644 --- a/shopfloor/models/stock_move_line.py +++ b/shopfloor/models/stock_move_line.py @@ -153,6 +153,7 @@ def _split_qty_to_be_done(self, qty_done, split_partial=True, **split_default_va :param split_partial: split if qty is less than expected otherwise rely on a backorder. """ + assert self.product_uom_qty >= 0, "The demand cannot be negative" # store a new line if we have split our line (not enough qty) new_line = self.env["stock.move.line"] rounding = self.product_uom_id.rounding From b2ce1bd25f6ab05bedff577ca26ccf8ddab98a30 Mon Sep 17 00:00:00 2001 From: JuMiSanAr Date: Tue, 25 Apr 2023 08:16:54 +0200 Subject: [PATCH 005/133] shopfloor_checkout: show list of products after scanning lot or line --- shopfloor/services/checkout.py | 22 ++++++++++++++----- shopfloor/tests/test_checkout_scan_line.py | 3 ++- .../test_checkout_select_package_base.py | 3 ++- .../tests/test_checkout_scan_line.py | 4 +++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/shopfloor/services/checkout.py b/shopfloor/services/checkout.py index d9339ec7d5..b227d96e16 100644 --- a/shopfloor/services/checkout.py +++ b/shopfloor/services/checkout.py @@ -486,9 +486,9 @@ def _select_lines_from_package( return self._response_for_select_package(picking, lines) def _select_lines_from_product( - self, picking, selection_lines, product, prefill_qty=1, **kw + self, picking, selection_lines, product, prefill_qty=1, check_lot=True, **kw ): - if product.tracking in ("lot", "serial"): + if product.tracking in ("lot", "serial") and check_lot: return self._response_for_select_line( picking, message=self.msg_store.scan_lot_on_product_tracked_by_lot() ) @@ -570,8 +570,14 @@ def _select_lines_from_lot( picking, selection_lines, packages, prefill_qty=prefill_qty, **kw ) - self._select_lines(lines, prefill_qty=prefill_qty) - return self._response_for_select_package(picking, lines) + first_allowed_line = fields.first(lines) + return self._select_lines_from_product( + picking, + selection_lines, + first_allowed_line.product_id, + prefill_qty=prefill_qty, + check_lot=False, + ) def _select_lines_from_serial(self, picking, selection_lines, lot, **kw): # Search for serial number is actually the same as searching for lot (as of v14...) @@ -634,8 +640,12 @@ def _select_line_move_line(self, picking, selection_lines, move_line): return self._select_lines_from_package( picking, selection_lines, move_line.package_id ) - self._select_lines(move_line) - return self._response_for_select_package(picking, move_line) + + related_lines = selection_lines.filtered( + lambda l: not l.package_id and l.product_id != move_line.product_id + ) + lines = self._select_lines(move_line, related_lines=related_lines) + return self._response_for_select_package(picking, lines) def select_line(self, picking_id, package_id=None, move_line_id=None): """Select move lines of the stock picking diff --git a/shopfloor/tests/test_checkout_scan_line.py b/shopfloor/tests/test_checkout_scan_line.py index 1f02ebd9ec..b79efcbf15 100644 --- a/shopfloor/tests/test_checkout_scan_line.py +++ b/shopfloor/tests/test_checkout_scan_line.py @@ -118,7 +118,8 @@ def test_scan_line_product_lot_ok(self): picking.action_assign() first_line = picking.move_line_ids[0] lot = first_line.lot_id - self._test_scan_line_ok(lot.name, first_line) + related_lines = picking.move_line_ids - first_line + self._test_scan_line_ok(lot.name, first_line, related_lines) def test_scan_line_product_in_one_package_all_package_lines_ok(self): picking = self._create_picking( diff --git a/shopfloor/tests/test_checkout_select_package_base.py b/shopfloor/tests/test_checkout_select_package_base.py index a9ba7f128a..5f4ffe42ce 100644 --- a/shopfloor/tests/test_checkout_select_package_base.py +++ b/shopfloor/tests/test_checkout_select_package_base.py @@ -61,4 +61,5 @@ def _assert_selected( ) for line in unselected_lines + related_lines: self.assertEqual(line.qty_done, 0) - self._assert_selected_response(response, selected_lines, message=message, **kw) + package_lines = selected_lines + related_lines + self._assert_selected_response(response, package_lines, message=message, **kw) diff --git a/shopfloor_packing_info/tests/test_checkout_scan_line.py b/shopfloor_packing_info/tests/test_checkout_scan_line.py index 23bd165292..2d0658baf7 100644 --- a/shopfloor_packing_info/tests/test_checkout_scan_line.py +++ b/shopfloor_packing_info/tests/test_checkout_scan_line.py @@ -27,5 +27,7 @@ def test_scan_line_package_ok_packing_info_filled_info(self): picking.action_assign() move_line = move1.move_line_ids self._test_scan_line_ok( - move_line.package_id.name, move_line, packing_info=packing_info_text + move_line.package_id.name, + move_line, + packing_info=packing_info_text, ) From 257f92ac5042045ed5d931bebed8f954d0eab705 Mon Sep 17 00:00:00 2001 From: JuMiSanAr Date: Thu, 27 Jul 2023 09:48:25 +0200 Subject: [PATCH 006/133] shopfloor_reception: prevent creating lines with negative demand --- shopfloor/models/stock_move_line.py | 3 ++- shopfloor_reception/services/reception.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/shopfloor/models/stock_move_line.py b/shopfloor/models/stock_move_line.py index 5ebdb924a4..e70ae50307 100644 --- a/shopfloor/models/stock_move_line.py +++ b/shopfloor/models/stock_move_line.py @@ -153,7 +153,8 @@ def _split_qty_to_be_done(self, qty_done, split_partial=True, **split_default_va :param split_partial: split if qty is less than expected otherwise rely on a backorder. """ - assert self.product_uom_qty >= 0, "The demand cannot be negative" + if self.product_uom_qty < 0: + raise UserError(_("The demand cannot be negative")) # store a new line if we have split our line (not enough qty) new_line = self.env["stock.move.line"] rounding = self.product_uom_id.rounding diff --git a/shopfloor_reception/services/reception.py b/shopfloor_reception/services/reception.py index 971b3f07d1..c0fec83d7d 100644 --- a/shopfloor_reception/services/reception.py +++ b/shopfloor_reception/services/reception.py @@ -261,7 +261,7 @@ def _scan_line__find_or_create_line(self, picking, move, qty_done=1): # the remaining quantity to do of its move. line.product_uom_qty = move.product_uom_qty - move.quantity_done else: - qty_todo_remaining = move.product_uom_qty - move.quantity_done + qty_todo_remaining = max(0, move.product_uom_qty - move.quantity_done) values = move._prepare_move_line_vals(quantity=qty_todo_remaining) line = self.env["stock.move.line"].create(values) return self._scan_line__assign_user(picking, line, qty_done) From 57e1dde2acd0126652dcafa46b7847c86dd35f96 Mon Sep 17 00:00:00 2001 From: Michael Tietz Date: Wed, 19 Jul 2023 05:05:39 +0200 Subject: [PATCH 007/133] [IMP] stock_warehouse_flow: assign_picking only if needed Do not call assign_picking on apply if it is getting called from action_confirm --- stock_warehouse_flow/README.rst | 6 +++--- stock_warehouse_flow/models/stock_move.py | 6 +++++- stock_warehouse_flow/models/stock_warehouse_flow.py | 13 +++++++------ stock_warehouse_flow/static/description/index.html | 4 ++-- stock_warehouse_flow_release/README.rst | 6 +++--- .../static/description/index.html | 4 ++-- .../tests/test_warehouse_flow_release.py | 3 +++ 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/stock_warehouse_flow/README.rst b/stock_warehouse_flow/README.rst index f6073ca559..29a677bab2 100644 --- a/stock_warehouse_flow/README.rst +++ b/stock_warehouse_flow/README.rst @@ -19,9 +19,9 @@ Stock Warehouse Flow .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/wms-14-0/wms-14-0-stock_warehouse_flow :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/285/14.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/wms&target_branch=14.0 + :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| diff --git a/stock_warehouse_flow/models/stock_move.py b/stock_warehouse_flow/models/stock_move.py index d8ad94c7a2..826b18a562 100644 --- a/stock_warehouse_flow/models/stock_move.py +++ b/stock_warehouse_flow/models/stock_move.py @@ -17,7 +17,11 @@ def _action_confirm(self, merge=True, merge_into=False): if not move._apply_flow_on_action_confirm(): move_ids_to_confirm.append(move.id) continue - move_ids_to_confirm += FLOW._search_and_apply_for_move(move).ids + # Do not assign a picking within the _apply_on_move method + # because it gets called later from _action_confirm itself + move_ids_to_confirm += FLOW._search_and_apply_for_move( + move, assign_picking=False + ).ids moves_to_confirm = self.browse(move_ids_to_confirm) return super(StockMove, moves_to_confirm)._action_confirm( merge=merge, merge_into=merge_into diff --git a/stock_warehouse_flow/models/stock_warehouse_flow.py b/stock_warehouse_flow/models/stock_warehouse_flow.py index f56359ad2e..3e031fc5d9 100644 --- a/stock_warehouse_flow/models/stock_warehouse_flow.py +++ b/stock_warehouse_flow/models/stock_warehouse_flow.py @@ -421,14 +421,14 @@ def _search_for_move(self, move): return self.search(domain) @api.model - def _search_and_apply_for_move(self, move): + def _search_and_apply_for_move(self, move, assign_picking=True): move.ensure_one() flows = self._search_for_move(move) if not flows: return move - return flows.apply_on_move(move) + return flows.apply_on_move(move, assign_picking) - def apply_on_move(self, move): + def apply_on_move(self, move, assign_picking=True): move_ids = [] flows = self for flow in self: @@ -439,7 +439,7 @@ def apply_on_move(self, move): # Try to apply the rest of the flows to the split move for split_move in split_moves: move_ids += (flows - flow).apply_on_move(split_move).ids - flow._apply_on_move(move) + flow._apply_on_move(move, assign_picking) return move.browse(move_ids) raise UserError( _( @@ -516,7 +516,7 @@ def split_move(self, move): return self._split_move_simple(move) return split_moves - def _apply_on_move(self, move): + def _apply_on_move(self, move, assign_picking=True): """Apply the flow configuration on the move.""" if not self: return False @@ -530,7 +530,8 @@ def _apply_on_move(self, move): ) move.procure_method = rule.procure_method move.rule_id = rule - move._assign_picking() + if assign_picking: + move._assign_picking() def write(self, vals): res = super().write(vals) diff --git a/stock_warehouse_flow/static/description/index.html b/stock_warehouse_flow/static/description/index.html index 5c08426744..7ef8ec6d18 100644 --- a/stock_warehouse_flow/static/description/index.html +++ b/stock_warehouse_flow/static/description/index.html @@ -3,7 +3,7 @@ - + Stock Warehouse Flow + + +
+

Shopfloor Purchase Base

+ + +

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

+

This is a glue module between shopfloor and l10n_eu_product_adr

+

Table of contents

+ +
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • MT Software
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+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.

+

Current maintainer:

+

mt-software-de

+

This module is part of the OCA/wms project on GitHub.

+

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

+
+
+
+ + diff --git a/shopfloor_purchase_base/tests/__init__.py b/shopfloor_purchase_base/tests/__init__.py new file mode 100644 index 0000000000..c6a5342420 --- /dev/null +++ b/shopfloor_purchase_base/tests/__init__.py @@ -0,0 +1 @@ +from . import test_actions_data diff --git a/shopfloor_purchase_base/tests/test_actions_data.py b/shopfloor_purchase_base/tests/test_actions_data.py new file mode 100644 index 0000000000..a8389b07aa --- /dev/null +++ b/shopfloor_purchase_base/tests/test_actions_data.py @@ -0,0 +1,29 @@ +# Copyright 2023 Michael Tietz (MT Software) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from odoo.addons.shopfloor.tests.test_actions_data_base import ActionsDataCaseBase + + +class ActionsDataPurchase(ActionsDataCaseBase): + def test_data_purchase_order(self): + picking = self.env["stock.picking"].search( + [("purchase_id", "!=", False)], limit=1 + ) + purchase = picking.purchase_id + purchase.sudo().partner_ref = "test" + expected_purchase_data = { + "id": purchase.id, + "name": purchase.name, + "partner_ref": purchase.partner_ref, + } + purchase_data = self.data.purchase_order(purchase) + self.assertDictEqual(expected_purchase_data, purchase_data) + self.assert_schema(self.schema.purchase_order(), purchase_data) + data = self.data.picking(picking) + self.assertTrue("purchase_order" not in data) + expected_picking_data = data + expected_picking_data.update({"purchase_order": purchase_data}) + self.assert_schema(self.schema.picking(), expected_picking_data) + self.assertDictEqual( + expected_picking_data, + self.data.picking(picking, with_purchase_order=True), + ) From 204f933a52ae2a1a56eaaefbbafd5ba503b51b87 Mon Sep 17 00:00:00 2001 From: Michael Tietz Date: Thu, 10 Aug 2023 21:35:14 +0200 Subject: [PATCH 028/133] [IMP] shopfloor: compute package move_line_count when needed If you want to get the data for a package it always computes the move_line_count. This is very bad for perf on scenario - like zone picking - where you have a long list of moves with packages w/o needing such information. The only scenario which is using the move_line_count from the package data is the checkout. So i think it is convenient to not compute it by default only if it is really needed. --- shopfloor/actions/data.py | 2 +- shopfloor/services/checkout.py | 1 + shopfloor/tests/test_actions_data.py | 35 ++++++++++++++++--- shopfloor/tests/test_actions_data_detail.py | 18 +++++++--- shopfloor/tests/test_checkout_base.py | 6 ++-- shopfloor/tests/test_checkout_list_package.py | 4 ++- .../tests/test_actions_data.py | 1 - 7 files changed, 53 insertions(+), 14 deletions(-) diff --git a/shopfloor/actions/data.py b/shopfloor/actions/data.py index 10f893a9d1..a87bd4674f 100644 --- a/shopfloor/actions/data.py +++ b/shopfloor/actions/data.py @@ -102,7 +102,7 @@ def package(self, record, picking=None, with_packaging=False, **kw): ] operation_progress = self._get_operation_progress(domain) data.update({"operation_progress": operation_progress}) - if data and picking: + if kw.get("with_package_move_line_count") and data and picking: move_line_count = self.env["stock.move.line"].search_count( [ ("picking_id.picking_type_id", "=", picking.picking_type_id.id), diff --git a/shopfloor/services/checkout.py b/shopfloor/services/checkout.py index 14e9592b62..a311b3ee4f 100644 --- a/shopfloor/services/checkout.py +++ b/shopfloor/services/checkout.py @@ -136,6 +136,7 @@ def _response_for_select_dest_package(self, picking, move_lines, message=None): packages.with_context(picking_id=picking.id).sorted(), picking=picking, with_packaging=True, + with_package_move_line_count=True, ) return self._response( next_state="select_dest_package", diff --git a/shopfloor/tests/test_actions_data.py b/shopfloor/tests/test_actions_data.py index 08f181d9ea..71d584affe 100644 --- a/shopfloor/tests/test_actions_data.py +++ b/shopfloor/tests/test_actions_data.py @@ -80,6 +80,28 @@ def test_data_package(self): package.package_storage_type_id = self.storage_type_pallet data = self.data.package(package, picking=self.picking, with_packaging=True) self.assert_schema(self.schema.package(with_packaging=True), data) + expected = { + "id": package.id, + "name": package.name, + "packaging": self._expected_packaging(package.packaging_id), + "storage_type": self._expected_storage_type( + package.package_storage_type_id + ), + "weight": 20.0, + } + self.assertDictEqual(data, expected) + + def test_data_package_with_move_line_count(self): + package = self.move_a.move_line_ids.package_id + package.packaging_id = self.packaging.id + package.package_storage_type_id = self.storage_type_pallet + data = self.data.package( + package, + picking=self.picking, + with_packaging=True, + with_package_move_line_count=True, + ) + self.assert_schema(self.schema.package(with_packaging=True), data) expected = { "id": package.id, "name": package.name, @@ -202,14 +224,12 @@ def test_data_move_line_package(self): "package_src": { "id": move_line.package_id.id, "name": move_line.package_id.name, - "move_line_count": 1, "weight": 20.0, "storage_type": None, }, "package_dest": { "id": result_package.id, "name": result_package.name, - "move_line_count": 1, "weight": 6.0, "storage_type": None, }, @@ -219,6 +239,10 @@ def test_data_move_line_package(self): "progress": 30.0, } self.assertDictEqual(data, expected) + data = self.data.move_line(move_line, with_package_move_line_count=True) + expected["package_src"]["move_line_count"] = 1 + expected["package_dest"]["move_line_count"] = 1 + self.assertDictEqual(data, expected) def test_data_move_line_lot(self): move_line = self.move_b.move_line_ids @@ -263,14 +287,12 @@ def test_data_move_line_package_lot(self): "package_src": { "id": move_line.package_id.id, "name": move_line.package_id.name, - "move_line_count": 2, "weight": 30, "storage_type": None, }, "package_dest": { "id": move_line.result_package_id.id, "name": move_line.result_package_id.name, - "move_line_count": 2, "weight": 0, "storage_type": None, }, @@ -280,6 +302,11 @@ def test_data_move_line_package_lot(self): "progress": 0.0, } self.assertDictEqual(data, expected) + data = self.data.move_line(move_line, with_package_move_line_count=True) + self.assert_schema(self.schema.move_line(), data) + expected["package_src"]["move_line_count"] = 2 + expected["package_dest"]["move_line_count"] = 2 + self.assertDictEqual(data, expected) def test_data_move_line_raw(self): move_line = self.move_d.move_line_ids diff --git a/shopfloor/tests/test_actions_data_detail.py b/shopfloor/tests/test_actions_data_detail.py index 4875abb434..39ac1822f0 100644 --- a/shopfloor/tests/test_actions_data_detail.py +++ b/shopfloor/tests/test_actions_data_detail.py @@ -80,7 +80,6 @@ def test_data_package(self): "name": package.location_id.display_name, }, "name": package.name, - "move_line_count": 2, "packaging": self.data_detail.packaging(package.packaging_id), "weight": 20.0, "pickings": self.data_detail.pickings(pickings), @@ -91,6 +90,11 @@ def test_data_package(self): }, } self.assertDictEqual(data, expected) + data = self.data_detail.package_detail( + package, picking=self.picking, with_package_move_line_count=True + ) + expected.update({"move_line_count": 2}) + self.assertDictEqual(data, expected) def test_data_picking(self): picking = self.picking @@ -185,14 +189,12 @@ def test_data_move_line_package(self): "package_src": { "id": move_line.package_id.id, "name": move_line.package_id.name, - "move_line_count": 1, "weight": 20.0, "storage_type": None, }, "package_dest": { "id": result_package.id, "name": result_package.name, - "move_line_count": 1, "weight": 6.0, "storage_type": None, }, @@ -202,6 +204,10 @@ def test_data_move_line_package(self): "progress": 30.0, } self.assertDictEqual(data, expected) + data = self.data_detail.move_line(move_line, with_package_move_line_count=True) + expected["package_src"]["move_line_count"] = 1 + expected["package_dest"]["move_line_count"] = 1 + self.assertDictEqual(data, expected) def test_data_move_line_lot(self): move_line = self.move_b.move_line_ids @@ -247,14 +253,12 @@ def test_data_move_line_package_lot(self): "package_src": { "id": move_line.package_id.id, "name": move_line.package_id.name, - "move_line_count": 2, "weight": 30.0, "storage_type": None, }, "package_dest": { "id": move_line.result_package_id.id, "name": move_line.result_package_id.name, - "move_line_count": 2, "weight": 0.0, "storage_type": None, }, @@ -264,6 +268,10 @@ def test_data_move_line_package_lot(self): "progress": 0.0, } self.assertDictEqual(data, expected) + data = self.data_detail.move_line(move_line, with_package_move_line_count=True) + expected["package_src"]["move_line_count"] = 2 + expected["package_dest"]["move_line_count"] = 2 + self.assertDictEqual(data, expected) def test_data_move_line_raw(self): move_line = self.move_d.move_line_ids diff --git a/shopfloor/tests/test_checkout_base.py b/shopfloor/tests/test_checkout_base.py index f4f7a16e86..120e1e71af 100644 --- a/shopfloor/tests/test_checkout_base.py +++ b/shopfloor/tests/test_checkout_base.py @@ -40,8 +40,10 @@ def _picking_summary_data(self, picking): def _move_line_data(self, move_line): return self.data.move_line(move_line) - def _package_data(self, package, picking): - return self.data.package(package, picking=picking, with_packaging=True) + def _package_data(self, package, picking, **kwargs): + return self.data.package( + package, picking=picking, with_packaging=True, **kwargs + ) def _packaging_data(self, packaging): return self.data.packaging(packaging) diff --git a/shopfloor/tests/test_checkout_list_package.py b/shopfloor/tests/test_checkout_list_package.py index 3144767585..6f5db8134a 100644 --- a/shopfloor/tests/test_checkout_list_package.py +++ b/shopfloor/tests/test_checkout_list_package.py @@ -26,7 +26,9 @@ def _assert_response_select_dest_package( "picking": picking_data, "packages": [ self._package_data( - package.with_context(picking_id=picking.id), picking + package.with_context(picking_id=picking.id), + picking, + with_package_move_line_count=True, ) for package in packages ], diff --git a/shopfloor_dangerous_goods/tests/test_actions_data.py b/shopfloor_dangerous_goods/tests/test_actions_data.py index 31061934d8..d8b08d0939 100644 --- a/shopfloor_dangerous_goods/tests/test_actions_data.py +++ b/shopfloor_dangerous_goods/tests/test_actions_data.py @@ -62,7 +62,6 @@ def test_data_package(self): expected = { "id": package.id, "name": package.name, - "move_line_count": 2, "packaging": self._expected_packaging(package.packaging_id), "storage_type": self._expected_storage_type( package.package_storage_type_id From 4c416bb281feef6e6156d48b9405fe3c2f0a26a7 Mon Sep 17 00:00:00 2001 From: Michael Tietz Date: Wed, 15 Mar 2023 08:28:55 +0100 Subject: [PATCH 029/133] [ADD] shopfloor_reception_purchase_partner_ref Show the partner_ref field of a purchase order on the reception scenario --- .../shopfloor_reception_purchase_partner_ref | 1 + .../setup.py | 6 + ...loor_reception_purchase_partner_ref_mobile | 1 + .../setup.py | 6 + .../README.rst | 82 ++++ .../__init__.py | 1 + .../__manifest__.py | 11 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 2 + .../services/__init__.py | 1 + .../services/reception.py | 12 + .../static/description/index.html | 422 ++++++++++++++++++ .../tests/__init__.py | 1 + .../tests/test_data.py | 13 + .../README.rst | 82 ++++ .../__init__.py | 0 .../__manifest__.py | 16 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 2 + .../static/description/index.html | 422 ++++++++++++++++++ .../static/src/scenario/reception.js | 32 ++ .../templates/assets.xml | 20 + 22 files changed, 1135 insertions(+) create mode 120000 setup/shopfloor_reception_purchase_partner_ref/odoo/addons/shopfloor_reception_purchase_partner_ref create mode 100644 setup/shopfloor_reception_purchase_partner_ref/setup.py create mode 120000 setup/shopfloor_reception_purchase_partner_ref_mobile/odoo/addons/shopfloor_reception_purchase_partner_ref_mobile create mode 100644 setup/shopfloor_reception_purchase_partner_ref_mobile/setup.py create mode 100644 shopfloor_reception_purchase_partner_ref/README.rst create mode 100644 shopfloor_reception_purchase_partner_ref/__init__.py create mode 100644 shopfloor_reception_purchase_partner_ref/__manifest__.py create mode 100644 shopfloor_reception_purchase_partner_ref/readme/CONTRIBUTORS.rst create mode 100644 shopfloor_reception_purchase_partner_ref/readme/DESCRIPTION.rst create mode 100644 shopfloor_reception_purchase_partner_ref/services/__init__.py create mode 100644 shopfloor_reception_purchase_partner_ref/services/reception.py create mode 100644 shopfloor_reception_purchase_partner_ref/static/description/index.html create mode 100644 shopfloor_reception_purchase_partner_ref/tests/__init__.py create mode 100644 shopfloor_reception_purchase_partner_ref/tests/test_data.py create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/README.rst create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/__init__.py create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/__manifest__.py create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/readme/CONTRIBUTORS.rst create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/readme/DESCRIPTION.rst create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/static/description/index.html create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/static/src/scenario/reception.js create mode 100644 shopfloor_reception_purchase_partner_ref_mobile/templates/assets.xml diff --git a/setup/shopfloor_reception_purchase_partner_ref/odoo/addons/shopfloor_reception_purchase_partner_ref b/setup/shopfloor_reception_purchase_partner_ref/odoo/addons/shopfloor_reception_purchase_partner_ref new file mode 120000 index 0000000000..fa30757d85 --- /dev/null +++ b/setup/shopfloor_reception_purchase_partner_ref/odoo/addons/shopfloor_reception_purchase_partner_ref @@ -0,0 +1 @@ +../../../../shopfloor_reception_purchase_partner_ref \ No newline at end of file diff --git a/setup/shopfloor_reception_purchase_partner_ref/setup.py b/setup/shopfloor_reception_purchase_partner_ref/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/shopfloor_reception_purchase_partner_ref/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/shopfloor_reception_purchase_partner_ref_mobile/odoo/addons/shopfloor_reception_purchase_partner_ref_mobile b/setup/shopfloor_reception_purchase_partner_ref_mobile/odoo/addons/shopfloor_reception_purchase_partner_ref_mobile new file mode 120000 index 0000000000..2b0ae97b9b --- /dev/null +++ b/setup/shopfloor_reception_purchase_partner_ref_mobile/odoo/addons/shopfloor_reception_purchase_partner_ref_mobile @@ -0,0 +1 @@ +../../../../shopfloor_reception_purchase_partner_ref_mobile \ No newline at end of file diff --git a/setup/shopfloor_reception_purchase_partner_ref_mobile/setup.py b/setup/shopfloor_reception_purchase_partner_ref_mobile/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/shopfloor_reception_purchase_partner_ref_mobile/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/shopfloor_reception_purchase_partner_ref/README.rst b/shopfloor_reception_purchase_partner_ref/README.rst new file mode 100644 index 0000000000..cdabcfc070 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/README.rst @@ -0,0 +1,82 @@ +======================================== +Shopfloor Reception Purchase Partner Ref +======================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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 + :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 + :target: https://github.com/OCA/wms/tree/14.0/shopfloor_reception_purchase_partner_ref + :alt: OCA/wms +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/wms-14-0/wms-14-0-shopfloor_reception_purchase_partner_ref + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/wms&target_branch=14.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Shopfloor extension of the reception scenario. +Show the purchase.order partner_ref field on the picking views + +**Table of contents** + +.. contents:: + :local: + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* MT Software + +Contributors +~~~~~~~~~~~~ + +* Michael Tietz (MT Software) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +.. |maintainer-mt-software-de| image:: https://github.com/mt-software-de.png?size=40px + :target: https://github.com/mt-software-de + :alt: mt-software-de + +Current `maintainer `__: + +|maintainer-mt-software-de| + +This module is part of the `OCA/wms `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/shopfloor_reception_purchase_partner_ref/__init__.py b/shopfloor_reception_purchase_partner_ref/__init__.py new file mode 100644 index 0000000000..99464a7510 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/__init__.py @@ -0,0 +1 @@ +from . import services diff --git a/shopfloor_reception_purchase_partner_ref/__manifest__.py b/shopfloor_reception_purchase_partner_ref/__manifest__.py new file mode 100644 index 0000000000..828c695653 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/__manifest__.py @@ -0,0 +1,11 @@ +{ + "name": "Shopfloor Reception Purchase Partner Ref", + "summary": "Adds the purchase partner ref field to shopfloor reception scenario", + "version": "14.0.1.0.0", + "category": "Inventory", + "website": "https://github.com/OCA/wms", + "author": "MT Software, Odoo Community Association (OCA)", + "maintainers": ["mt-software-de"], + "license": "AGPL-3", + "depends": ["shopfloor_purchase_base", "shopfloor_reception", "purchase_stock"], +} diff --git a/shopfloor_reception_purchase_partner_ref/readme/CONTRIBUTORS.rst b/shopfloor_reception_purchase_partner_ref/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..446fd1d576 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Michael Tietz (MT Software) diff --git a/shopfloor_reception_purchase_partner_ref/readme/DESCRIPTION.rst b/shopfloor_reception_purchase_partner_ref/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..640124599b --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +Shopfloor extension of the reception scenario. +Show the purchase.order partner_ref field on the picking views diff --git a/shopfloor_reception_purchase_partner_ref/services/__init__.py b/shopfloor_reception_purchase_partner_ref/services/__init__.py new file mode 100644 index 0000000000..aa19bba8ce --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/services/__init__.py @@ -0,0 +1 @@ +from . import reception diff --git a/shopfloor_reception_purchase_partner_ref/services/reception.py b/shopfloor_reception_purchase_partner_ref/services/reception.py new file mode 100644 index 0000000000..94c6236d3b --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/services/reception.py @@ -0,0 +1,12 @@ +# Copyright 2023 Michael Tietz (MT Software) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from odoo.addons.component.core import Component + + +class Reception(Component): + _inherit = "shopfloor.reception" + + def _data_for_stock_picking(self, picking, with_lines=False, **kw): + if "with_purchase_order" not in kw: + kw["with_purchase_order"] = True + return super()._data_for_stock_picking(picking, with_lines, **kw) diff --git a/shopfloor_reception_purchase_partner_ref/static/description/index.html b/shopfloor_reception_purchase_partner_ref/static/description/index.html new file mode 100644 index 0000000000..26a20d8ba1 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/static/description/index.html @@ -0,0 +1,422 @@ + + + + + + +Shopfloor Reception Purchase Partner Ref + + + +
+

Shopfloor Reception Purchase Partner Ref

+ + +

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

+

Shopfloor extension of the reception scenario. +Show the purchase.order partner_ref field on the picking views

+

Table of contents

+ +
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • MT Software
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+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.

+

Current maintainer:

+

mt-software-de

+

This module is part of the OCA/wms project on GitHub.

+

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

+
+
+
+ + diff --git a/shopfloor_reception_purchase_partner_ref/tests/__init__.py b/shopfloor_reception_purchase_partner_ref/tests/__init__.py new file mode 100644 index 0000000000..6ed6a549ad --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/tests/__init__.py @@ -0,0 +1 @@ +from . import test_data diff --git a/shopfloor_reception_purchase_partner_ref/tests/test_data.py b/shopfloor_reception_purchase_partner_ref/tests/test_data.py new file mode 100644 index 0000000000..9bcfdbfd98 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref/tests/test_data.py @@ -0,0 +1,13 @@ +# Copyright 2023 Michael Tietz (MT Software) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from odoo.addons.shopfloor_reception.tests.common import CommonCase + + +class TestDataForPicking(CommonCase): + def test_data_for_picking(self): + picking = self._create_picking() + data = self.service._data_for_stock_picking(picking) + expected = self.data.picking( + picking, **{"with_progress": True, "with_purchase_order": True} + ) + self.assertDictEqual(expected, data) diff --git a/shopfloor_reception_purchase_partner_ref_mobile/README.rst b/shopfloor_reception_purchase_partner_ref_mobile/README.rst new file mode 100644 index 0000000000..7c1dc76347 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/README.rst @@ -0,0 +1,82 @@ +=============================================== +Shopfloor Reception Purchase Partner Ref Mobile +=============================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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 + :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 + :target: https://github.com/OCA/wms/tree/14.0/shopfloor_reception_purchase_partner_ref_mobile + :alt: OCA/wms +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/wms-14-0/wms-14-0-shopfloor_reception_purchase_partner_ref_mobile + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/wms&target_branch=14.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Shopfloor extensio of the reception scenario. +Show the purchase.order partner_ref field on the picking views + +**Table of contents** + +.. contents:: + :local: + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* MT Software + +Contributors +~~~~~~~~~~~~ + +* Michael Tietz (MT Software) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +.. |maintainer-mt-software-de| image:: https://github.com/mt-software-de.png?size=40px + :target: https://github.com/mt-software-de + :alt: mt-software-de + +Current `maintainer `__: + +|maintainer-mt-software-de| + +This module is part of the `OCA/wms `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/shopfloor_reception_purchase_partner_ref_mobile/__init__.py b/shopfloor_reception_purchase_partner_ref_mobile/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/shopfloor_reception_purchase_partner_ref_mobile/__manifest__.py b/shopfloor_reception_purchase_partner_ref_mobile/__manifest__.py new file mode 100644 index 0000000000..79e048c797 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/__manifest__.py @@ -0,0 +1,16 @@ +{ + "name": "Shopfloor Reception Purchase Partner Ref Mobile", + "summary": "Adds the purchase partner ref field to shopfloor reception scenario", + "version": "14.0.1.0.0", + "category": "Inventory", + "website": "https://github.com/OCA/wms", + "author": "MT Software, Odoo Community Association (OCA)", + "maintainers": ["mt-software-de"], + "license": "AGPL-3", + "depends": [ + "shopfloor_reception_purchase_partner_ref", + "shopfloor_reception_mobile", + ], + "data": ["templates/assets.xml"], + "auto_install": True, +} diff --git a/shopfloor_reception_purchase_partner_ref_mobile/readme/CONTRIBUTORS.rst b/shopfloor_reception_purchase_partner_ref_mobile/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..446fd1d576 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Michael Tietz (MT Software) diff --git a/shopfloor_reception_purchase_partner_ref_mobile/readme/DESCRIPTION.rst b/shopfloor_reception_purchase_partner_ref_mobile/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..2060028106 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +Shopfloor extensio of the reception scenario. +Show the purchase.order partner_ref field on the picking views diff --git a/shopfloor_reception_purchase_partner_ref_mobile/static/description/index.html b/shopfloor_reception_purchase_partner_ref_mobile/static/description/index.html new file mode 100644 index 0000000000..1847c8edcc --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/static/description/index.html @@ -0,0 +1,422 @@ + + + + + + +Shopfloor Reception Purchase Partner Ref Mobile + + + +
+

Shopfloor Reception Purchase Partner Ref Mobile

+ + +

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

+

Shopfloor extensio of the reception scenario. +Show the purchase.order partner_ref field on the picking views

+

Table of contents

+ +
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • MT Software
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+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.

+

Current maintainer:

+

mt-software-de

+

This module is part of the OCA/wms project on GitHub.

+

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

+
+
+
+ + diff --git a/shopfloor_reception_purchase_partner_ref_mobile/static/src/scenario/reception.js b/shopfloor_reception_purchase_partner_ref_mobile/static/src/scenario/reception.js new file mode 100644 index 0000000000..476c3c1c05 --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/static/src/scenario/reception.js @@ -0,0 +1,32 @@ +/** + * Copyright 2023 Michael Tietz (MT Software) + * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + */ + +import {process_registry} from "/shopfloor_mobile_base/static/wms/src/services/process_registry.js"; + +const reception_scenario = process_registry.get("reception"); +const select_dest_package_display_name_values = + reception_scenario.component.methods.select_dest_package_display_name_values; +const picking_display_fields = + reception_scenario.component.methods.picking_display_fields; + +const ReceptionPartnerRef = process_registry.extend("reception", { + "methods.select_dest_package_display_name_values": function (rec) { + var values = select_dest_package_display_name_values.bind(this)(rec); + if (rec.purchase_order.partner_ref) { + values.splice(1, 0, rec.purchase_order.partner_ref); + } + return values; + }, + "methods.picking_display_fields": function () { + var fields = picking_display_fields.bind(this)(); + fields.splice(1, 0, { + path: "purchase_order.partner_ref", + label: "Vendor Reference", + }); + return fields; + }, +}); + +process_registry.replace("reception", ReceptionPartnerRef); diff --git a/shopfloor_reception_purchase_partner_ref_mobile/templates/assets.xml b/shopfloor_reception_purchase_partner_ref_mobile/templates/assets.xml new file mode 100644 index 0000000000..552e8ab01a --- /dev/null +++ b/shopfloor_reception_purchase_partner_ref_mobile/templates/assets.xml @@ -0,0 +1,20 @@ + + + + From 73b131bf315df5456d95943401466d4fcd369bfc Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Mon, 21 Aug 2023 10:46:00 +0200 Subject: [PATCH 030/133] shopfloor: fix zone picking scan empty package --- shopfloor/services/zone_picking.py | 11 +++++----- .../tests/test_zone_picking_select_line.py | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/shopfloor/services/zone_picking.py b/shopfloor/services/zone_picking.py index 73b4ec3fb6..a94f4755d1 100644 --- a/shopfloor/services/zone_picking.py +++ b/shopfloor/services/zone_picking.py @@ -594,11 +594,12 @@ def _scan_source_package( package = search.package_from_scan(barcode) if not package: return response, message - if not package.location_id.is_sublocation_of(self.zone_location): - # Package is not in an allowed location - response = self._list_move_lines(self.zone_location) - message = self.msg_store.location_not_allowed() - return response, message + if package.location_id: + if not package.location_id.is_sublocation_of(self.zone_location): + # Package is not in an allowed location + response = self._list_move_lines(self.zone_location) + message = self.msg_store.location_not_allowed() + return response, message move_lines = self._find_location_move_lines( locations=sublocation, package=package diff --git a/shopfloor/tests/test_zone_picking_select_line.py b/shopfloor/tests/test_zone_picking_select_line.py index 2d58a1b761..8a09f75706 100644 --- a/shopfloor/tests/test_zone_picking_select_line.py +++ b/shopfloor/tests/test_zone_picking_select_line.py @@ -276,6 +276,28 @@ def test_scan_source_package_many_products(self): location_first=False, ) + def test_scan_source_empty_package(self): + """Scan source: scanned an empty package.""" + pack_empty = self.env["stock.quant.package"].create({}) + response = self.service.dispatch( + "scan_source", + params={"barcode": pack_empty.name}, + ) + move_lines = self.service._find_location_move_lines( + locations=self.zone_location + ) + move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True) + self.assert_response_select_line( + response, + zone_location=self.zone_location, + picking_type=self.picking_type, + move_lines=move_lines, + message=self.service.msg_store.package_has_no_product_to_take( + pack_empty.name + ), + location_first=False, + ) + def test_scan_source_barcode_package_can_replace_in_line(self): """Scan source: scanned package has no related line but can replace next step 'select_line' expected with confirmation required set. From 6c1474bbf1ff80374abdf3b0033360b78c4765a7 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 21 Aug 2023 14:07:32 +0000 Subject: [PATCH 031/133] shopfloor 14.0.3.5.1 --- shopfloor/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shopfloor/__manifest__.py b/shopfloor/__manifest__.py index e2ff590911..e9bdca2487 100644 --- a/shopfloor/__manifest__.py +++ b/shopfloor/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Shopfloor", "summary": "manage warehouse operations with barcode scanners", - "version": "14.0.3.5.0", + "version": "14.0.3.5.1", "development_status": "Beta", "category": "Inventory", "website": "https://github.com/OCA/wms", From 0a5cb6ae8326bdfc96dd236cd42d8b692f120994 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 21 Aug 2023 14:07:38 +0000 Subject: [PATCH 032/133] [UPD] addons table in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ef2ed7bb80..c30f47dc24 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ addon | version | maintainers | summary [sale_stock_available_to_promise_release](sale_stock_available_to_promise_release/) | 14.0.1.1.1 | | Integration between Sales and Available to Promise Release [sale_stock_available_to_promise_release_cutoff](sale_stock_available_to_promise_release_cutoff/) | 14.0.1.1.1 | | Cutoff management with respect to stock availability [sale_stock_available_to_promise_release_dropshipping](sale_stock_available_to_promise_release_dropshipping/) | 14.0.1.0.0 | | Glue module between sale_stock_available_to_promise_release and stock_dropshipping -[shopfloor](shopfloor/) | 14.0.3.5.0 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) [![simahawk](https://github.com/simahawk.png?size=30px)](https://github.com/simahawk) [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | manage warehouse operations with barcode scanners +[shopfloor](shopfloor/) | 14.0.3.5.1 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) [![simahawk](https://github.com/simahawk.png?size=30px)](https://github.com/simahawk) [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | manage warehouse operations with barcode scanners [shopfloor_base](shopfloor_base/) | 14.0.2.10.1 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) [![simahawk](https://github.com/simahawk.png?size=30px)](https://github.com/simahawk) [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | Core module for creating mobile apps [shopfloor_base_multicompany](shopfloor_base_multicompany/) | 14.0.1.0.0 | | Provide multi-company support and validation to Shopfloor applications. [shopfloor_batch_automatic_creation](shopfloor_batch_automatic_creation/) | 14.0.1.2.0 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) | Create batch transfers for Cluster Picking From 8124332cf232b3ccb9e07c1cdef13f78e137ea13 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 21 Aug 2023 15:20:24 +0000 Subject: [PATCH 033/133] shopfloor 14.0.3.5.2 --- shopfloor/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shopfloor/__manifest__.py b/shopfloor/__manifest__.py index e9bdca2487..ecc65f5e59 100644 --- a/shopfloor/__manifest__.py +++ b/shopfloor/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Shopfloor", "summary": "manage warehouse operations with barcode scanners", - "version": "14.0.3.5.1", + "version": "14.0.3.5.2", "development_status": "Beta", "category": "Inventory", "website": "https://github.com/OCA/wms", From adcddca08f405477bbd97a4af1faa32d06920ee2 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 21 Aug 2023 15:20:29 +0000 Subject: [PATCH 034/133] [UPD] addons table in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c30f47dc24..1e0b121a0f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ addon | version | maintainers | summary [sale_stock_available_to_promise_release](sale_stock_available_to_promise_release/) | 14.0.1.1.1 | | Integration between Sales and Available to Promise Release [sale_stock_available_to_promise_release_cutoff](sale_stock_available_to_promise_release_cutoff/) | 14.0.1.1.1 | | Cutoff management with respect to stock availability [sale_stock_available_to_promise_release_dropshipping](sale_stock_available_to_promise_release_dropshipping/) | 14.0.1.0.0 | | Glue module between sale_stock_available_to_promise_release and stock_dropshipping -[shopfloor](shopfloor/) | 14.0.3.5.1 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) [![simahawk](https://github.com/simahawk.png?size=30px)](https://github.com/simahawk) [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | manage warehouse operations with barcode scanners +[shopfloor](shopfloor/) | 14.0.3.5.2 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) [![simahawk](https://github.com/simahawk.png?size=30px)](https://github.com/simahawk) [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | manage warehouse operations with barcode scanners [shopfloor_base](shopfloor_base/) | 14.0.2.10.1 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) [![simahawk](https://github.com/simahawk.png?size=30px)](https://github.com/simahawk) [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | Core module for creating mobile apps [shopfloor_base_multicompany](shopfloor_base_multicompany/) | 14.0.1.0.0 | | Provide multi-company support and validation to Shopfloor applications. [shopfloor_batch_automatic_creation](shopfloor_batch_automatic_creation/) | 14.0.1.2.0 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) | Create batch transfers for Cluster Picking From a23501266bcadf13b569bf89661349c08dec0807 Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Tue, 22 Aug 2023 08:13:23 +0200 Subject: [PATCH 035/133] s_a_to_promise_release: fix schedule date change --- stock_available_to_promise_release/models/stock_picking.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stock_available_to_promise_release/models/stock_picking.py b/stock_available_to_promise_release/models/stock_picking.py index c640615219..f65c026c67 100644 --- a/stock_available_to_promise_release/models/stock_picking.py +++ b/stock_available_to_promise_release/models/stock_picking.py @@ -160,7 +160,9 @@ def _after_release_set_expected_date(self): new_expected_date = fields.Datetime.add( fields.Datetime.now(), minutes=prep_time ) - move_to_update = self.move_lines.filtered(lambda m: m.state == "assigned") + move_to_update = self.move_lines.filtered( + lambda m: m.state in ["assigned", "confirmed", "partially_available"] + ) move_to_update_ids = move_to_update.ids for origin_moves in move_to_update._get_chained_moves_iterator("move_dest_ids"): move_to_update_ids += origin_moves.ids From fe772ba6158d629cab637f89f5d4717a7fb47f1a Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 22 Aug 2023 08:43:11 +0000 Subject: [PATCH 036/133] [UPD] addons table in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1e0b121a0f..16c26b5fc6 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,11 @@ addon | version | maintainers | summary [stock_available_to_promise_release](stock_available_to_promise_release/) | 14.0.2.1.1 | | Release Operations based on available to promise [stock_available_to_promise_release_dynamic_routing](stock_available_to_promise_release_dynamic_routing/) | 14.0.1.0.0 | | Glue between moves release and dynamic routing [stock_checkout_sync](stock_checkout_sync/) | 14.0.1.1.0 | | Sync location for Checkout operations -[stock_dynamic_routing](stock_dynamic_routing/) | 14.0.1.0.2 | | Dynamic routing of stock moves +[stock_dynamic_routing](stock_dynamic_routing/) | 14.0.1.0.2 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Dynamic routing of stock moves [stock_dynamic_routing_checkout_sync](stock_dynamic_routing_checkout_sync/) | 14.0.1.0.0 | | Glue module for tests when dynamic routing and checkout sync are used [stock_dynamic_routing_reserve_rule](stock_dynamic_routing_reserve_rule/) | 14.0.1.0.1 | | Glue module between dynamic routing and reservation rules -[stock_move_source_relocate](stock_move_source_relocate/) | 14.0.1.1.0 | | Change source location of unavailable moves -[stock_move_source_relocate_dynamic_routing](stock_move_source_relocate_dynamic_routing/) | 14.0.1.0.1 | | Glue module +[stock_move_source_relocate](stock_move_source_relocate/) | 14.0.1.1.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Change source location of unavailable moves +[stock_move_source_relocate_dynamic_routing](stock_move_source_relocate_dynamic_routing/) | 14.0.1.0.1 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Glue module [stock_picking_completion_info](stock_picking_completion_info/) | 14.0.1.1.0 | | Display on current document completion information according to next operations [stock_picking_consolidation_priority](stock_picking_consolidation_priority/) | 14.0.1.1.0 | | Raise priority of all transfers for a chain when started [stock_picking_type_shipping_policy](stock_picking_type_shipping_policy/) | 14.0.1.1.0 | | Define different shipping policies according to picking type From 573c3a7a35d556256744d873de91e78330147be1 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 22 Aug 2023 08:43:17 +0000 Subject: [PATCH 037/133] [UPD] README.rst --- stock_dynamic_routing/README.rst | 9 +++++++++ .../static/description/index.html | 3 +++ stock_move_source_relocate/README.rst | 19 ++++++++++++------- .../static/description/index.html | 12 +++++------- .../README.rst | 19 ++++++++++++------- .../static/description/index.html | 12 +++++------- 6 files changed, 46 insertions(+), 28 deletions(-) diff --git a/stock_dynamic_routing/README.rst b/stock_dynamic_routing/README.rst index 26039acdce..f78fb5703d 100644 --- a/stock_dynamic_routing/README.rst +++ b/stock_dynamic_routing/README.rst @@ -156,6 +156,7 @@ Authors ~~~~~~~ * Camptocamp +* BCIM Contributors ~~~~~~~~~~~~ @@ -178,6 +179,14 @@ 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. +.. |maintainer-jbaudoux| image:: https://github.com/jbaudoux.png?size=40px + :target: https://github.com/jbaudoux + :alt: jbaudoux + +Current `maintainer `__: + +|maintainer-jbaudoux| + This module is part of the `OCA/wms `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_dynamic_routing/static/description/index.html b/stock_dynamic_routing/static/description/index.html index eedcdcc321..2dac3c93c1 100644 --- a/stock_dynamic_routing/static/description/index.html +++ b/stock_dynamic_routing/static/description/index.html @@ -500,6 +500,7 @@

Credits

Authors

  • Camptocamp
  • +
  • BCIM
@@ -518,6 +519,8 @@

Maintainers

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.

+

Current maintainer:

+

jbaudoux

This module is part of the OCA/wms project on GitHub.

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

diff --git a/stock_move_source_relocate/README.rst b/stock_move_source_relocate/README.rst index 7608ac9c0e..5d35b6748e 100644 --- a/stock_move_source_relocate/README.rst +++ b/stock_move_source_relocate/README.rst @@ -7,9 +7,9 @@ Stock Move Source Relocation !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status - :alt: Alpha + :alt: Beta .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 @@ -57,11 +57,6 @@ module is handy to organize internal replenishments. Compatible with ``stock_dynamic_routing``: when the source location is updated by this module, a dynamic routing may be applied. -.. IMPORTANT:: - This is an alpha version, the data model and design can change at any time without warning. - Only for development or testing purpose, do not use in production. - `More details on development status `_ - **Table of contents** .. contents:: @@ -101,11 +96,13 @@ Authors ~~~~~~~ * Camptocamp +* BCIM Contributors ~~~~~~~~~~~~ * Guewen Baconnier +* Jacques-Etienne Baudoux (BCIM) * `Trobz `_: * Dung Tran @@ -127,6 +124,14 @@ 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. +.. |maintainer-jbaudoux| image:: https://github.com/jbaudoux.png?size=40px + :target: https://github.com/jbaudoux + :alt: jbaudoux + +Current `maintainer `__: + +|maintainer-jbaudoux| + This module is part of the `OCA/wms `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_move_source_relocate/static/description/index.html b/stock_move_source_relocate/static/description/index.html index d64b89f1c9..b1dad40ac8 100644 --- a/stock_move_source_relocate/static/description/index.html +++ b/stock_move_source_relocate/static/description/index.html @@ -367,7 +367,7 @@

Stock Move Source Relocation

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Alpha License: AGPL-3 OCA/wms Translate me on Weblate Try me on Runbot

+

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

Relocate source location of unconfirmed moves

Add relocation rules for moves.

Some use cases:

@@ -398,12 +398,6 @@

Stock Move Source Relocation

module is handy to organize internal replenishments.

Compatible with stock_dynamic_routing: when the source location is updated by this module, a dynamic routing may be applied.

-
-

Important

-

This is an alpha version, the data model and design can change at any time without warning. -Only for development or testing purpose, do not use in production. -More details on development status

-

Table of contents

Contributors

@@ -466,6 +462,8 @@

Maintainers

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.

+

Current maintainer:

+

jbaudoux

This module is part of the OCA/wms project on GitHub.

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

diff --git a/stock_move_source_relocate_dynamic_routing/README.rst b/stock_move_source_relocate_dynamic_routing/README.rst index cdadde55fe..2049102d9a 100644 --- a/stock_move_source_relocate_dynamic_routing/README.rst +++ b/stock_move_source_relocate_dynamic_routing/README.rst @@ -7,9 +7,9 @@ Stock Source Relocate - Dynamic Routing !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status - :alt: Alpha + :alt: Beta .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 @@ -28,11 +28,6 @@ Stock Source Relocate - Dynamic Routing Glue module between ``stock_move_source_relocate`` and ``stock_dynamic_routing``. -.. IMPORTANT:: - This is an alpha version, the data model and design can change at any time without warning. - Only for development or testing purpose, do not use in production. - `More details on development status `_ - **Table of contents** .. contents:: @@ -55,11 +50,13 @@ Authors ~~~~~~~ * Camptocamp +* BCIM Contributors ~~~~~~~~~~~~ * Guewen Baconnier +* Jacques-Etienne Baudoux (BCIM) Maintainers ~~~~~~~~~~~ @@ -74,6 +71,14 @@ 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. +.. |maintainer-jbaudoux| image:: https://github.com/jbaudoux.png?size=40px + :target: https://github.com/jbaudoux + :alt: jbaudoux + +Current `maintainer `__: + +|maintainer-jbaudoux| + This module is part of the `OCA/wms `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_move_source_relocate_dynamic_routing/static/description/index.html b/stock_move_source_relocate_dynamic_routing/static/description/index.html index 7dfbf38075..95e74af33c 100644 --- a/stock_move_source_relocate_dynamic_routing/static/description/index.html +++ b/stock_move_source_relocate_dynamic_routing/static/description/index.html @@ -367,15 +367,9 @@

Stock Source Relocate - Dynamic Routing

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Alpha License: AGPL-3 OCA/wms Translate me on Weblate Try me on Runbot

+

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

Glue module between stock_move_source_relocate and stock_dynamic_routing.

-
-

Important

-

This is an alpha version, the data model and design can change at any time without warning. -Only for development or testing purpose, do not use in production. -More details on development status

-

Table of contents

Contributors

@@ -417,6 +413,8 @@

Maintainers

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.

+

Current maintainer:

+

jbaudoux

This module is part of the OCA/wms project on GitHub.

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

From fca40ef516f4d8fe613cb556960fef6413aec847 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 22 Aug 2023 08:43:18 +0000 Subject: [PATCH 038/133] stock_dynamic_routing 14.0.1.1.0 --- stock_dynamic_routing/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock_dynamic_routing/__manifest__.py b/stock_dynamic_routing/__manifest__.py index d6035abf09..c0bf0126bd 100644 --- a/stock_dynamic_routing/__manifest__.py +++ b/stock_dynamic_routing/__manifest__.py @@ -6,7 +6,7 @@ "maintainers": ["jbaudoux"], "website": "https://github.com/OCA/wms", "category": "Warehouse Management", - "version": "14.0.1.0.2", + "version": "14.0.1.1.0", "license": "AGPL-3", "depends": ["stock", "stock_helper"], "demo": [ From 0c6099f4d556692fa4ef118982ba799ff006253b Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 22 Aug 2023 08:43:19 +0000 Subject: [PATCH 039/133] stock_move_source_relocate_dynamic_routing 14.0.1.1.0 --- stock_move_source_relocate_dynamic_routing/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock_move_source_relocate_dynamic_routing/__manifest__.py b/stock_move_source_relocate_dynamic_routing/__manifest__.py index a34368b22d..e199672e17 100644 --- a/stock_move_source_relocate_dynamic_routing/__manifest__.py +++ b/stock_move_source_relocate_dynamic_routing/__manifest__.py @@ -6,7 +6,7 @@ "maintainers": ["jbaudoux"], "website": "https://github.com/OCA/wms", "category": "Warehouse Management", - "version": "14.0.1.0.1", + "version": "14.0.1.1.0", "license": "AGPL-3", "depends": ["stock_dynamic_routing", "stock_move_source_relocate"], "demo": [], From 481205e199b9fdb4652458aed256ef13bf96f5e1 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 22 Aug 2023 08:43:20 +0000 Subject: [PATCH 040/133] stock_move_source_relocate 14.0.1.2.0 --- stock_move_source_relocate/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock_move_source_relocate/__manifest__.py b/stock_move_source_relocate/__manifest__.py index 0d182a44c7..b22bb44f61 100644 --- a/stock_move_source_relocate/__manifest__.py +++ b/stock_move_source_relocate/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock Move Source Relocation", "summary": "Change source location of unavailable moves", - "version": "14.0.1.1.0", + "version": "14.0.1.2.0", "development_status": "Beta", "category": "Warehouse Management", "website": "https://github.com/OCA/wms", From e2a8d5bc420e157267055253b524f91df7dc262f Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 22 Aug 2023 08:43:26 +0000 Subject: [PATCH 041/133] [UPD] addons table in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 16c26b5fc6..e40bc159a6 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,11 @@ addon | version | maintainers | summary [stock_available_to_promise_release](stock_available_to_promise_release/) | 14.0.2.1.1 | | Release Operations based on available to promise [stock_available_to_promise_release_dynamic_routing](stock_available_to_promise_release_dynamic_routing/) | 14.0.1.0.0 | | Glue between moves release and dynamic routing [stock_checkout_sync](stock_checkout_sync/) | 14.0.1.1.0 | | Sync location for Checkout operations -[stock_dynamic_routing](stock_dynamic_routing/) | 14.0.1.0.2 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Dynamic routing of stock moves +[stock_dynamic_routing](stock_dynamic_routing/) | 14.0.1.1.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Dynamic routing of stock moves [stock_dynamic_routing_checkout_sync](stock_dynamic_routing_checkout_sync/) | 14.0.1.0.0 | | Glue module for tests when dynamic routing and checkout sync are used [stock_dynamic_routing_reserve_rule](stock_dynamic_routing_reserve_rule/) | 14.0.1.0.1 | | Glue module between dynamic routing and reservation rules -[stock_move_source_relocate](stock_move_source_relocate/) | 14.0.1.1.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Change source location of unavailable moves -[stock_move_source_relocate_dynamic_routing](stock_move_source_relocate_dynamic_routing/) | 14.0.1.0.1 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Glue module +[stock_move_source_relocate](stock_move_source_relocate/) | 14.0.1.2.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Change source location of unavailable moves +[stock_move_source_relocate_dynamic_routing](stock_move_source_relocate_dynamic_routing/) | 14.0.1.1.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Glue module [stock_picking_completion_info](stock_picking_completion_info/) | 14.0.1.1.0 | | Display on current document completion information according to next operations [stock_picking_consolidation_priority](stock_picking_consolidation_priority/) | 14.0.1.1.0 | | Raise priority of all transfers for a chain when started [stock_picking_type_shipping_policy](stock_picking_type_shipping_policy/) | 14.0.1.1.0 | | Define different shipping policies according to picking type From 2d2195a3e65e3b1480fd1caf3d5042fc7bfd828d Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 23 Aug 2023 05:58:29 +0000 Subject: [PATCH 042/133] [UPD] addons table in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e40bc159a6..15f19078d3 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ addon | version | maintainers | summary [stock_reception_screen_measuring_device](stock_reception_screen_measuring_device/) | 14.0.1.0.0 | [![gurneyalex](https://github.com/gurneyalex.png?size=30px)](https://github.com/gurneyalex) | Allow to use a measuring device from a reception screen.for packaging measurement [stock_reception_screen_qty_by_packaging](stock_reception_screen_qty_by_packaging/) | 14.0.1.1.0 | | Glue module for `stock_product_qty_by_packaging` and `stock_vertical_lift`. [stock_release_channel](stock_release_channel/) | 14.0.2.1.0 | [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | Manage workload in WMS with release channels -[stock_storage_type](stock_storage_type/) | 14.0.1.12.0 | | Manage packages and locations storage types +[stock_storage_type](stock_storage_type/) | 14.0.1.12.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Manage packages and locations storage types [stock_storage_type_buffer](stock_storage_type_buffer/) | 14.0.1.3.0 | | Exclude storage locations from put-away if their buffer is full [stock_storage_type_putaway_abc](stock_storage_type_putaway_abc/) | 14.0.1.0.0 | | Advanced storage strategy ABC for WMS [stock_unique_order_per_location](stock_unique_order_per_location/) | 14.0.1.0.0 | [![TDu](https://github.com/TDu.png?size=30px)](https://github.com/TDu) | Prevent to mix sales order on same consolidation location. From c8b9158e5f21d4d2f1d62a52ae51d7c583b84842 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 23 Aug 2023 05:58:36 +0000 Subject: [PATCH 043/133] [UPD] README.rst --- stock_storage_type/README.rst | 8 ++++++++ stock_storage_type/static/description/index.html | 2 ++ 2 files changed, 10 insertions(+) diff --git a/stock_storage_type/README.rst b/stock_storage_type/README.rst index 30d0bf70ac..9522383eb2 100644 --- a/stock_storage_type/README.rst +++ b/stock_storage_type/README.rst @@ -149,6 +149,14 @@ 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. +.. |maintainer-jbaudoux| image:: https://github.com/jbaudoux.png?size=40px + :target: https://github.com/jbaudoux + :alt: jbaudoux + +Current `maintainer `__: + +|maintainer-jbaudoux| + This module is part of the `OCA/wms `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_storage_type/static/description/index.html b/stock_storage_type/static/description/index.html index 2184f1419e..6d3a11af06 100644 --- a/stock_storage_type/static/description/index.html +++ b/stock_storage_type/static/description/index.html @@ -485,6 +485,8 @@

Maintainers

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.

+

Current maintainer:

+

jbaudoux

This module is part of the OCA/wms project on GitHub.

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

From f4e5a2b6da2a9a611fe936cbabce8505beaba711 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 23 Aug 2023 05:58:37 +0000 Subject: [PATCH 044/133] stock_storage_type 14.0.1.12.1 --- stock_storage_type/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock_storage_type/__manifest__.py b/stock_storage_type/__manifest__.py index 7e1986ce9e..8617c88e5c 100644 --- a/stock_storage_type/__manifest__.py +++ b/stock_storage_type/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Stock Storage Type", "summary": "Manage packages and locations storage types", - "version": "14.0.1.12.0", + "version": "14.0.1.12.1", "development_status": "Beta", "category": "Warehouse Management", "website": "https://github.com/OCA/wms", From c24373d04f104e02c3db936afd717dc60c4db14b Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 23 Aug 2023 05:58:42 +0000 Subject: [PATCH 045/133] [UPD] addons table in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 15f19078d3..0a889c6519 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ addon | version | maintainers | summary [stock_reception_screen_measuring_device](stock_reception_screen_measuring_device/) | 14.0.1.0.0 | [![gurneyalex](https://github.com/gurneyalex.png?size=30px)](https://github.com/gurneyalex) | Allow to use a measuring device from a reception screen.for packaging measurement [stock_reception_screen_qty_by_packaging](stock_reception_screen_qty_by_packaging/) | 14.0.1.1.0 | | Glue module for `stock_product_qty_by_packaging` and `stock_vertical_lift`. [stock_release_channel](stock_release_channel/) | 14.0.2.1.0 | [![sebalix](https://github.com/sebalix.png?size=30px)](https://github.com/sebalix) | Manage workload in WMS with release channels -[stock_storage_type](stock_storage_type/) | 14.0.1.12.0 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Manage packages and locations storage types +[stock_storage_type](stock_storage_type/) | 14.0.1.12.1 | [![jbaudoux](https://github.com/jbaudoux.png?size=30px)](https://github.com/jbaudoux) | Manage packages and locations storage types [stock_storage_type_buffer](stock_storage_type_buffer/) | 14.0.1.3.0 | | Exclude storage locations from put-away if their buffer is full [stock_storage_type_putaway_abc](stock_storage_type_putaway_abc/) | 14.0.1.0.0 | | Advanced storage strategy ABC for WMS [stock_unique_order_per_location](stock_unique_order_per_location/) | 14.0.1.0.0 | [![TDu](https://github.com/TDu.png?size=30px)](https://github.com/TDu) | Prevent to mix sales order on same consolidation location. From c45e1fcfdd14cf0f8d3d1f8f62081f2b50330202 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 23 Aug 2023 06:18:37 +0000 Subject: [PATCH 046/133] [UPD] README.rst --- stock_warehouse_flow/README.rst | 6 +++--- stock_warehouse_flow/static/description/index.html | 4 ++-- stock_warehouse_flow_release/README.rst | 6 +++--- stock_warehouse_flow_release/static/description/index.html | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/stock_warehouse_flow/README.rst b/stock_warehouse_flow/README.rst index 29a677bab2..f6073ca559 100644 --- a/stock_warehouse_flow/README.rst +++ b/stock_warehouse_flow/README.rst @@ -19,9 +19,9 @@ Stock Warehouse Flow .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/wms-14-0/wms-14-0-stock_warehouse_flow :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/wms&target_branch=14.0 - :alt: Try me on Runboat +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/285/14.0 + :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| diff --git a/stock_warehouse_flow/static/description/index.html b/stock_warehouse_flow/static/description/index.html index 7ef8ec6d18..5c08426744 100644 --- a/stock_warehouse_flow/static/description/index.html +++ b/stock_warehouse_flow/static/description/index.html @@ -3,7 +3,7 @@ - + Stock Warehouse Flow