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
23 changes: 17 additions & 6 deletions shopfloor_reception/services/reception.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ def _scan_line__find_or_create_line(self, picking, move, qty_done=1):
"""
unassigned_lines = self.env["stock.move.line"]
for line in move.move_line_ids:
if line.shopfloor_unloaded:
continue
if line.shopfloor_user_id.id == self.env.uid:
return self._scan_line__recover(picking, line, qty_done)
elif not line.shopfloor_user_id:
Expand Down Expand Up @@ -333,7 +335,7 @@ def _select_line__filter_lines_by_packaging__return(self, lines, packaging):
return_line = fields.first(
lines.filtered(
lambda l: not l.package_id.product_packaging_id
and not l.result_package_id
and not l.shopfloor_unloaded
and l.shopfloor_user_id.id in (False, self.env.uid)
)
)
Expand All @@ -350,7 +352,7 @@ def _select_line__filter_lines_by_packaging(self, lines, packaging):
return fields.first(
lines.filtered(
lambda l: l.package_id.product_packaging_id == packaging
and not l.result_package_id
and not l.shopfloor_unloaded
and l.shopfloor_user_id.id in [False, self.env.uid]
)
)
Expand Down Expand Up @@ -544,9 +546,12 @@ def _scan_line__by_lot(self, picking, lot):
"""
lines = picking.move_line_ids.filtered(
lambda l: (
lot == l.lot_id
or (lot.name == l.lot_name and lot.product_id == l.product_id)
and not l.result_package_id
(
lot == l.lot_id
or (lot.name == l.lot_name and lot.product_id == l.product_id)
)
and not l.shopfloor_unloaded
and l.shopfloor_user_id.id in (False, self.env.uid)
)
)
if not lines:
Expand All @@ -568,7 +573,9 @@ def _scan_line__by_lot(self, picking, lot):
def _scan_line__fallback(self, picking, barcode):
# We might have lines with no lot, but with a lot_name.
lines = picking.move_line_ids.filtered(
lambda l: l.lot_name == barcode and not l.result_package_id
lambda l: l.lot_name == barcode
and not l.shopfloor_unloaded
and l.shopfloor_user_id.id in (False, self.env.uid)
)
if not lines:
return self._response_for_select_move(
Expand Down Expand Up @@ -1380,7 +1387,11 @@ def process_without_pack(self, picking_id, selected_line_id, quantity):
return self._response_for_set_destination(picking, selected_line)

def _post_line(self, selected_line):
"""
Called when the product is unloaded at destination.
"""
selected_line.reserved_uom_qty = selected_line.qty_done
selected_line.shopfloor_unloaded = True
if (
selected_line.picking_id.is_shopfloor_created
and self.work.menu.allow_return
Expand Down
117 changes: 117 additions & 0 deletions shopfloor_reception/tests/test_select_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,93 @@ def test_scan_product(self):
},
)

def test_scan_product_partial(self):
# Scan a line
# Set a partial quantity done
# Try to scan the product again
# The selected line should be the other one
picking = self._create_picking()
lot = self._create_lot()
self.assertFalse(picking.printed)
selected_move_line = picking.move_line_ids.filtered(
lambda l: l.product_id == self.product_a
)

# Activate INPUT location
selected_move_line.location_dest_id.sudo().active = True

selected_move_line.lot_id = lot
response = self.service.dispatch(
"scan_line",
params={"picking_id": picking.id, "barcode": lot.name},
)
data = self.data.picking(picking)

self.assertTrue(selected_move_line.picking_id.printed)
self.assert_response(
response,
next_state="set_quantity",
data={
"picking": data,
"selected_move_line": self.data.move_lines(selected_move_line),
"confirmation_required": None,
},
)

selected_move_line.shopfloor_user_id = self.env.uid
response = self.service.dispatch(
"set_quantity",
params={
"picking_id": picking.id,
"selected_line_id": selected_move_line.id,
"quantity": 5.0,
},
)

response = self.service.dispatch(
"process_without_pack",
params={
"picking_id": picking.id,
"selected_line_id": selected_move_line.id,
"quantity": 5.0,
},
)
data = self.data.picking(picking)
self.assert_response(
response,
next_state="set_destination",
data={
"picking": data,
"selected_move_line": self.data.move_lines(selected_move_line),
},
)

response = self.service.dispatch(
"set_destination",
params={
"picking_id": picking.id,
"selected_line_id": selected_move_line.id,
"location_name": "INPUT",
},
)
self.assert_response(
response,
next_state="select_move",
data=self._data_for_select_move(picking),
)
lines = picking.move_line_ids.filtered(lambda l: l.product_id == self.product_a)
self.assertEqual(2, len(lines))
previous_line = selected_move_line

response = self.service.dispatch(
"scan_line",
params={"picking_id": picking.id, "barcode": lot.name},
)

self.assertNotEqual(
previous_line.id, response["data"]["set_lot"]["selected_move_line"][0]["id"]
)

def test_scan_packaging(self):
picking = self._create_picking()
self._add_package(picking)
Expand Down Expand Up @@ -93,6 +180,36 @@ def test_scan_lot(self):
},
)

def test_scan_lot_concurrent(self):
"""
If 2 operators work on the same lot, the second operator
should not steal the move line of the first.
"""
picking = self._create_picking()
lot = self._create_lot()

service_u1 = self.service
res_u1 = service_u1.dispatch(
"scan_line",
params={
"picking_id": picking.id,
"barcode": lot.name,
},
)
# User 2 starts working on the same move
service_u2 = self._get_service_for_user(self.shopfloor_manager)
res_u2 = service_u2.dispatch(
"scan_line",
params={
"picking_id": picking.id,
"barcode": lot.name,
},
)
self.assertNotEqual(
res_u1["data"]["set_lot"]["selected_move_line"][0]["id"],
res_u2["data"]["set_lot"]["selected_move_line"][0]["id"],
)

def test_scan_not_tracked_product(self):
self.product_a.tracking = "none"
picking = self._create_picking()
Expand Down
2 changes: 1 addition & 1 deletion shopfloor_reception/tests/test_set_destination.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def test_auto_posting_full_two_lines(self):
# One move remaining in the picking, for product b, still to be processed
self.assertEqual(picking.move_ids.product_id, self.product_b)

def test_auto_posting_concurent_work(self):
def test_auto_posting_concurrent_work(self):
"""Check 2 users working on the same move.

With the auto post line option On.
Expand Down