Skip to content
Open
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
60 changes: 46 additions & 14 deletions shopfloor_reception/services/reception.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
UTC = timezone.utc


class RollbackTransaction(Exception):
"""Internal exception used to trigger a savepoint rollback without bubbling up."""


class Reception(Component):
"""
Methods for the Reception Process
Expand Down Expand Up @@ -741,16 +745,35 @@ def _set_quantity__by_new_package(
selected_line.result_package_id = package
return self._response_for_set_destination(picking, selected_line)

def _set_quantity__by_location(self, picking, selected_line, location):
if not self.is_dest_location_valid(selected_line.move_id, location):
message = self.msg_store.dest_location_not_allowed()
return self._response_for_set_quantity(
picking, selected_line, message=message
def _set_quantity__by_location(self, picking, selected_line, location, quantity=1):
err_message = None
try:
with self.env.cr.savepoint():
self.process_without_pack(
picking.id,
selected_line.id,
quantity,
is_over_reception_confirmed=False,
)
response = self.set_destination(
picking.id,
selected_line.id,
location.name,
confirmation=location.name,
)
# If location wasn't applied, trigger rollback
if selected_line.location_dest_id != location:
err_message = response.get("message")
raise RollbackTransaction()
except RollbackTransaction:
# TODO: this is necessary because we hit `set_quantity__assign_quantity`
# before entering this function
selected_line.qty_done = 0

response = self._response_for_set_quantity(
picking, selected_line, message=err_message
)
# process without pack, set destination location, and go back to
# `select_move`
selected_line.location_dest_id = location
return self._response_for_select_move(picking)
return response

def _set_quantity__by_lot(self, picking, selected_line, lot):
if selected_line.lot_id.name == lot.name or selected_line.lot_name == lot.name:
Expand Down Expand Up @@ -821,7 +844,7 @@ def _response_for_set_lot(
self, picking, line, message=None, lot_name=None, lot_expiration_date=None, **kw
):
# ↓ In case "lot_name" is pre-filled on the line in odoo, pre-fill
# shpofloor screen
# shopfloor screen
if lot_name and not lot_expiration_date and not message:
lot = (
self._actions_for("search")
Expand Down Expand Up @@ -1399,19 +1422,18 @@ def _set_quantity__get_handlers_by_type(self):
"product": self._set_quantity__by_product,
"packaging": self._set_quantity__by_packaging,
"package": self._set_quantity__by_package,
"location": self._set_quantity__by_location,
"lot": self._set_quantity__by_lot,
}

def _set_quantity__by_barcode(
self, picking, selected_line, barcode, confirmation=None
self, picking, selected_line, barcode, confirmation=None, quantity=1
):
handlers_by_type = self._set_quantity__get_handlers_by_type()
search = self._actions_for("search").for_products(selected_line.product_id)
try:
search_result = search.find(
barcode,
handlers_by_type.keys(),
[*handlers_by_type.keys(), "location"],
)
except SearchInvalidProduct as e:
return self._response_for_set_quantity(
Expand All @@ -1423,6 +1445,12 @@ def _set_quantity__by_barcode(
if handler:
return handler(picking, selected_line, search_result.record)

# We scanned a location -> skip the "set destination" screen
if search_result.type == "location":
return self._set_quantity__by_location(
picking, selected_line, search_result.record, quantity
)

# Nothing found, ask user if we should create a new pack for the scanned
# barcode
return self._set_quantity__by_new_package(
Expand Down Expand Up @@ -1489,7 +1517,11 @@ def set_quantity(
# Then, we add the qty of whatever was scanned
# on top of the qty of the picker.
return self._set_quantity__by_barcode(
picking, selected_line, barcode, confirmation
picking,
selected_line,
barcode,
confirmation,
quantity if quantity else 1,
)
return self._response_for_set_quantity(picking, selected_line)

Expand Down
14 changes: 10 additions & 4 deletions shopfloor_reception/tests/test_set_quantity.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,11 @@ def test_scan_location_child_of_dest_location(self):
"picking_id": picking.id,
"selected_line_id": selected_move_line.id,
"barcode": self.dispatch_location.barcode,
"quantity": 4,
},
)
self.assertTrue(selected_move_line.shopfloor_unloaded)
self.assertEqual(selected_move_line.qty_done, 4)
self.assertEqual(selected_move_line.location_dest_id, self.dispatch_location)
self.assert_response(
response, next_state="select_move", data=self._data_for_select_move(picking)
Expand All @@ -342,18 +345,21 @@ def test_scan_location_not_child_of_dest_location(self):
"picking_id": picking.id,
"selected_line_id": selected_move_line.id,
"barcode": self.packing_location.barcode,
"quantity": 4,
},
)
data = self.data.picking(picking)

self.assertFalse(selected_move_line.shopfloor_unloaded)
self.assertEqual(selected_move_line.qty_done, 0)
self.assert_response(
response,
next_state="set_quantity",
data={
"picking": data,
"picking": self.data.picking(picking),
"selected_move_line": self.data.move_lines(selected_move_line),
"confirmation_required": None,
},
message={"message_type": "error", "body": "You cannot place it here"},
message=self.msg_store.dest_location_not_allowed(),
)

def test_scan_location_view_usage(self):
Expand Down Expand Up @@ -381,7 +387,7 @@ def test_scan_location_view_usage(self):
"selected_move_line": self.data.move_lines(selected_move_line),
"confirmation_required": None,
},
message={"message_type": "error", "body": "You cannot place it here"},
message=self.msg_store.dest_location_not_allowed(),
)

def test_scan_new_package(self):
Expand Down
24 changes: 18 additions & 6 deletions shopfloor_reception_putinpack_restriction/services/reception.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ def _check_picking_putinpack_restriction(self, picking, with_pack: bool):
if picking.put_in_pack_restriction == "with_package" and not with_pack:
return self.msg_store.package_required_for_operation(picking)

def process_with_existing_pack(self, picking_id, selected_line_id, quantity):
def process_with_existing_pack(
self, picking_id, selected_line_id, quantity, is_over_reception_confirmed=False
):
picking = self.env["stock.picking"].browse(picking_id)
selected_line = self.env["stock.move.line"].browse(selected_line_id)

Expand All @@ -28,11 +30,15 @@ def process_with_existing_pack(self, picking_id, selected_line_id, quantity):
return self._response_for_set_quantity(
picking, selected_line, message=message
)
res = super().process_with_existing_pack(picking_id, selected_line_id, quantity)
res = super().process_with_existing_pack(
picking_id, selected_line_id, quantity, is_over_reception_confirmed
)

return res

def process_with_new_pack(self, picking_id, selected_line_id, quantity):
def process_with_new_pack(
self, picking_id, selected_line_id, quantity, is_over_reception_confirmed=False
):
picking = self.env["stock.picking"].browse(picking_id)
selected_line = self.env["stock.move.line"].browse(selected_line_id)

Expand All @@ -42,11 +48,15 @@ def process_with_new_pack(self, picking_id, selected_line_id, quantity):
return self._response_for_set_quantity(
picking, selected_line, message=message
)
res = super().process_with_new_pack(picking_id, selected_line_id, quantity)
res = super().process_with_new_pack(
picking_id, selected_line_id, quantity, is_over_reception_confirmed
)

return res

def process_without_pack(self, picking_id, selected_line_id, quantity):
def process_without_pack(
self, picking_id, selected_line_id, quantity, is_over_reception_confirmed=False
):
picking = self.env["stock.picking"].browse(picking_id)
selected_line = self.env["stock.move.line"].browse(selected_line_id)

Expand All @@ -56,7 +66,9 @@ def process_without_pack(self, picking_id, selected_line_id, quantity):
return self._response_for_set_quantity(
picking, selected_line, message=message
)
res = super().process_without_pack(picking_id, selected_line_id, quantity)
res = super().process_without_pack(
picking_id, selected_line_id, quantity, is_over_reception_confirmed
)

return res

Expand Down
Loading