Ask to scan a tray type when no storage type is configured

The use cases we want to cover are:

1. Putaway for a package/good without storage type
2. Putaway for a package with a storage type configured to be
   stored in a tray (associated with a tray type)
3. Putaway for a package with a storage type NOT configured on a tray
   type

The case 1. is implement in "stock_vertical_lift", the 2. was already
implement in this module, this commit implements the case 3.

A typical flow is:

* We configure a generic Kardex Box storage type, not associated with
  any tray type, that is set on the package at reception (the reception
  person doesn't know the tray type at this point). this Kardex Box
  storage type is set on the Vertical Lift view (above the shuttles).
* On the putaway transfer, as per the configuration above, the putaway
  changes the destination location to the Vertical Lift view.
* When we scan the package in the shuttle's screen, as we have a storage
  type which is not configured on any locations in the shuttle
  (reminder, if we had, it would select the tray automatically), the
  user is asked to scan a tray type of the correct size.
This commit is contained in:
Guewen Baconnier
2020-07-03 08:13:20 +02:00
committed by Hai Lang
parent 48f3d60102
commit e83ea033c2
2 changed files with 89 additions and 8 deletions

View File

@@ -57,10 +57,44 @@ class VerticalLiftOperationPut(models.Model):
return tuple(updated_transitions)
def _has_storage_type(self):
def _has_storage_type_domain(self):
move_line = self.current_move_line_id
storage_type = move_line.package_id.package_storage_type_id
return bool(storage_type)
package_storage_type = move_line.package_id.package_storage_type_id
# When a put-away is done based on the package's storage type and no
# destination is found, we can have 2 reasons:
#
# 1. No location is available according to the storage types rules,
# for instance because they are full
# 2. The storage type of the package doesn't have any location
# configured in the shuttle's locations
#
# We want to differentiate the 2 cases and handle them differently.
# For 2. we consider the storage type is not meant to be in any
# shuttle's tray but the user still tries: act the same way as if we
# had no storage type at all, the user has to scan the tray type.
# For 1. we try to find a destination location and if none is found,
# a notification indicates that the shuttle is full.
# In any case, the user should always be able to scan a different
# tray type.
return [
("id", "!=", self.location_id.id),
("id", "child_of", self.location_id.id),
(
"allowed_location_storage_type_ids",
"in",
package_storage_type.location_storage_type_ids.ids,
),
]
def _has_storage_type(self):
domain = self._has_storage_type_domain()
# we don't care about order and count, only if we have at least one
# configured location for the storage type: sorting by id and limit by
# 1 will give the best explain plan
compatible_locations = self.env["stock.location"].search(
domain, limit=1, order="id"
)
return bool(compatible_locations)
def _putaway_with_storage_type(self):
move_line = self.current_move_line_id
@@ -74,6 +108,8 @@ class VerticalLiftOperationPut(models.Model):
move_line.package_level_id.location_dest_id = new_destination
self.fetch_tray()
return True
# no destination found: all the trays for this tray type are full, or rejected
# by the location storage type rules
return False
def _put_away_with_storage_type_failed(self):

View File

@@ -21,8 +21,24 @@ class TestPut(VerticalLiftCase):
{"name": "Small 8x", "only_empty": True}
)
# storage type used for Tray 1A
PackageStorageType = cls.env["stock.package.storage.type"]
# package storage type used only to putaway a package temporarily in
# the vertical lift view location before being put in a shuttle, which
# will not be configured in any shuttle's locations, we'll use when
# the operator knows that a good has to go in a shuttle, but doesn't
# know yet in which tray type: when the first putaway is done, the good
# stays in the vertical lift view (above the shuttles), then, when the
# user scans the package in a shuttle, they have to scan a tray type.
cls.package_storage_type_buffer = PackageStorageType.create(
{
"name": "VLift Box",
"location_storage_type_ids": [
(4, cls.location_storage_type_buffer.id),
],
}
)
# storage type used for Tray 1A, user won't have to scan a tray type
# when this storage type is already set on the package
cls.package_storage_type_small_8x = PackageStorageType.create(
{
"name": "Small 8x",
@@ -58,9 +74,7 @@ class TestPut(VerticalLiftCase):
}
)
cls.package = cls.env["stock.quant.package"].create(
{"package_storage_type_id": cls.package_storage_type_small_8x.id}
)
cls.package = cls.env["stock.quant.package"].create({})
cls._update_qty_in_location(
cls.wh.wh_input_stock_loc_id, cls.product_socks, 10, package=cls.package
)
@@ -97,6 +111,7 @@ class TestPut(VerticalLiftCase):
)
def test_storage_type_put_away(self):
self.package.package_storage_type_id = self.package_storage_type_small_8x
move_line = self.int_picking.move_line_ids
self.assertEqual(move_line.location_dest_id, self.vertical_lift_loc)
self.assertEqual(
@@ -113,8 +128,38 @@ class TestPut(VerticalLiftCase):
# the dest location was Vertical Lift, it has been change to Vertical
# Lift/Shuttle 1, and the computation from there took the first cell
# available, we should be the pos x1 and y1 in the tray A.
self.assertTrue(move_line.location_dest_id, self.location_1a_x1y1)
self.assertEqual(move_line.location_dest_id, self.location_1a_x1y1)
self.assertEqual(
move_line.package_level_id.location_dest_id, self.location_1a_x1y1
)
# the state goes straight to "save", as we don't need to scan the tray type
# when a putaway is available
self.assertEqual(operation.state, "save")
def test_storage_type_not_configured(self):
# if we do have a storage type, but the storage type is not used in the
# shuttle (although it may be used on the lift view location, so we can have an
# initial putaway rule that puts the package in the lift view location first),
# we have to ask to scan a tray type
self.package.package_storage_type_id = self.package_storage_type_buffer
move_line = self.int_picking.move_line_ids
self.assertEqual(move_line.location_dest_id, self.vertical_lift_loc)
self.assertEqual(
move_line.package_level_id.location_dest_id, self.vertical_lift_loc
)
operation = self._open_screen("put")
# we begin with an empty screen, user has to scan a package, product,
# or lot
self.assertEqual(operation.state, "scan_source")
operation.on_barcode_scanned(self.package.name)
self.assertEqual(operation.current_move_line_id, move_line)
# it stays here, as the put-away has no rule to put the "buffer box" in
# any location
self.assertEqual(move_line.location_dest_id, self.vertical_lift_loc)
# and the user has to scan a tray type (so we are back to the normal
# flow, tested in stock_vertical_lift)
self.assertEqual(operation.state, "scan_tray_type")