Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][IMP] shopfloor: package checkout buttons #665

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions shopfloor/actions/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,27 @@ def no_line_to_pack(self):
"message_type": "warning",
"body": _("No line to pack found."),
}

def invalid_scanned_checkout_object_wo_package(
self, scanned_object, package_process_type
):
scanned_object_name = {
"package": _("a package"),
"packaging": _("a packaging"),
"delivery_packaging": _("a delivery packaging"),
}.get(scanned_object, _("N/A"))

selection = self.env["shopfloor.menu"]._fields["package_process_type"].selection
ppt_name = None
for el in selection:
if el[0] == package_process_type:
ppt_name = el[1]
break

return {
"message_type": "error",
"body": _(
"You scanned {scanned_object_name} which is not allowed"
" with the package process type '{ppt_name}'"
).format(scanned_object_name=scanned_object_name, ppt_name=ppt_name),
}
Comment on lines +811 to +833
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you rename this to checkout_package_scan_is_not_allowed

Suggested change
def invalid_scanned_checkout_object_wo_package(
self, scanned_object, package_process_type
):
scanned_object_name = {
"package": _("a package"),
"packaging": _("a packaging"),
"delivery_packaging": _("a delivery packaging"),
}.get(scanned_object, _("N/A"))
selection = self.env["shopfloor.menu"]._fields["package_process_type"].selection
ppt_name = None
for el in selection:
if el[0] == package_process_type:
ppt_name = el[1]
break
return {
"message_type": "error",
"body": _(
"You scanned {scanned_object_name} which is not allowed"
" with the package process type '{ppt_name}'"
).format(scanned_object_name=scanned_object_name, ppt_name=ppt_name),
}
def checkout_package_scan_is_not_allowed(
self, scanned_object, package_process_type
):
scanned_object_name = {
"package": _("a package"),
"packaging": _("a packaging"),
"delivery_packaging": _("a delivery packaging"),
}.get(scanned_object, _("N/A"))
selection = self.env["shopfloor.menu"]._fields["package_process_type"].selection
ppt_name = None
for el in selection:
if el[0] == package_process_type:
ppt_name = el[1]
break
return {
"message_type": "error",
"body": _(
"You scanned {scanned_object_name} which is not allowed"
" with the package process type '{ppt_name}'"
).format(scanned_object_name=scanned_object_name, ppt_name=ppt_name),
}

3 changes: 2 additions & 1 deletion shopfloor/data/shopfloor_scenario_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
{
"no_prefill_qty": true,
"show_oneline_package_content": true,
"auto_post_line": true
"auto_post_line": true,
"package_process_type": true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to add a migration for this change as well.
`import json
from odoo import SUPERUSER_ID, api

def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
scenario = env.ref("shopfloor.scenario_checkout")
options = scenario.options
options["package_process_type"] = True
scenario.options_edit = json.dumps(options)
`

}
</field>
</record>
Expand Down
18 changes: 18 additions & 0 deletions shopfloor/models/shopfloor_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ class ShopfloorMenu(models.Model):
compute="_compute_auto_post_line_is_possible"
)

package_process_type_is_possible = fields.Boolean(
compute="_compute_package_process_type_is_possible"
)
package_process_type = fields.Selection(
[
("without_package", "Without Package"),
("with_package", "With Package"),
],
"Package Proccess Type",
)
Comment on lines +199 to +208
Copy link
Contributor

@jbaudoux jbaudoux Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to move the configuration to the picking type in a separate module e.g. stock_picking_putinpack_restriction in stock-logistics-workflow and handle the "put in pack" button according to the chosen option. Options similar to https://github.com/OCA/stock-logistics-warehouse/blob/14.0/stock_location_package_restriction/models/stock_location.py#L14


@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 Down Expand Up @@ -411,3 +422,10 @@ def _compute_allow_alternative_destination_is_possible(self):
menu.allow_alternative_destination_is_possible = (
menu.scenario_id.has_option("allow_alternative_destination")
)

@api.depends("scenario_id")
def _compute_package_process_type_is_possible(self):
for menu in self:
menu.package_process_type_is_possible = menu.scenario_id.has_option(
"package_process_type"
)
50 changes: 45 additions & 5 deletions shopfloor/services/checkout.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,28 @@ def _response_for_manual_selection(self, message=None):
return self._response(next_state="manual_selection", data=data, message=message)

def _response_for_select_package(self, picking, lines, message=None):
with_pack, wo_pack = self._get_allow_package_options()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
with_pack, wo_pack = self._get_allow_package_options()

return self._response(
next_state="select_package",
data={
"selected_move_lines": self._data_for_move_lines(lines.sorted()),
"picking": self.data.picking(picking),
"packing_info": self._data_for_packing_info(picking),
"no_package_enabled": not self.options.get(
"checkout__disable_no_package"
),
"allow_with_package": with_pack,
"allow_without_package": wo_pack,
Comment on lines +93 to +94
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"allow_with_package": with_pack,
"allow_without_package": wo_pack,
"allow_with_package": self._is_process_with_package_enabled(),
"allow_without_package": self._is_process_with_package_enabled(),

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second one should be _is_process_without_package_enabled, right?

},
message=message,
)

def _get_allow_package_options(self):
if not self.work.menu.package_process_type:
return True, True

if self.work.menu.package_process_type == "with_package":
return True, False

return False, True

Comment on lines +99 to +107
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should split this into two separate methods. This would simplify the code later.

Suggested change
def _get_allow_package_options(self):
if not self.work.menu.package_process_type:
return True, True
if self.work.menu.package_process_type == "with_package":
return True, False
return False, True
def _is_process_with_package_enabled(self):
if not self.work.menu.package_process_type:
return True
if self.work.menu.package_process_type == "with_package":
return True
return False
def _is_process_without_package_enabled(self):
if not self.work.menu.package_process_type:
return True
if self.work.menu.package_process_type == "without_package":
return True
return False

def _data_for_packing_info(self, picking):
"""Return the packing information

Expand Down Expand Up @@ -913,11 +922,37 @@ def scan_package_action(self, picking_id, selected_line_ids, barcode):

selected_lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
search_result = self._scan_package_find(picking, barcode)

message = self._check_scan_package_find_result(search_result)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
message = self._check_scan_package_find_result(search_result)
message = self._is_package_scan_allowed(search_result)

if message:
return self._response_for_select_package(
picking,
selected_lines,
message=message,
)

result_handler = getattr(
self, "_scan_package_action_from_" + search_result.type
)
return result_handler(picking, selected_lines, search_result.record)

def _check_scan_package_find_result(self, search_result):
ppt = self.work.menu.package_process_type
# Currently there is no known way to finish the checkout with a scan. To
# process without any package is only possible with a button. In its def
# a BadRequest is raised in case no package is not allowed
if not ppt or ppt == "with_package":
return

stype = search_result.type

if ppt == "without_package" and stype in [
"package",
"packaging",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"packaging",

packaging is a product packaging. This must be allowed

"delivery_packaging",
]:
return self.msg_store.invalid_scanned_checkout_object_wo_package(stype, ppt)

Comment on lines +939 to +955
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a docstring and rename this method.

Suggested change
def _check_scan_package_find_result(self, search_result):
ppt = self.work.menu.package_process_type
# Currently there is no known way to finish the checkout with a scan. To
# process without any package is only possible with a button. In its def
# a BadRequest is raised in case no package is not allowed
if not ppt or ppt == "with_package":
return
stype = search_result.type
if ppt == "without_package" and stype in [
"package",
"packaging",
"delivery_packaging",
]:
return self.msg_store.invalid_scanned_checkout_object_wo_package(stype, ppt)
def _is_package_scan_allowed(self, search_result):
if self._is_process_with_package_enabled():
return
package_process_type = self.work.menu.package_process_type
if package_process_type == "without_package" and search_result.type in [
"package",
"packaging",
"delivery_packaging",
]:
return self.msg_store.checkout_package_scan_is_not_allowed(search_result.type, package_process_type)

def _scan_package_find(self, picking, barcode, search_types=None):
search = self._actions_for("search")
search_types = (
Expand Down Expand Up @@ -1087,7 +1122,7 @@ def no_package(self, picking_id, selected_line_ids):
Transitions:
* select_line: goes back to selection of lines to work on next lines
"""
if self.options.get("checkout__disable_no_package"):
if self.work.menu.package_process_type == "with_package":
raise BadRequest("`checkout.no_package` endpoint is not enabled")
picking = self.env["stock.picking"].browse(picking_id)
message = self._check_picking_status(picking)
Expand Down Expand Up @@ -1562,7 +1597,12 @@ def _states(self):
"select_package": dict(
self._schema_selected_lines,
packing_info={"type": "string", "nullable": True},
no_package_enabled={
allow_with_package={
"type": "boolean",
"nullable": True,
"required": False,
},
allow_without_package={
"type": "boolean",
"nullable": True,
"required": False,
Expand Down
3 changes: 2 additions & 1 deletion shopfloor/tests/test_checkout_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ def _assert_select_package_qty_above(self, response, picking):
],
"picking": self._picking_summary_data(picking),
"packing_info": "",
"no_package_enabled": True,
"allow_with_package": True,
"allow_without_package": True,
},
message={
"message_type": "warning",
Expand Down
5 changes: 2 additions & 3 deletions shopfloor/tests/test_checkout_list_delivery_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,8 @@ def test_list_delivery_packaging_not_available(self):
self._move_line_data(ml) for ml in selected_lines.sorted()
],
"packing_info": self.service._data_for_packing_info(self.picking),
"no_package_enabled": not self.service.options.get(
"checkout__disable_no_package"
),
"allow_with_package": True,
"allow_without_package": True,
},
message=self.service.msg_store.no_delivery_packaging_available(),
)
4 changes: 2 additions & 2 deletions shopfloor/tests/test_checkout_no_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ def test_no_package_ok(self):
},
)

def test_no_package_disabled(self):
self.service.work.options = {"checkout__disable_no_package": True}
def test_without_package_disabled(self):
self.menu.sudo().package_process_type = "with_package"
with self.assertRaises(werkzeug.exceptions.BadRequest) as err:
self.service.dispatch(
"no_package",
Expand Down
Loading