mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
@@ -0,0 +1 @@
|
||||
../../../../stock_picking_consolidation_priority
|
||||
6
setup/stock_picking_consolidation_priority/setup.py
Normal file
6
setup/stock_picking_consolidation_priority/setup.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
||||
1
stock_picking_consolidation_priority/__init__.py
Normal file
1
stock_picking_consolidation_priority/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
15
stock_picking_consolidation_priority/__manifest__.py
Normal file
15
stock_picking_consolidation_priority/__manifest__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright 2020 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
"name": "Stock Transfers Consolidation Priority",
|
||||
"summary": "Raise priority of all transfers for a chain when started",
|
||||
"version": "13.0.1.0.0",
|
||||
"author": "Camptocamp, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
||||
"category": "Stock Management",
|
||||
"depends": ["stock"],
|
||||
"data": [],
|
||||
"installable": True,
|
||||
"license": "AGPL-3",
|
||||
}
|
||||
2
stock_picking_consolidation_priority/models/__init__.py
Normal file
2
stock_picking_consolidation_priority/models/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import stock_picking_type
|
||||
from . import stock_move
|
||||
122
stock_picking_consolidation_priority/models/stock_move.py
Normal file
122
stock_picking_consolidation_priority/models/stock_move.py
Normal file
@@ -0,0 +1,122 @@
|
||||
# Copyright 2020 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from odoo import models
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
_consolidate_priority_value = "3"
|
||||
|
||||
def _action_done(self, cancel_backorder=False):
|
||||
moves_to_check = super()._action_done(cancel_backorder=cancel_backorder)
|
||||
moves_to_check.filtered(lambda move: move.state == "done")
|
||||
if moves_to_check:
|
||||
moves_to_check._consolidate_priority()
|
||||
return moves_to_check
|
||||
|
||||
def _query_get_consolidate_moves(self):
|
||||
"""Return a query to find the moves to consolidate in priority
|
||||
|
||||
Consider this chain of moves::
|
||||
|
||||
PICK/001 ━► PACK/001 ┓
|
||||
┃
|
||||
PICK/002 ┓ ┣━► OUT/001
|
||||
┣━► PACK/002 ┛
|
||||
INT/001 ━► PICK/003 ┛
|
||||
|
||||
If the flag "consolidate_priority" is set on the picking type of OUT,
|
||||
as soon as one of the move of PACK/001 or PACK/002 is done, all the
|
||||
moves of the INT, 3 PICK, and the 2 PACK must be returned to have their
|
||||
priority raised, as we want to consolidate everything asap in OUT/001.
|
||||
|
||||
If the flag is set on PACK and one move in PICK/001 is set to done,
|
||||
other moves of PICK/001 are returned to finish PACK/001.
|
||||
|
||||
If the flag is set on PACK and one move in PICK/002 is set to done, all
|
||||
the moves of INT/001 and PICK/003 and the other moves of PICK/002 have
|
||||
to be returned as they will help to consolidate PACK/002.
|
||||
|
||||
|
||||
If the flag is set on PACK, when a move in INT/001 is set to done,
|
||||
nothing happens, but when a move in PICK/003 is set to done, all the
|
||||
moves of INT/001 and PICK/002 and the other moves of PICK/003 have to
|
||||
be returned as they will help to consolidate PACK/002.
|
||||
|
||||
If the flag is set on both PACK and OUT, the result is the same as the
|
||||
first case: all PICK and PACK are returned.
|
||||
"""
|
||||
query = """
|
||||
WITH RECURSIVE
|
||||
-- For every destination move for which we have the flag set, walk back
|
||||
-- through stock_move_move_rel to find all the origin moves
|
||||
origins (id, picking_id, is_consolidation_dest) AS (
|
||||
-- Find the destination move of the current moves which have the flag
|
||||
-- consolidate_priority on their picking type. From there, find all
|
||||
-- the other moves of the consolidation transfer.
|
||||
-- They are the starting point to search the origin moves.
|
||||
-- In the final query, the rows with "consolidate_priority" equal
|
||||
-- to true are excluded, because we want to raise the priority of
|
||||
-- the moves *before* the picking type with the flag
|
||||
SELECT consolidation_dest_moves.id,
|
||||
stock_picking.id,
|
||||
stock_picking_type.consolidate_priority as is_consolidation_dest
|
||||
FROM stock_move_move_rel
|
||||
INNER JOIN stock_move move_dest
|
||||
ON move_dest.id = stock_move_move_rel.move_dest_id
|
||||
INNER JOIN stock_picking
|
||||
ON stock_picking.id = move_dest.picking_id
|
||||
-- select *all* the moves of the transfer with the consolidation flag,
|
||||
-- origin moves will be searched for all of them in the recursive part
|
||||
INNER JOIN stock_move consolidation_dest_moves
|
||||
ON consolidation_dest_moves.picking_id = stock_picking.id
|
||||
INNER JOIN stock_picking_type
|
||||
ON stock_picking_type.id = stock_picking.picking_type_id
|
||||
WHERE stock_move_move_rel.move_orig_id IN %s
|
||||
AND stock_picking_type.consolidate_priority = true
|
||||
|
||||
-- We use union here to keep duplicate in case a move both has the
|
||||
-- flag "consolidate_priority" on its picking type AND is the
|
||||
-- origin move for another move with the flag (e.g, option
|
||||
-- activated both on PACK and OUT). Anyway, the final query filters
|
||||
-- on the second part of the union.
|
||||
UNION ALL
|
||||
|
||||
-- recurse to find all the origin moves which have a destination that
|
||||
-- needs priority consolidation
|
||||
SELECT move_orig.id,
|
||||
move_orig.picking_id,
|
||||
false as is_consolidation_dest
|
||||
FROM stock_move move_orig
|
||||
INNER JOIN stock_move_move_rel
|
||||
ON move_orig.id = stock_move_move_rel.move_orig_id
|
||||
INNER JOIN origins
|
||||
ON origins.id = stock_move_move_rel.move_dest_id
|
||||
)
|
||||
SELECT id FROM origins WHERE is_consolidation_dest = false
|
||||
"""
|
||||
return (query, (tuple(self.ids),))
|
||||
|
||||
def _consolidate_priority_domain(self):
|
||||
return [("state", "not in", ("cancel", "done"))]
|
||||
|
||||
def _consolidate_priority_values(self):
|
||||
return {"priority": self._consolidate_priority_value}
|
||||
|
||||
def _consolidate_priority(self):
|
||||
self.flush(["move_dest_ids", "move_orig_ids", "picking_id"])
|
||||
self.env["stock.picking"].flush(["picking_type_id"])
|
||||
self.env["stock.picking.type"].flush(["consolidate_priority"])
|
||||
query, params = self._query_get_consolidate_moves()
|
||||
self.env.cr.execute(query, params)
|
||||
move_ids = [row[0] for row in self.env.cr.fetchall()]
|
||||
if not move_ids:
|
||||
return
|
||||
moves = self.search(
|
||||
expression.AND(
|
||||
[[("id", "in", move_ids)], self._consolidate_priority_domain()]
|
||||
)
|
||||
)
|
||||
moves.write(self._consolidate_priority_values())
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright 2020 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class StockPickingType(models.Model):
|
||||
_inherit = "stock.picking.type"
|
||||
|
||||
consolidate_priority = fields.Boolean(
|
||||
string="Raise priority when partially available",
|
||||
help="Tick this box to raise the priority of all previous related"
|
||||
" picking when current transfer will be made partially available."
|
||||
" This is usually used in packing zone when several people work"
|
||||
" on different transfers to be consolidated in the packing zone."
|
||||
" When the first one finish, all other related pickings gets with"
|
||||
" a high priority. The goal is to reduce the number of order being"
|
||||
" packed at the same time as the space is often limited.",
|
||||
default=False,
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
Update the flag "Raise priority when partially available" on Operation Types.
|
||||
@@ -0,0 +1 @@
|
||||
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
||||
14
stock_picking_consolidation_priority/readme/DESCRIPTION.rst
Normal file
14
stock_picking_consolidation_priority/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1,14 @@
|
||||
As the number of packing space is usually limited, if someone starts to prepare
|
||||
an order by picking it in a zone, all other related picking in the other zones
|
||||
should be of a higher priority. This should make a "started" order a priority
|
||||
for all.
|
||||
|
||||
This module adds an option "Raise priority when partially available" on
|
||||
operation types.
|
||||
|
||||
When the option is set on an operation type, the first time a packing operation
|
||||
is made partially available (goods have been moved for instance from a picking),
|
||||
all the other moves that will bring goods for the same packing transfer have
|
||||
their priority raised to "Very Urgent". If the moves that bring goods to the
|
||||
packing transfer involves a chain of several moves, all the moves of the chain
|
||||
have their priority raised.
|
||||
3
stock_picking_consolidation_priority/readme/ROADMAP.rst
Normal file
3
stock_picking_consolidation_priority/readme/ROADMAP.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
* The priority is hardcoded to "Very Urgent", it could be made configurable.
|
||||
That being said, it's easy enough to override ``_consolidate_priority_value``
|
||||
to customize the level.
|
||||
1
stock_picking_consolidation_priority/tests/__init__.py
Normal file
1
stock_picking_consolidation_priority/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import test_consolidation_priority
|
||||
@@ -0,0 +1,345 @@
|
||||
# Copyright 2020 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
from odoo.tests.common import SavepointCase
|
||||
|
||||
|
||||
class TestConsolidationPriority(SavepointCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
cls.warehouse = cls.env.ref("stock.warehouse0")
|
||||
cls.warehouse.write({"delivery_steps": "pick_pack_ship"})
|
||||
cls.stock_shelf_location = cls.env.ref("stock.stock_location_components")
|
||||
cls.customers_location = cls.env.ref("stock.stock_location_customers")
|
||||
cls.product_a = cls.env["product.product"].create(
|
||||
{"name": "Product A", "type": "product"}
|
||||
)
|
||||
cls.product_b = cls.env["product.product"].create(
|
||||
{"name": "Product B", "type": "product"}
|
||||
)
|
||||
|
||||
cls.pick_type = cls.warehouse.pick_type_id
|
||||
cls.pack_type = cls.warehouse.pack_type_id
|
||||
cls.out_type = cls.warehouse.out_type_id
|
||||
cls.int_type = cls.warehouse.int_type_id
|
||||
cls.procurement_group_1 = cls.env["procurement.group"].create(
|
||||
{"name": "Test 1"}
|
||||
)
|
||||
|
||||
cls.chain = cls.build_moves()
|
||||
|
||||
@classmethod
|
||||
def _update_qty_in_location(cls, location, product, quantity):
|
||||
cls.env["stock.quant"]._update_available_quantity(product, location, quantity)
|
||||
|
||||
@classmethod
|
||||
def _create_move(cls, name, picking_type, product, quantity, move_orig=None):
|
||||
move_vals = {
|
||||
"name": name,
|
||||
"picking_type_id": picking_type.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_qty": 2.0,
|
||||
"product_uom": product.uom_id.id,
|
||||
"location_id": picking_type.default_location_src_id.id,
|
||||
"location_dest_id": picking_type.default_location_dest_id.id
|
||||
or cls.customers_location.id,
|
||||
"state": "confirmed",
|
||||
"procure_method": "make_to_stock",
|
||||
"group_id": cls.procurement_group_1.id,
|
||||
}
|
||||
if move_orig:
|
||||
move_vals.update(
|
||||
{
|
||||
"procure_method": "make_to_order",
|
||||
"state": "waiting",
|
||||
"move_orig_ids": [(6, 0, move_orig.ids)],
|
||||
}
|
||||
)
|
||||
return cls.env["stock.move"].create(move_vals)
|
||||
|
||||
@classmethod
|
||||
def _create_picking(cls, moves):
|
||||
picking = cls.env["stock.picking"].create(moves._get_new_picking_values())
|
||||
moves.picking_id = picking.id
|
||||
return picking
|
||||
|
||||
@classmethod
|
||||
def build_moves(cls):
|
||||
"""Build a chain of moves and transfer
|
||||
|
||||
That looks like:
|
||||
|
||||
PICK/001 ━► PACK/001 ┓
|
||||
┃
|
||||
PICK/002 ┓ ┣━► OUT/001
|
||||
┣━► PACK/002 ┛
|
||||
INT/001 ━► PICK/003 ┛
|
||||
|
||||
Each contains 2 moves, one for product and one for product2
|
||||
"""
|
||||
Chain = namedtuple(
|
||||
"chain",
|
||||
"int1_a int1_b"
|
||||
# slots for the moves (product a, product b)
|
||||
" pick1_a pick1_b"
|
||||
" pick2_a pick2_b"
|
||||
" pick3_a pick3_b"
|
||||
" pack1_a pack1_b"
|
||||
" pack2_a pack2_b"
|
||||
" out1_a out1_b",
|
||||
)
|
||||
|
||||
int1_a = cls._create_move("int1_a", cls.int_type, cls.product_a, 2)
|
||||
int1_b = cls._create_move("int1_b", cls.int_type, cls.product_b, 2)
|
||||
cls._create_picking(int1_a + int1_b)
|
||||
|
||||
pick1_a = cls._create_move("pick1_a", cls.pick_type, cls.product_a, 2)
|
||||
pick1_b = cls._create_move("pick1_b", cls.pick_type, cls.product_b, 2)
|
||||
cls._create_picking(pick1_a + pick1_b)
|
||||
|
||||
pick2_a = cls._create_move("pick2_a", cls.pick_type, cls.product_a, 2)
|
||||
pick2_b = cls._create_move("pick2_b", cls.pick_type, cls.product_b, 2)
|
||||
cls._create_picking(pick2_a + pick2_b)
|
||||
|
||||
pick3_a = cls._create_move(
|
||||
"pick3_a", cls.pick_type, cls.product_a, 2, move_orig=int1_a
|
||||
)
|
||||
pick3_b = cls._create_move(
|
||||
"pick3_b", cls.pick_type, cls.product_b, 2, move_orig=int1_b
|
||||
)
|
||||
cls._create_picking(pick3_a + pick3_b)
|
||||
|
||||
pack1_a = cls._create_move(
|
||||
"pack1_a", cls.pack_type, cls.product_a, 2, move_orig=pick1_a
|
||||
)
|
||||
pack1_b = cls._create_move(
|
||||
"pack1_b", cls.pack_type, cls.product_b, 2, move_orig=pick1_b
|
||||
)
|
||||
cls._create_picking(pack1_a + pack1_b)
|
||||
|
||||
pack2_a = cls._create_move(
|
||||
"pack2_a", cls.pack_type, cls.product_a, 4, move_orig=pick2_a + pick3_a
|
||||
)
|
||||
pack2_b = cls._create_move(
|
||||
"pack2_b", cls.pack_type, cls.product_b, 4, move_orig=pick2_b + pick3_b
|
||||
)
|
||||
cls._create_picking(pack2_a + pack2_b)
|
||||
|
||||
out1_a = cls._create_move(
|
||||
"out1_a", cls.out_type, cls.product_a, 6, move_orig=pack1_a + pack2_a
|
||||
)
|
||||
out1_b = cls._create_move(
|
||||
"out2_b", cls.out_type, cls.product_b, 6, move_orig=pack1_b + pack2_b
|
||||
)
|
||||
cls._create_picking(out1_a + out1_b)
|
||||
|
||||
return Chain(
|
||||
int1_a,
|
||||
int1_b,
|
||||
pick1_a,
|
||||
pick1_b,
|
||||
pick2_a,
|
||||
pick2_b,
|
||||
pick3_a,
|
||||
pick3_b,
|
||||
pack1_a,
|
||||
pack1_b,
|
||||
pack2_a,
|
||||
pack2_b,
|
||||
out1_a,
|
||||
out1_b,
|
||||
)
|
||||
|
||||
def _enable_consolidate_priority(self, picking_types):
|
||||
picking_types.consolidate_priority = True
|
||||
picking_types.flush()
|
||||
|
||||
def _test_query(self, starting_move, expected):
|
||||
# we test only the result of the graph in this test, cancel/done move
|
||||
# are not filtered out, as they are filtered later
|
||||
query, params = starting_move._query_get_consolidate_moves()
|
||||
self.env.cr.execute(query, params)
|
||||
move_ids = [row[0] for row in self.env.cr.fetchall()]
|
||||
moves = self.env["stock.move"].browse(move_ids)
|
||||
self.assertEqual(
|
||||
moves,
|
||||
expected,
|
||||
"Priorities are not correct.\n\nExpected:\n{}\n\nGot:\n{}".format(
|
||||
"\n".join(
|
||||
[
|
||||
"* {}: {}".format(move.id, move.name)
|
||||
for move in expected.sorted()
|
||||
]
|
||||
),
|
||||
"\n".join(
|
||||
["* {}: {}".format(move.id, move.name) for move in moves.sorted()]
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
def test_query_graph_out1(self):
|
||||
# enable on OUT
|
||||
self._enable_consolidate_priority(self.chain.out1_a.picking_type_id)
|
||||
c = self.chain
|
||||
# these ones do not directly bring goods to OUT
|
||||
self._test_query(c.pick1_a, self.env["stock.move"])
|
||||
self._test_query(c.pick2_a, self.env["stock.move"])
|
||||
self._test_query(c.int1_a, self.env["stock.move"])
|
||||
self._test_query(c.pick3_a, self.env["stock.move"])
|
||||
all_before_out = (
|
||||
c.int1_a
|
||||
+ c.int1_b
|
||||
+ c.pick1_a
|
||||
+ c.pick1_b
|
||||
+ c.pick2_a
|
||||
+ c.pick2_b
|
||||
+ c.pick3_a
|
||||
+ c.pick3_b
|
||||
+ c.pack1_a
|
||||
+ c.pack1_b
|
||||
+ c.pack2_a
|
||||
+ c.pack2_b
|
||||
)
|
||||
# these ones do directly bring goods to OUT, they consolidate the moves
|
||||
# before
|
||||
self._test_query(c.pack1_a, all_before_out)
|
||||
self._test_query(c.pack2_a, all_before_out)
|
||||
|
||||
def test_query_graph_pack1(self):
|
||||
# enable on PACK
|
||||
self._enable_consolidate_priority(self.chain.pack1_a.picking_type_id)
|
||||
c = self.chain
|
||||
# this one does not directly bring goods to PACK
|
||||
self._test_query(c.int1_a, self.env["stock.move"])
|
||||
# these ones do directly bring goods to PACK, they consolidate the moves
|
||||
# before
|
||||
self._test_query(c.pick1_a, c.pick1_a + c.pick1_b)
|
||||
all_before_pack2 = (
|
||||
c.int1_a + c.int1_b + c.pick2_a + c.pick2_b + c.pick3_a + c.pick3_b
|
||||
)
|
||||
self._test_query(c.pick2_a, all_before_pack2)
|
||||
self._test_query(c.pick3_a, all_before_pack2)
|
||||
|
||||
def test_query_graph_out1_pack1(self):
|
||||
# enable on OUT and PACK
|
||||
self._enable_consolidate_priority(
|
||||
self.chain.out1_a.picking_type_id | self.chain.pack1_a.picking_type_id
|
||||
)
|
||||
c = self.chain
|
||||
all_before_out = (
|
||||
c.int1_a
|
||||
+ c.int1_b
|
||||
+ c.pick1_a
|
||||
+ c.pick1_b
|
||||
+ c.pick2_a
|
||||
+ c.pick2_b
|
||||
+ c.pick3_a
|
||||
+ c.pick3_b
|
||||
+ c.pack1_a
|
||||
+ c.pack1_b
|
||||
+ c.pack2_a
|
||||
+ c.pack2_b
|
||||
)
|
||||
self._test_query(c.pack1_a, all_before_out)
|
||||
self._test_query(c.pack2_a, all_before_out)
|
||||
self._test_query(c.pick1_a, c.pick1_a + c.pick1_b)
|
||||
all_before_pack2 = (
|
||||
c.int1_a + c.int1_b + c.pick2_a + c.pick2_b + c.pick3_a + c.pick3_b
|
||||
)
|
||||
self._test_query(c.pick2_a, all_before_pack2)
|
||||
|
||||
def _move_to_done(self, move):
|
||||
self._update_qty_in_location(
|
||||
move.location_id, move.product_id, move.product_uom_qty
|
||||
)
|
||||
move.picking_id.action_assign()
|
||||
for line in move.move_line_ids:
|
||||
line.qty_done = line.product_uom_qty
|
||||
move.picking_id.action_done()
|
||||
self.assertEqual(move.state, "done")
|
||||
|
||||
def all_chain_moves(self):
|
||||
return self.env["stock.move"].union(*[c for c in self.chain])
|
||||
|
||||
def assert_priority(self, changed_moves, unchanged_moves):
|
||||
expected_priority = self.env["stock.move"]._consolidate_priority_value
|
||||
changed_ok = all(move.priority == expected_priority for move in changed_moves)
|
||||
unchanged_ok = all(move.priority == "1" for move in unchanged_moves)
|
||||
self.assertTrue(
|
||||
changed_ok and unchanged_ok,
|
||||
"Priorities are not correct.\n\nExpected:\n{}\n{}\n\nGot:\n{}".format(
|
||||
"\n".join(
|
||||
[
|
||||
"* {}: {}".format(move.name, expected_priority)
|
||||
for move in changed_moves.sorted("id")
|
||||
]
|
||||
),
|
||||
"\n".join(
|
||||
[
|
||||
"* {}: {}".format(move.name, "1")
|
||||
for move in unchanged_moves.sorted("id")
|
||||
]
|
||||
),
|
||||
"\n".join(
|
||||
[
|
||||
"* {}: {}".format(move.name, move.priority)
|
||||
for move in self.all_chain_moves().sorted(
|
||||
lambda m: (-int(m.priority), m.id)
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
def assert_default_priority(self):
|
||||
self.assert_priority(
|
||||
# nothing is changed yet
|
||||
self.env["stock.move"],
|
||||
# all moves are unchanged
|
||||
self.all_chain_moves(),
|
||||
)
|
||||
|
||||
def test_flow_pick1_done_out1_consolidate(self):
|
||||
c = self.chain
|
||||
# enable on OUT
|
||||
self._enable_consolidate_priority(c.out1_a.picking_type_id)
|
||||
self._move_to_done(self.chain.pick1_a)
|
||||
self.assert_default_priority()
|
||||
self._move_to_done(self.chain.pack1_a)
|
||||
self.assert_priority(
|
||||
c.int1_a
|
||||
+ c.int1_b
|
||||
+ c.pick1_b
|
||||
+ c.pick2_a
|
||||
+ c.pick2_b
|
||||
+ c.pick3_a
|
||||
+ c.pick3_b
|
||||
+ c.pack1_b
|
||||
+ c.pack2_a,
|
||||
# pick1 and pack2 are unchanged as already done
|
||||
c.pack1_a + c.pick1_a + c.out1_a + c.out1_b,
|
||||
)
|
||||
|
||||
def test_flow_int1_done_pack_consolidate(self):
|
||||
c = self.chain
|
||||
# enable on PACK
|
||||
self._enable_consolidate_priority(c.pack2_a.picking_type_id)
|
||||
self._move_to_done(c.int1_a)
|
||||
self.assert_default_priority()
|
||||
self._move_to_done(c.pick3_a)
|
||||
self.assert_priority(
|
||||
c.int1_b + c.pick2_a + c.pick2_b + c.pick3_b,
|
||||
# int1 and pick3 are unchanged as already done
|
||||
c.int1_a + c.pick3_a
|
||||
# only moves *before* packs are changed
|
||||
+ c.pack1_a + c.pack1_b + c.pack2_a + c.pack2_b
|
||||
# pick1 is unchanged because they don't
|
||||
# go to the same transfer
|
||||
+ c.pick1_a + c.pick1_b
|
||||
# outgoing moves are late to the party, no impact on them
|
||||
+ c.out1_a + c.out1_b,
|
||||
)
|
||||
Reference in New Issue
Block a user