From f9be0e83c831a4aa1b82036de0e355699f14d2b0 Mon Sep 17 00:00:00 2001 From: Michael Tietz Date: Wed, 15 Jan 2025 15:52:51 +0100 Subject: [PATCH] [IMP] shopfloor: Refactor _write_destination_on_lines --- shopfloor/actions/stock.py | 19 ++++++++++++ shopfloor/services/cluster_picking.py | 15 ++++------ .../services/location_content_transfer.py | 5 ++-- shopfloor/services/single_pack_transfer.py | 5 +++- shopfloor/services/zone_picking.py | 15 ++++------ shopfloor_checkout_sync/__init__.py | 1 - shopfloor_checkout_sync/actions/__init__.py | 1 + .../actions/checkout_sync.py | 7 ++--- shopfloor_checkout_sync/actions/stock.py | 18 ++++++++++++ .../readme/CONTRIBUTORS.rst | 1 + shopfloor_checkout_sync/services/__init__.py | 3 -- .../services/cluster_picking.py | 19 ------------ .../services/location_content_transfer.py | 19 ------------ .../services/zone_picking.py | 19 ------------ .../services/single_product_transfer.py | 29 ++----------------- 15 files changed, 61 insertions(+), 115 deletions(-) create mode 100644 shopfloor_checkout_sync/actions/stock.py delete mode 100644 shopfloor_checkout_sync/services/__init__.py delete mode 100644 shopfloor_checkout_sync/services/cluster_picking.py delete mode 100644 shopfloor_checkout_sync/services/location_content_transfer.py delete mode 100644 shopfloor_checkout_sync/services/zone_picking.py diff --git a/shopfloor/actions/stock.py b/shopfloor/actions/stock.py index 5325efe703..8d16f7cec1 100644 --- a/shopfloor/actions/stock.py +++ b/shopfloor/actions/stock.py @@ -1,4 +1,5 @@ # Copyright 2020 Camptocamp SA (http://www.camptocamp.com) +# Copyright 2025 Michael Tietz (MT Software) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import _, fields from odoo.tools.float_utils import float_round @@ -228,3 +229,21 @@ def no_putaway_available(self, picking_types, move_lines): # when no putaway is found, the move line destination stays the # default's of the picking type return any(line.location_dest_id in base_locations for line in move_lines) + + def _lock_lines(self, lines): + self._actions_for("lock").for_update(lines) + + def _set_destination_on_lines( + self, lines, location_dest, unload=False, set_src_location=False + ): + lines.package_level_id.location_dest_id = location_dest + lines.location_dest_id = location_dest + + def _unload_package(self, lines): + lines.result_package_id = False + + def set_locations_and_unload_lines(self, lines, location_dest, unload=False): + self._lock_lines(lines) + self._set_destination_on_lines(lines, location_dest) + if unload: + self._unload_package(lines) diff --git a/shopfloor/services/cluster_picking.py b/shopfloor/services/cluster_picking.py index 20d161a4af..622eeeebec 100644 --- a/shopfloor/services/cluster_picking.py +++ b/shopfloor/services/cluster_picking.py @@ -1147,8 +1147,11 @@ def set_destination_all(self, picking_batch_id, barcode, confirmation=None): return self._unload_end(batch, completion_info_popup=completion_info_popup) def _unload_write_destination_on_lines(self, lines, location): - lines.write({"shopfloor_unloaded": True, "location_dest_id": location.id}) - lines.package_level_id.location_dest_id = location + stock = self._actions_for("stock") + stock.set_locations_and_unload_lines( + lines, location, self.work.menu.unload_package_at_destination + ) + lines.write({"shopfloor_unloaded": True}) for line in lines: # We set the picking to done only when the last line is # unloaded to avoid backorders. @@ -1158,8 +1161,6 @@ def _unload_write_destination_on_lines(self, lines, location): picking_lines = picking.mapped("move_line_ids") if all(line.shopfloor_unloaded for line in picking_lines): picking._action_done() - if self.work.menu.unload_package_at_destination: - lines.result_package_id = False def _unload_end(self, batch, completion_info_popup=None): """Try to close the batch if all transfers are done. @@ -1279,15 +1280,11 @@ def unload_scan_destination( batch, package, lines, barcode, confirmation=confirmation ) - def _lock_lines(self, lines): - """Lock move lines""" - self._actions_for("lock").for_update(lines) - def _unload_scan_destination_lines( self, batch, package, lines, barcode, confirmation=None ): # Lock move lines that will be updated - self._lock_lines(lines) + self._actions_for("lock").for_update(lines) first_line = fields.first(lines) scanned_location = self._actions_for("search").location_from_scan(barcode) if not scanned_location: diff --git a/shopfloor/services/location_content_transfer.py b/shopfloor/services/location_content_transfer.py index c7e941a2b0..0dfd42946d 100644 --- a/shopfloor/services/location_content_transfer.py +++ b/shopfloor/services/location_content_transfer.py @@ -456,10 +456,9 @@ def _find_transfer_move_lines(self, location): ) return lines - # hook used in module shopfloor_checkout_sync def _write_destination_on_lines(self, lines, location, package=None): - lines.location_dest_id = location - lines.package_level_id.location_dest_id = location + stock = self._actions_for("stock") + stock.set_locations_and_unload_lines(lines, location) if package: lines.result_package_id = package diff --git a/shopfloor/services/single_pack_transfer.py b/shopfloor/services/single_pack_transfer.py index 9658cf1f1f..5c0b0fb619 100644 --- a/shopfloor/services/single_pack_transfer.py +++ b/shopfloor/services/single_pack_transfer.py @@ -1,6 +1,7 @@ # Copyright 2020-2021 Camptocamp SA (http://www.camptocamp.com) # Copyright 2020-2021 Jacques-Etienne Baudoux (BCIM) # Copyright 2020 Akretion (http://www.akretion.com) +# Copyright 2025 Michael Tietz (MT Software) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import fields @@ -268,8 +269,10 @@ def _router_validate_success(self, package_level): def _set_destination_and_done(self, package_level, scanned_location): # when writing the destination on the package level, it writes # on the move lines - package_level.location_dest_id = scanned_location stock = self._actions_for("stock") + stock.set_locations_and_unload_lines( + package_level.move_line_ids, scanned_location + ) stock.put_package_level_in_move(package_level) stock.validate_moves(package_level.move_line_ids.move_id) diff --git a/shopfloor/services/zone_picking.py b/shopfloor/services/zone_picking.py index c4b3fec154..119e3a668a 100644 --- a/shopfloor/services/zone_picking.py +++ b/shopfloor/services/zone_picking.py @@ -1036,7 +1036,7 @@ def _set_destination_package(self, move_line, quantity, package): ) return (package_changed, response) stock = self._actions_for("stock") - self._lock_lines(move_line) + stock._lock_lines(move_line) try: stock.mark_move_line_as_picked( move_line, quantity, package, check_user=True @@ -1591,11 +1591,10 @@ def set_destination_all(self, barcode, confirmation=None): return self._set_destination_all_response(buffer_lines, message=message) def _write_destination_on_lines(self, lines, location): - self._lock_lines(lines) - lines.location_dest_id = location - lines.package_level_id.location_dest_id = location - if self.work.menu.unload_package_at_destination: - lines.result_package_id = False + stock = self._actions_for("stock") + stock.set_locations_and_unload_lines( + lines, location, unload=self.work.menu.unload_package_at_destination + ) def unload_split(self): """Indicates that now the buffer must be treated line per line @@ -1676,10 +1675,6 @@ def unload_scan_pack(self, package_id, barcode): unload_single_message=self.msg_store.barcode_no_match(package.name), ) - def _lock_lines(self, lines): - """Lock move lines""" - self._actions_for("lock").for_update(lines) - def unload_set_destination(self, package_id, barcode, confirmation=None): """Scan the final destination for move lines in the buffer with the destination package diff --git a/shopfloor_checkout_sync/__init__.py b/shopfloor_checkout_sync/__init__.py index cf850b590c..f5fe63aaf7 100644 --- a/shopfloor_checkout_sync/__init__.py +++ b/shopfloor_checkout_sync/__init__.py @@ -1,2 +1 @@ from . import actions -from . import services diff --git a/shopfloor_checkout_sync/actions/__init__.py b/shopfloor_checkout_sync/actions/__init__.py index 790da7db9e..8cae1c2411 100644 --- a/shopfloor_checkout_sync/actions/__init__.py +++ b/shopfloor_checkout_sync/actions/__init__.py @@ -1 +1,2 @@ from . import checkout_sync +from . import stock diff --git a/shopfloor_checkout_sync/actions/checkout_sync.py b/shopfloor_checkout_sync/actions/checkout_sync.py index 656878de58..b8ce9f9e00 100644 --- a/shopfloor_checkout_sync/actions/checkout_sync.py +++ b/shopfloor_checkout_sync/actions/checkout_sync.py @@ -1,4 +1,5 @@ # Copyright 2020 Camptocamp SA +# Copyright 2025 Michael Tietz (MT Software) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) from odoo.addons.component.core import Component @@ -27,8 +28,4 @@ def _all_lines_to_lock(self, lines): return lines def _sync_checkout(self, lines, location): - moves = lines.mapped("move_id") - if self._has_to_sync_destination(lines): - dest_pickings = moves._moves_to_sync_checkout() - all_moves = self.env["stock.move"].union(*dest_pickings.values()) - all_moves.sync_checkout_destination(location) + lines.move_id.sync_checkout_destination(location) diff --git a/shopfloor_checkout_sync/actions/stock.py b/shopfloor_checkout_sync/actions/stock.py new file mode 100644 index 0000000000..1b08596791 --- /dev/null +++ b/shopfloor_checkout_sync/actions/stock.py @@ -0,0 +1,18 @@ +# Copyright 2025 Michael Tietz (MT Software) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.addons.component.core import Component + + +class StockAction(Component): + _inherit = "shopfloor.stock.action" + + def _set_destination_on_lines(self, lines, location_dest): + checkout_sync = self._actions_for("checkout.sync") + checkout_sync._sync_checkout(lines, location_dest) + super()._set_destination_on_lines(lines, location_dest) + + def set_locations_and_unload_lines(self, lines, location_dest, unload=False): + checkout_sync = self._actions_for("checkout.sync") + checkout_sync._all_lines_to_lock(lines) + super().set_locations_and_unload_lines(lines, location_dest, unload) diff --git a/shopfloor_checkout_sync/readme/CONTRIBUTORS.rst b/shopfloor_checkout_sync/readme/CONTRIBUTORS.rst index dc8669b25f..bb52cff0d5 100644 --- a/shopfloor_checkout_sync/readme/CONTRIBUTORS.rst +++ b/shopfloor_checkout_sync/readme/CONTRIBUTORS.rst @@ -1,2 +1,3 @@ * Guewen Baconnier * `Trobz `_: +* Michael Tietz (MT Software) diff --git a/shopfloor_checkout_sync/services/__init__.py b/shopfloor_checkout_sync/services/__init__.py deleted file mode 100644 index 23b96cc923..0000000000 --- a/shopfloor_checkout_sync/services/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import cluster_picking -from . import location_content_transfer -from . import zone_picking diff --git a/shopfloor_checkout_sync/services/cluster_picking.py b/shopfloor_checkout_sync/services/cluster_picking.py deleted file mode 100644 index ed642e8e38..0000000000 --- a/shopfloor_checkout_sync/services/cluster_picking.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2020 Camptocamp SA -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) - -from odoo.addons.component.core import Component - - -class ClusterPicking(Component): - _inherit = "shopfloor.cluster.picking" - - @property - def checkout_sync(self): - return self._actions_for("checkout.sync") - - def _lock_lines(self, lines): - super()._lock_lines(self.checkout_sync._all_lines_to_lock(lines)) - - def _unload_write_destination_on_lines(self, lines, location): - self.checkout_sync._sync_checkout(lines, location) - return super()._unload_write_destination_on_lines(lines, location) diff --git a/shopfloor_checkout_sync/services/location_content_transfer.py b/shopfloor_checkout_sync/services/location_content_transfer.py deleted file mode 100644 index d57443d723..0000000000 --- a/shopfloor_checkout_sync/services/location_content_transfer.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2020 Camptocamp SA -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) - -from odoo.addons.component.core import Component - - -class LocationContentTransfer(Component): - _inherit = "shopfloor.location.content.transfer" - - @property - def checkout_sync(self): - return self._actions_for("checkout.sync") - - def _lock_lines(self, lines): - super()._lock_lines(self.checkout_sync._all_lines_to_lock(lines)) - - def _write_destination_on_lines(self, lines, location, package=None): - self.checkout_sync._sync_checkout(lines, location) - return super()._write_destination_on_lines(lines, location, package) diff --git a/shopfloor_checkout_sync/services/zone_picking.py b/shopfloor_checkout_sync/services/zone_picking.py deleted file mode 100644 index 09b4024210..0000000000 --- a/shopfloor_checkout_sync/services/zone_picking.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2020 Camptocamp SA -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) - -from odoo.addons.component.core import Component - - -class ZonePicking(Component): - _inherit = "shopfloor.zone.picking" - - @property - def checkout_sync(self): - return self._actions_for("checkout.sync") - - def _lock_lines(self, lines): - super()._lock_lines(self.checkout_sync._all_lines_to_lock(lines)) - - def _write_destination_on_lines(self, lines, location): - self.checkout_sync._sync_checkout(lines, location) - return super()._write_destination_on_lines(lines, location) diff --git a/shopfloor_single_product_transfer/services/single_product_transfer.py b/shopfloor_single_product_transfer/services/single_product_transfer.py index c15e9ccb46..98bda9be58 100644 --- a/shopfloor_single_product_transfer/services/single_product_transfer.py +++ b/shopfloor_single_product_transfer/services/single_product_transfer.py @@ -10,7 +10,6 @@ from odoo.addons.base_rest.components.service import to_int from odoo.addons.component.core import Component -from odoo.addons.component.exception import NoComponentError from odoo.addons.shopfloor.utils import to_float _logger = logging.getLogger("shopfloor.services.single_product_transfer") @@ -612,31 +611,9 @@ def _set_quantity__check_location( move_line, message=message, asking_confirmation=confirmation or None ) - def _lock_lines(self, lines): - self._actions_for("lock").for_update(lines) - def _write_destination_on_lines(self, lines, location): - # TODO - # '_write_destination_on_lines' is implemented in: - # - # - 'location_content_transfer' - # - 'zone_picking' - # - 'cluster_picking' (but it is called '_unload_write_destination_on_lines') - # - # And all of them has a different implementation, - # To refactor later. - try: - # TODO lose dependency on 'shopfloor_checkout_sync' to avoid having - # yet another glue module. In the long term we should make - # 'shopfloor_checkout_sync' use events and trash the overrides made - # on all scenarios. - checkout_sync = self._actions_for("checkout.sync") - except NoComponentError: - self._lock_lines(lines) - else: - self._lock_lines(checkout_sync._all_lines_to_lock(lines)) - checkout_sync._sync_checkout(lines, location) - lines.location_dest_id = location + stock = self._actions_for("stock") + stock.set_locations_and_unload_lines(lines, location) def _set_quantity__post_move(self, move_line, location, confirmation=None): # TODO qty_done = 0: transfer_no_qty_done @@ -864,7 +841,7 @@ def set_quantity(self, selected_line_id, barcode, quantity, confirmation=None): # TODO Should probably return to scan_product or scan_location? return self._response_for_set_quantity(move_line) - self._lock_lines(move_line) + self._actions_for("stock")._lock_lines(move_line) if move_line.state == "done": message = self.msg_store.move_already_done() return self._response_for_set_quantity(move_line, message=message)