Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
12 commits
Select commit Hold shift + click to select a range
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
6 changes: 0 additions & 6 deletions shopfloor/actions/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,12 +526,6 @@ def packaging_not_found_in_picking(self):
"body": _("Packaging not found in the current transfer."),
}

def packaging_dimension_updated(self, packaging):
return {
"message_type": "success",
"body": _("Packaging {} dimension updated.").format(packaging.name),
}

def expiration_date_missing(self):
return {
"message_type": "error",
Expand Down
1 change: 1 addition & 0 deletions shopfloor_reception_packaging_dimension/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .hooks import post_init_hook, uninstall_hook
from . import models
from . import services
from . import actions
3 changes: 3 additions & 0 deletions shopfloor_reception_packaging_dimension/actions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import data
from . import schema
from . import message
25 changes: 25 additions & 0 deletions shopfloor_reception_packaging_dimension/actions/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from odoo.addons.component.core import Component
from odoo.addons.shopfloor_base.utils import ensure_model


class DataAction(Component):
_inherit = "shopfloor.data.action"

@property
def _packaging_dimension_detail_parser(self):
return [
"id",
"name",
"qty",
"packaging_length",
"width",
"height",
"weight",
"length_uom_name",
"weight_uom_name",
"barcode",
]

@ensure_model("product.packaging")
def packaging_dimensions(self, record, **kw):
return self._jsonify(record, self._packaging_dimension_detail_parser, **kw)
17 changes: 17 additions & 0 deletions shopfloor_reception_packaging_dimension/actions/message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import logging

from odoo import _

from odoo.addons.component.core import Component

_logger = logging.getLogger(__name__)


class MessageAction(Component):
_inherit = "shopfloor.message.action"

def packaging_updated(self, packaging):
return {
"message_type": "success",
"body": _("Packaging '{}' updated.").format(packaging.name),
}
27 changes: 27 additions & 0 deletions shopfloor_reception_packaging_dimension/actions/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from odoo.addons.component.core import Component


class ShopfloorSchemaAction(Component):
_inherit = "shopfloor.schema.action"

def packaging_dimensions(self):
return {
"id": {"required": True, "type": "integer"},
"name": {"type": "string", "nullable": False, "required": True},
"qty": {"type": "float", "required": True},
"packaging_length": {"type": "float", "nullable": True, "required": False},
"width": {"type": "float", "nullable": True, "required": False},
"height": {"type": "float", "nullable": True, "required": False},
"weight": {"type": "float", "nullable": True, "required": False},
"length_uom_name": {
"type": "string",
"nullable": True,
"required": False,
},
"weight_uom_name": {
"type": "string",
"nullable": True,
"required": False,
},
"barcode": {"type": "string", "nullable": True, "required": False},
}
81 changes: 47 additions & 34 deletions shopfloor_reception_packaging_dimension/services/reception.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ def __init__(self, work_context):

def _before_state__set_quantity(self, picking, line, message=None):
"""Show the packaging dimension screen before the set quantity screen."""
if self.work.menu.set_packaging_dimension and not self.packaging_update_done:
packaging = self._get_next_packaging_to_set_dimension(line.product_id)
if packaging:
return self._response_for_set_packaging_dimension(
picking, line, packaging, message=message
)
return super()._before_state__set_quantity(picking, line, message=message)
if not self.work.menu.set_packaging_dimension or self.packaging_update_done:
return super()._before_state__set_quantity(picking, line, message=message)

packaging = self._get_next_packaging_to_set_dimension(line.product_id)
if not packaging:
return super()._before_state__set_quantity(picking, line, message=message)

return self._response_for_set_packaging_dimension(
picking, line, packaging, message=message
)

def _get_domain_packaging_needs_dimension(self):
return expression.OR(
Expand Down Expand Up @@ -86,14 +89,14 @@ def _response_for_set_packaging_dimension(
)

def _set_packaging_dimension_data_for_packaging(self, packaging):
return self.data_detail.packaging_detail(packaging)
return self.data.packaging_dimensions(packaging)

def set_packaging_dimension(
self, picking_id, selected_line_id, packaging_id, cancel=False, **kwargs
self, picking_id, selected_line_id, packaging_id, skip=False, **kwargs
):
"""Set the dimension on a product packaging.

If the user cancel the dimension update we still propose the next
If the user skip the dimension update we still propose the next
possible packaging.

Transitions:
Expand All @@ -103,38 +106,48 @@ def set_packaging_dimension(
picking = self.env["stock.picking"].browse(picking_id)
selected_line = self.env["stock.move.line"].browse(selected_line_id)
packaging = self.env["product.packaging"].sudo().browse(packaging_id)
message = None
next_packaging = None

if not packaging:
message = self.msg_store.record_not_found()
elif not cancel and self._check_dimension_to_update(kwargs):
self._update_packaging_dimension(packaging, kwargs)
message = self.msg_store.packaging_dimension_updated(packaging)
if packaging:
next_packaging = self._get_next_packaging_to_set_dimension(
selected_line.product_id, packaging
return self._before_state__set_quantity(
picking, selected_line, message=self.msg_store.record_not_found()
)

message = None

if not skip and self._check_dimension_to_update(kwargs):
self._update_packaging_dimension(packaging, kwargs)
message = self.msg_store.packaging_updated(packaging)

next_packaging = self._get_next_packaging_to_set_dimension(
selected_line.product_id, packaging
)
if next_packaging:
return self._response_for_set_packaging_dimension(
picking, selected_line, next_packaging, message=message
)

self.packaging_update_done = True
return self._before_state__set_quantity(picking, selected_line, message=message)

def _check_dimension_to_update(self, dimensions):
"""Return True if any dimension on the packaging needs to be updated"""
return any([value is not None for key, value in dimensions.items()])

def _get_dimension_fields_conversion_map(self):
return {"length": "packaging_length"}
"""Check if the Shopfloor payload contains data for a packaging update."""
return any(value is not None for value in dimensions.values())

def _update_packaging_dimension(self, packaging, dimensions_to_update):
"""Update dimension on the packaging."""
fields_conv_map = self._get_dimension_fields_conversion_map()
for dimension, value in dimensions_to_update.items():
if value is not None:
dimension = fields_conv_map.get(dimension, dimension)
packaging[dimension] = value
values_to_update = {}
packaging_values = packaging.read(dimensions_to_update.keys())[0]

for key, value in dimensions_to_update.items():
if value is None:
continue
# Skip updating fields with unchanged values to prevent unnecessary
# triggers of compute methods or other side effects
if packaging_values[key] != value:
values_to_update[key] = value

if values_to_update:
packaging.write(values_to_update)


class ShopfloorReceptionValidator(Component):
Expand All @@ -155,7 +168,7 @@ def set_packaging_dimension(self):
"type": "float",
"nullable": True,
},
"length": {
"packaging_length": {
"coerce": to_float,
"required": False,
"type": "float",
Expand Down Expand Up @@ -186,7 +199,7 @@ def set_packaging_dimension(self):
"nullable": True,
},
"barcode": {"type": "string", "required": False, "nullable": True},
"cancel": {"type": "boolean"},
"skip": {"type": "boolean"},
}


Expand All @@ -213,13 +226,13 @@ def _schema_set_packaging_dimension(self):
return {
"picking": {"type": "dict", "schema": self.schemas.picking()},
"selected_move_line": {"type": "dict", "schema": self.schemas.move_line()},
"packaging": self._schema_packaging(),
"packaging": self._schema_packaging_dimensions(),
}

def _schema_packaging(self):
def _schema_packaging_dimensions(self):
return {
"type": "dict",
"schema": self.schemas_detail.packaging_detail(),
"schema": self.schemas.packaging_dimensions(),
}

def _set_packaging_dimension_next_states(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _assert_response_set_dimension(
data = {
"picking": self.data.picking(picking),
"selected_move_line": self.data.move_line(line),
"packaging": self.data_detail.packaging_detail(packaging),
"packaging": self.data.packaging_dimensions(packaging),
}
self.assert_response(
response,
Expand Down Expand Up @@ -206,7 +206,7 @@ def test_set_multiple_packaging_dimension(self):
"selected_line_id": line.id,
"packaging_id": self.product_c_packaging.id,
"height": 55,
"length": 233,
"packaging_length": 233,
},
)
self.assertEqual(self.product_c_packaging.height, 55)
Expand All @@ -216,9 +216,7 @@ def test_set_multiple_packaging_dimension(self):
self.picking,
line,
self.product_c_packaging_2,
message=self.msg_store.packaging_dimension_updated(
self.product_c_packaging
),
message=self.msg_store.packaging_updated(self.product_c_packaging),
)
response = self.service.dispatch(
"set_packaging_dimension",
Expand All @@ -240,7 +238,35 @@ def test_set_multiple_packaging_dimension(self):
"selected_move_line": self.data.move_lines(line),
"confirmation_required": None,
},
message=self.msg_store.packaging_dimension_updated(
self.product_c_packaging_2
),
message=self.msg_store.packaging_updated(self.product_c_packaging_2),
)

def test_skip_packaging_dimension_skips_to_next(self):
line = self.picking.move_line_ids.filtered(
lambda li: li.product_id == self.product_c
)
original_height = self.product_c_packaging.height

response = self.service.dispatch(
"set_packaging_dimension",
params={
"picking_id": self.picking.id,
"selected_line_id": line.id,
"packaging_id": self.product_c_packaging.id,
"height": 999.0, # This value should be ignored
"skip": True,
},
)

self.assertEqual(
self.product_c_packaging.height,
original_height,
"Packaging height should not change when skipped",
)
self._assert_response_set_dimension(
response,
self.picking,
line,
self.product_c_packaging_2,
message=None, # No 'Updated' message should be returned when skipping
)
Loading
Loading