Skip to content

Commit

Permalink
[IMP] shopfloor: Zone picking no packing
Browse files Browse the repository at this point in the history
Add an option to skip the packing step when processing a line into the zone picking scenario. Thanks to this option the processing of a line can be done by processing the location, set the qty and scan the destination even if the oroduct is not into a package.
  • Loading branch information
lmignon committed Jun 6, 2024
1 parent 81419b7 commit 13f7bf1
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 7 deletions.
2 changes: 1 addition & 1 deletion shopfloor/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{
"name": "Shopfloor",
"summary": "manage warehouse operations with barcode scanners",
"version": "16.0.2.1.0",
"version": "16.0.2.1.1",
"development_status": "Beta",
"category": "Inventory",
"website": "https://github.com/OCA/wms",
Expand Down
3 changes: 2 additions & 1 deletion shopfloor/data/shopfloor_scenario_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"multiple_move_single_pack": true,
"no_prefill_qty": true,
"scan_location_or_pack_first": true,
"allow_alternative_destination_package": true
"allow_alternative_destination_package": true,
"require_destination_package": true
}
</field>
</record>
Expand Down
26 changes: 26 additions & 0 deletions shopfloor/migrations/16.0.2.1.1/post-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2024 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import json
import logging

from odoo import SUPERUSER_ID, api

_logger = logging.getLogger(__name__)


def migrate(cr, version):
_logger.info("Updating scenario Zone Picking")
if not version:
return
env = api.Environment(cr, SUPERUSER_ID, {})
zone_picking_scenario = env.ref("shopfloor.scenario_zone_picking")
_update_scenario_options(zone_picking_scenario)


def _update_scenario_options(scenario):
options = scenario.options
options["require_destination_package"] = True
options_edit = json.dumps(options or {}, indent=4, sort_keys=True)
scenario.write({"options_edit": options_edit})
_logger.info("Option require_destination_package added to scenario Zone Picking")
42 changes: 42 additions & 0 deletions shopfloor/models/shopfloor_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ class ShopfloorMenu(models.Model):
compute="_compute_allow_alternative_destination_package_is_possible"
)

require_destination_package = fields.Boolean(
string="Destination package required",
default=True,
help="If set, the user will have to scan only the source location "
"and the destination location to process a line. The unload step will be skipped.",
)

require_destination_package_is_possible = fields.Boolean(
compute="_compute_require_destination_package_is_possible"
)

@api.onchange("unload_package_at_destination")
def _onchange_unload_package_at_destination(self):
# Uncheck pick_pack_same_time when unload_package_at_destination is set to True
Expand All @@ -243,6 +254,16 @@ def _onchange_pick_pack_same_time(self):
record.unload_package_at_destination = False
record.multiple_move_single_pack = False

@api.onchange("require_destination_package")
def _onchange_require_destination_package(self):
# require_destination_package is incompatible with pick_pack_same_time and
# unload_package_at_destination and multiple_move_single_pack
for record in self:
if not record.require_destination_package:
record.pick_pack_same_time = False
record.unload_package_at_destination = False
record.multiple_move_single_pack = False

Check warning on line 265 in shopfloor/models/shopfloor_menu.py

View check run for this annotation

Codecov / codecov/patch

shopfloor/models/shopfloor_menu.py#L263-L265

Added lines #L263 - L265 were not covered by tests

@api.onchange("multiple_move_single_pack")
def _onchange_multiple_move_single_pack(self):
# multiple_move_single_pack is incompatible with pick_pack_same_time,
Expand All @@ -254,6 +275,7 @@ def _onchange_multiple_move_single_pack(self):
"unload_package_at_destination",
"pick_pack_same_time",
"multiple_move_single_pack",
"require_destination_package",
)
def _check_options(self):
if self.pick_pack_same_time and self.unload_package_at_destination:
Expand All @@ -270,6 +292,19 @@ def _check_options(self):
"'Multiple moves same destination package'."
)
)
elif not self.require_destination_package and (
self.pick_pack_same_time
or self.unload_package_at_destination
or self.multiple_move_single_pack
):
raise exceptions.UserError(

Check warning on line 300 in shopfloor/models/shopfloor_menu.py

View check run for this annotation

Codecov / codecov/patch

shopfloor/models/shopfloor_menu.py#L300

Added line #L300 was not covered by tests
_(
"'No destination package required' is incompatible with "
"'Pick and pack at the same time',"
"'Unload package at destination' and 'Multiple moves "
"same destination package'."
)
)

@api.depends("scenario_id", "picking_type_ids")
def _compute_move_create_is_possible(self):
Expand Down Expand Up @@ -458,3 +493,10 @@ def _compute_allow_alternative_destination_package_is_possible(self):
menu.allow_alternative_destination_package_is_possible = (
menu.scenario_id.has_option("allow_alternative_destination_package")
)

@api.depends("scenario_id")
def _compute_require_destination_package_is_possible(self):
for menu in self:
menu.require_destination_package_is_possible = menu.scenario_id.has_option(

Check warning on line 500 in shopfloor/models/shopfloor_menu.py

View check run for this annotation

Codecov / codecov/patch

shopfloor/models/shopfloor_menu.py#L500

Added line #L500 was not covered by tests
"require_destination_package"
)
5 changes: 4 additions & 1 deletion shopfloor/services/zone_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ def lines_order(self):
def _pick_pack_same_time(self):
return self.work.menu.pick_pack_same_time

def _packing_required(self):
return self.work.menu.require_destination_package

def _handle_complete_mix_pack(self, package):
packaging = self._actions_for("packaging")
return (
Expand Down Expand Up @@ -924,7 +927,7 @@ def _set_destination_location(
return (location_changed, response)

# If no destination package
if not move_line.result_package_id:
if self._packing_required() and not move_line.result_package_id:
response = self._response_for_set_line_destination(
move_line,
message=self.msg_store.dest_package_required(),
Expand Down
11 changes: 7 additions & 4 deletions shopfloor/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/*
:Author: David Goodger ([email protected])
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.

See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
Expand Down Expand Up @@ -274,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -300,7 +301,7 @@
span.pre {
white-space: pre }

span.problematic {
span.problematic, pre.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -485,7 +486,9 @@ <h2><a class="toc-backref" href="#toc-entry-10">Other credits</a></h2>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-11">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
Expand Down
1 change: 1 addition & 0 deletions shopfloor/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
from . import test_zone_picking_unload_single
from . import test_zone_picking_unload_all
from . import test_zone_picking_unload_set_destination
from . import test_zone_picking_require_destination_package
from . import test_misc
from . import test_move_action_assign
from . import test_scan_anything
Expand Down
62 changes: 62 additions & 0 deletions shopfloor/tests/test_zone_picking_require_destination_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright 2020 Camptocamp SA (http://www.camptocamp.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from .test_zone_picking_base import ZonePickingCommonCase

# pylint: disable=missing-return


class ZonePickingNoPAcking(ZonePickingCommonCase):
"""Tests zone picking without packing steps.
* /set_destination
"""

def setUp(self):
super().setUp()
self.service.work.current_picking_type = self.picking1.picking_type_id
self.picking1.move_line_ids.result_package_id = False

def test_set_destination(self):
# when no packing is set, you can set the destination directly
# without the need to pack the product
self.service.work.menu.sudo().require_destination_package = True
zone_location = self.zone_location
picking_type = self.picking1.picking_type_id
move_line = self.picking1.move_line_ids[0]
response = self.service.dispatch(
"set_destination",
params={
"move_line_id": move_line.id,
"barcode": move_line.location_dest_id.barcode,
"quantity": move_line.reserved_uom_qty,
"confirmation": None,
},
)
self.assert_response_set_line_destination(
response,
zone_location,
picking_type,
move_line,
qty_done=move_line.reserved_uom_qty,
message=self.service.msg_store.dest_package_required(),
)
self.service.work.menu.sudo().require_destination_package = False
response = self.service.dispatch(
"set_destination",
params={
"move_line_id": move_line.id,
"barcode": move_line.location_dest_id.barcode,
"quantity": move_line.reserved_uom_qty,
"confirmation": None,
},
)
move_lines = self.service._find_location_move_lines()
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
self.assert_response_select_line(
response,
zone_location,
picking_type,
move_lines,
message=self.service.msg_store.confirm_pack_moved(),
)
10 changes: 10 additions & 0 deletions shopfloor/views/shopfloor_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
>
<field name="ignore_no_putaway_available_is_possible" invisible="1" />
<field name="ignore_no_putaway_available" />
</group>
<group
name="require_destination_package"
attrs="{'invisible': [('require_destination_package_is_possible', '=', False)]}"
>
<field
name="require_destination_package_is_possible"
invisible="1"
/>
<field name="require_destination_package" />
</group>
<group
name="pick_pack_same_time"
Expand Down

0 comments on commit 13f7bf1

Please sign in to comment.