Skip to content

Commit

Permalink
Fix use case with different moves, keep only one picking
Browse files Browse the repository at this point in the history
  • Loading branch information
guewen committed Jul 5, 2019
1 parent 4ab2334 commit a7dc125
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 51 deletions.
2 changes: 1 addition & 1 deletion stock_picking_zone/demo/stock_location_demo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<record id="stock_location_handover_demo" model="stock.location">
<field name="name">Handover</field>
<field name="location_id" model="stock.location"
eval="obj().env.ref('stock.warehouse0').view_location_id.id"/>
eval="obj().env.ref('stock.warehouse0').lot_stock_id.id"/>
</record>

</odoo>
4 changes: 2 additions & 2 deletions stock_picking_zone/models/stock_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ def _insert_middle_moves(self):
self.write({
'move_dest_ids': [(3, dest_move.id), (4, middle_move.id)],
})
middle_move._action_confirm()
middle_move._action_confirm(merge=False)

def _prepare_middle_move_values(self, destination):
return {
'picking_id': False,
'location_id': self.location_dest_id.id,
'location_id': self.location_id.id,
'location_dest_id': destination.id,
'state': 'waiting',
'picking_type_id': self.picking_id.picking_type_id.id,
Expand Down
279 changes: 231 additions & 48 deletions stock_picking_zone/tests/test_picking_zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,33 @@ def setUpClass(cls):
'name': 'Highbay',
'location_id': cls.wh.lot_stock_id.id,
})
cls.location_shelf_1 = cls.env['stock.location'].create({
'name': 'Shelf 1',
'location_id': cls.wh.lot_stock_id.id,
})
cls.location_hb_1 = cls.env['stock.location'].create({
'name': 'Highbay Shelve 1',
'name': 'Highbay Shelf 1',
'location_id': cls.location_hb.id,
})
cls.location_hb_1_1 = cls.env['stock.location'].create({
'name': 'Highbay Shelve 1 Bin 1',
'name': 'Highbay Shelf 1 Bin 1',
'location_id': cls.location_hb_1.id,
})
cls.location_hb_1_2 = cls.env['stock.location'].create({
'name': 'Highbay Shelve 1 Bin 2',
'name': 'Highbay Shelf 1 Bin 2',
'location_id': cls.location_hb_1.id,
})

cls.location_handover = cls.env['stock.location'].create({
'name': 'Handover',
'location_id': cls.wh.view_location_id.id,
'location_id': cls.wh.lot_stock_id.id,
})

cls.product_a = cls.env['product.product'].create({
'name': 'Product A', 'type': 'product',
cls.product1 = cls.env['product.product'].create({
'name': 'Product 1', 'type': 'product',
})
cls.product2 = cls.env['product.product'].create({
'name': 'Product 2', 'type': 'product',
})

picking_type_sequence = cls.env['ir.sequence'].create({
Expand All @@ -60,24 +67,18 @@ def setUpClass(cls):
'sequence_id': picking_type_sequence.id,
})

def _create_pick_ship(self, wh):
def _create_pick_ship(self, wh, products=[]):
"""Create pick+ship pickings
Products must be a list of tuples (product, quantity).
One stock move will be create for each tuple.
"""
customer_picking = self.env['stock.picking'].create({
'location_id': wh.wh_output_stock_loc_id.id,
'location_dest_id': self.customer_loc.id,
'partner_id': self.partner_delta.id,
'picking_type_id': wh.out_type_id.id,
})
dest = self.env['stock.move'].create({
'name': self.product_a.name,
'product_id': self.product_a.id,
'product_uom_qty': 10,
'product_uom': self.product_a.uom_id.id,
'picking_id': customer_picking.id,
'location_id': wh.wh_output_stock_loc_id.id,
'location_dest_id': self.customer_loc.id,
'state': 'waiting',
'procure_method': 'make_to_order',
})

pick_picking = self.env['stock.picking'].create({
'location_id': wh.lot_stock_id.id,
Expand All @@ -86,27 +87,72 @@ def _create_pick_ship(self, wh):
'picking_type_id': wh.pick_type_id.id,
})

self.env['stock.move'].create({
'name': self.product_a.name,
'product_id': self.product_a.id,
'product_uom_qty': 10,
'product_uom': self.product_a.uom_id.id,
'picking_id': pick_picking.id,
'location_id': wh.lot_stock_id.id,
'location_dest_id': wh.wh_output_stock_loc_id.id,
'move_dest_ids': [(4, dest.id)],
'state': 'confirmed',
})
for product, qty in products:
dest = self.env['stock.move'].create({
'name': product.name,
'product_id': product.id,
'product_uom_qty': qty,
'product_uom': product.uom_id.id,
'picking_id': customer_picking.id,
'location_id': wh.wh_output_stock_loc_id.id,
'location_dest_id': self.customer_loc.id,
'state': 'waiting',
'procure_method': 'make_to_order',
})

self.env['stock.move'].create({
'name': product.name,
'product_id': product.id,
'product_uom_qty': qty,
'product_uom': product.uom_id.id,
'picking_id': pick_picking.id,
'location_id': wh.lot_stock_id.id,
'location_dest_id': wh.wh_output_stock_loc_id.id,
'move_dest_ids': [(4, dest.id)],
'state': 'confirmed',
})
return pick_picking, customer_picking

def _update_product_qty_in_location(self, location, product, quantity):
self.env['stock.quant']._update_available_quantity(
product, location, quantity
)

def test_change_location_to_zone(self):
def assert_src_stock(self, record):
self.assertEqual(record.location_id, self.wh.lot_stock_id)

def assert_src_handover(self, record):
self.assertEqual(record.location_id, self.location_handover)

pick_picking, customer_picking = self._create_pick_ship(self.wh)
def assert_dest_handover(self, record):
self.assertEqual(record.location_dest_id, self.location_handover)

def assert_src_shelf1(self, record):
self.assertEqual(record.location_id, self.location_shelf_1)

def assert_dest_shelf1(self, record):
self.assertEqual(record.location_dest_id, self.location_shelf_1)

def assert_src_highbay_1_2(self, record):
self.assertEqual(record.location_id, self.location_hb_1_2)

def assert_dest_highbay_1_2(self, record):
self.assertEqual(record.location_destid, self.location_hb_1_2)

def assert_src_output(self, record):
self.assertEqual(record.location_id, self.wh.wh_output_stock_loc_id)

def assert_dest_output(self, record):
self.assertEqual(record.location_dest_id,
self.wh.wh_output_stock_loc_id)

def assert_dest_customer(self, record):
self.assertEqual(record.location_dest_id, self.customer_loc)

def test_change_location_to_zone(self):
pick_picking, customer_picking = self._create_pick_ship(
self.wh, [(self.product1, 10)]
)
move_a = pick_picking.move_lines
move_b = customer_picking.move_lines

Expand All @@ -117,30 +163,167 @@ def test_change_location_to_zone(self):

ml = move_a.move_line_ids
self.assertEqual(len(ml), 1)
self.assertEqual(ml.location_id, self.location_hb_1_2)
self.assertEqual(ml.location_dest_id, self.location_handover)
self.assert_src_highbay_1_2(ml)
self.assert_dest_handover(ml)

self.assertEqual(ml.picking_id.picking_type_id, self.pick_type_zone)

self.assertEqual(move_a.location_id, self.wh.lot_stock_id)
self.assertEqual(move_a.location_dest_id, self.location_handover)
# the move stays B stays on the same source location (sticky)
self.assertEqual(move_b.location_id, self.wh.wh_output_stock_loc_id)
self.assertEqual(move_b.location_dest_id, self.customer_loc)
self.assert_src_stock(move_a)
self.assert_dest_handover(move_a)
# the move stays B stays on the same source location
self.assert_src_output(move_b)
self.assert_dest_customer(move_b)

move_middle = move_a.move_dest_ids
self.assertEqual(move_middle.location_id, move_a.location_dest_id)
self.assertEqual(move_middle.location_dest_id, move_b.location_id)
# the middle move stays in the same source location than the original
# move: the move line will be in the sub-locations (handover)

self.assertEqual(
move_a.picking_id.location_dest_id,
self.location_handover
)
self.assertEqual(
move_middle.picking_id.location_id,
self.location_handover
)
self.assert_src_stock(move_middle)
# Output
self.assert_dest_output(move_middle)

self.assert_src_stock(move_a.picking_id)
self.assert_dest_handover(move_a.picking_id)

self.assertEqual(move_a.state, 'assigned')
self.assertEqual(move_middle.state, 'waiting')
self.assertEqual(move_b.state, 'waiting')

# we deliver move A to check that our middle move line properly takes
# goods from the handover
move_a.move_line_ids.qty_done = move_a.move_line_ids.product_uom_qty
move_a._action_done()
self.assertEqual(move_a.state, 'done')
self.assertEqual(move_middle.state, 'assigned')
self.assertEqual(move_b.state, 'waiting')

move_line_middle = move_middle.move_line_ids
self.assertEqual(len(move_line_middle), 1)
self.assert_src_handover(move_line_middle)
self.assert_dest_output(move_line_middle)

def test_several_move_lines(self):
pick_picking, customer_picking = self._create_pick_ship(
self.wh, [(self.product1, 10), (self.product2, 10)]
)
product1 = self.product1
product2 = self.product2
# in Highbay → should generate a new operation in Highbay picking type
self._update_product_qty_in_location(
self.location_hb_1_2, self.product1, 20
)
# another product in a shelf, no additional operation for this one
self._update_product_qty_in_location(
self.location_shelf_1, self.product2, 20
)
pick_moves = pick_picking.move_lines
move_a_p1 = pick_moves.filtered(lambda r: r.product_id == product1)
move_a_p2 = pick_moves.filtered(lambda r: r.product_id == product2)
cust_moves = customer_picking.move_lines
move_b_p1 = cust_moves.filtered(lambda r: r.product_id == product1)
move_b_p2 = cust_moves.filtered(lambda r: r.product_id == product2)

pick_picking.action_assign()

# At this point, we should have 3 stock.picking:
#
# +-------------------------------------------------------------------+
# | HO/xxxx Assigned |
# | Stock → Stock/Handover |
# | Product1 Highbay/Bay1/Bin1 → Stock/Handover (available) move_a_p1 |
# +-------------------------------------------------------------------+
#
# +------------------------------------------------------------------+
# | PICK/xxxx Waiting |
# | Stock → Output |
# | Product1 Stock/Handover → Output (waiting) move_middle (added) |
# | Product2 Stock/Shelf1 → Output (available) move_a_p2 |
# +------------------------------------------------------------------+
#
# +------------------------------------------------+
# | OUT/xxxx Waiting |
# | Output → Customer |
# | Product1 Output → Customer (waiting) move_b_p1 |
# | Product2 Output → Customer (waiting) move_b_p2 |
# +------------------------------------------------+

move_middle = move_a_p1.move_dest_ids
self.assertEqual(len(move_middle), 1)

self.assertFalse(move_a_p1.move_orig_ids)
self.assertEqual(move_middle.move_dest_ids, move_b_p1)
self.assertFalse(move_a_p2.move_orig_ids)
self.assertEqual(move_a_p2.move_dest_ids, move_b_p2)

ml = move_a_p1.move_line_ids
self.assertEqual(len(ml), 1)
self.assert_src_highbay_1_2(ml)
self.assert_dest_handover(ml)
# this is a new HO picking
self.assertEqual(ml.picking_id.picking_type_id, self.pick_type_zone)
self.assertEqual(ml.state, 'assigned')

# this one stays in the PICK/
ml = move_a_p2.move_line_ids
self.assertEqual(len(ml), 1)
self.assert_src_shelf1(ml)
self.assert_dest_output(ml)
self.assertEqual(ml.picking_id.picking_type_id, self.wh.pick_type_id)
self.assertEqual(ml.state, 'assigned')

# the move stays B stays on the same source location
self.assert_src_output(move_b_p1)
self.assert_dest_customer(move_b_p1)
self.assertEqual(move_b_p1.state, 'waiting')
self.assert_src_output(move_b_p2)
self.assert_dest_customer(move_b_p2)
self.assertEqual(move_b_p2.state, 'waiting')

# Check middle move
# Stock
self.assert_src_stock(move_middle)
# Output
self.assert_dest_output(move_middle)
self.assert_src_stock(move_middle.picking_id)
# we deliver move A to check that our middle move line properly takes
# goods from the handover
qty = move_a_p1.move_line_ids.product_uom_qty
move_a_p1.move_line_ids.qty_done = qty
move_a_p1.picking_id.action_done()

self.assertEqual(move_a_p1.state, 'done')
self.assertEqual(move_a_p2.state, 'assigned')
self.assertEqual(move_middle.state, 'assigned')
self.assertEqual(move_b_p1.state, 'waiting')
self.assertEqual(move_b_p2.state, 'waiting')

move_line_middle = move_middle.move_line_ids
self.assertEqual(len(move_line_middle), 1)
# Handover
self.assert_src_handover(move_line_middle)
# Output
self.assert_dest_output(move_line_middle)

qty = move_middle.move_line_ids.product_uom_qty
move_middle.move_line_ids.qty_done = qty
qty = move_a_p2.move_line_ids.product_uom_qty
move_a_p2.move_line_ids.qty_done = qty
pick_picking.action_done()

self.assertEqual(move_a_p1.state, 'done')
self.assertEqual(move_a_p2.state, 'done')
self.assertEqual(move_middle.state, 'done')
self.assertEqual(move_b_p1.state, 'assigned')
self.assertEqual(move_b_p2.state, 'assigned')

qty = move_b_p1.move_line_ids.product_uom_qty
move_b_p1.move_line_ids.qty_done = qty
qty = move_b_p2.move_line_ids.product_uom_qty
move_b_p2.move_line_ids.qty_done = qty
customer_picking.action_done()

self.assertEqual(move_a_p1.state, 'done')
self.assertEqual(move_a_p2.state, 'done')
self.assertEqual(move_middle.state, 'done')
self.assertEqual(move_b_p1.state, 'done')
self.assertEqual(move_b_p2.state, 'done')

0 comments on commit a7dc125

Please sign in to comment.