Skip to content

Commit

Permalink
new method to validate moves in a separate transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
sebalix committed Sep 16, 2020
1 parent 1ce4f60 commit 4aafbf2
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 21 deletions.
41 changes: 40 additions & 1 deletion shopfloor/models/stock_move.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from odoo import models
from odoo import _, models


class StockMove(models.Model):
Expand Down Expand Up @@ -36,3 +36,42 @@ def _action_done(self, cancel_backorder=False):
if picking.state == "done":
picking.action_done()
return moves

def extract_and_action_done(self):
"""Extract the moves in a separate transfer and validate them.
You can combine this method with `split_other_move_lines` method
to first extract some move lines in a separate move, then validate it
with this method.
"""
moves = self.filtered(lambda m: m.state == "assigned")
if not moves:
return False
for picking in moves.picking_id:
moves_todo = picking.move_lines & moves
if moves_todo == picking.move_lines:
# No need to create a new transfer if we are processing all moves
new_picking = picking
else:
new_picking = picking.copy(
{
"name": "/",
"move_lines": [],
"move_line_ids": [],
"backorder_id": picking.id,
}
)
new_picking.message_post(
body=_(
"Created from backorder "
"<a href=# data-oe-model=stock.picking data-oe-id=%d>%s</a>."
)
% (picking.id, picking.name)
)
moves_todo.write({"picking_id": new_picking.id})
moves_todo.mapped("package_level_id").write({"picking_id": new_picking.id})
moves_todo.mapped("move_line_ids").write({"picking_id": new_picking.id})
new_picking.action_assign()
assert new_picking.state == "assigned"
new_picking.action_done()
return True
112 changes: 92 additions & 20 deletions shopfloor/tests/test_stock_split.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def setUpClass(cls):
cls.pack_location = cls.warehouse.wh_pack_stock_loc_id
cls.ship_location = cls.warehouse.wh_output_stock_loc_id
cls.stock_location = cls.env.ref("stock.stock_location_stock")
# Create a product
# Create products
cls.product_a = (
cls.env["product.product"]
.sudo()
Expand All @@ -39,6 +39,30 @@ def setUpClass(cls):
}
)
)
cls.product_b = (
cls.env["product.product"]
.sudo()
.create(
{
"name": "Product B",
"type": "product",
"default_code": "B",
"barcode": "B",
"weight": 2,
}
)
)
cls.product_b_packaging = (
cls.env["product.packaging"]
.sudo()
.create(
{
"name": "Box",
"product_id": cls.product_b.id,
"barcode": "ProductBBox",
}
)
)
# Put product_a quantities in different packages to get several move lines
cls.package_1 = cls.env["stock.quant.package"].create({"name": "PACKAGE_1"})
cls.package_2 = cls.env["stock.quant.package"].create({"name": "PACKAGE_2"})
Expand All @@ -53,6 +77,8 @@ def setUpClass(cls):
cls._update_qty_in_location(
cls.stock_location, cls.product_a, 5, package=cls.package_3
)
# Put product_b quantities in stock
cls._update_qty_in_location(cls.stock_location, cls.product_b, 10)
# Create the pick/pack/ship transfer
cls.ship_move_a = cls.env["stock.move"].create(
{
Expand All @@ -68,12 +94,28 @@ def setUpClass(cls):
"state": "draft",
}
)
cls.ship_move_a._assign_picking()
cls.ship_move_a._action_confirm(merge=False)
cls.pack_move = cls.ship_move_a.move_orig_ids[0]
cls.pick_move = cls.pack_move.move_orig_ids[0]
cls.picking = cls.pick_move.picking_id
cls.packing = cls.pack_move.picking_id
cls.ship_move_b = cls.env["stock.move"].create(
{
"name": cls.product_b.display_name,
"product_id": cls.product_b.id,
"product_uom_qty": 4,
"product_uom": cls.product_b.uom_id.id,
"location_id": cls.ship_location.id,
"location_dest_id": cls.customer_location.id,
"warehouse_id": cls.warehouse.id,
"picking_type_id": cls.warehouse.out_type_id.id,
"procure_method": "make_to_order",
"state": "draft",
}
)
(cls.ship_move_a | cls.ship_move_b)._assign_picking()
(cls.ship_move_a | cls.ship_move_b)._action_confirm(merge=False)
cls.pack_move_a = cls.ship_move_a.move_orig_ids[0]
cls.pick_move_a = cls.pack_move_a.move_orig_ids[0]
cls.pack_move_b = cls.ship_move_b.move_orig_ids[0]
cls.pick_move_b = cls.pack_move_b.move_orig_ids[0]
cls.picking = cls.pick_move_a.picking_id
cls.packing = cls.pack_move_a.picking_id
cls.picking.action_assign()

@classmethod
Expand All @@ -90,27 +132,27 @@ def _update_qty_in_location(
)

def test_split_pickings_from_source_location(self):
dest_location = self.pick_move.location_dest_id.sudo().copy(
dest_location = self.pick_move_a.location_dest_id.sudo().copy(
{
"name": self.pick_move.location_dest_id.name + "_2",
"barcode": self.pick_move.location_dest_id.barcode + "_2",
"location_id": self.pick_move.location_dest_id.id,
"name": self.pick_move_a.location_dest_id.name + "_2",
"barcode": self.pick_move_a.location_dest_id.barcode + "_2",
"location_id": self.pick_move_a.location_dest_id.id,
}
)
# Pick goods from stock and move some of them to a different destination
self.assertEqual(self.pick_move.state, "assigned")
for i, move_line in enumerate(self.pick_move.move_line_ids):
self.assertEqual(self.pick_move_a.state, "assigned")
for i, move_line in enumerate(self.pick_move_a.move_line_ids):
move_line.qty_done = move_line.product_uom_qty
if i % 2:
move_line.location_dest_id = dest_location
self.pick_move.with_context(_sf_no_backorder=True)._action_done()
self.assertEqual(self.pick_move.state, "done")
self.pick_move_a.with_context(_sf_no_backorder=True)._action_done()
self.assertEqual(self.pick_move_a.state, "done")
# Pack step, we want to split move lines from common source location
self.assertEqual(self.pack_move.state, "assigned")
move_lines_to_process = self.pack_move.move_line_ids.filtered(
self.assertEqual(self.pack_move_a.state, "assigned")
move_lines_to_process = self.pack_move_a.move_line_ids.filtered(
lambda ml: ml.location_id == dest_location
)
self.assertEqual(len(self.pack_move.move_line_ids), 3)
self.assertEqual(len(self.pack_move_a.move_line_ids), 3)
self.assertEqual(len(self.packing.package_level_ids), 3)
self.assertEqual(len(move_lines_to_process), 1)
new_packing = move_lines_to_process._split_pickings_from_source_location()
Expand All @@ -120,9 +162,39 @@ def test_split_pickings_from_source_location(self):
self.assertTrue(new_packing != self.packing)
self.assertEqual(new_packing.backorder_id, self.packing)
self.assertEqual(
self.pick_move.move_dest_ids.picking_id, self.packing | new_packing
self.pick_move_a.move_dest_ids.picking_id, self.packing | new_packing
)
self.assertEqual(move_lines_to_process.state, "assigned")
self.assertEqual(
set(self.pack_move.move_line_ids.mapped("state")), {"assigned"}
set(self.pack_move_a.move_line_ids.mapped("state")), {"assigned"}
)

def test_extract_and_action_done_one_move(self):
self.assertFalse(self.picking.backorder_ids)
self.assertEqual(self.picking.state, "assigned")
for move_line in self.pick_move_b.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
self.pick_move_b.extract_and_action_done()
new_picking = self.picking.backorder_ids
self.assertTrue(new_picking)
# Check move lines repartition
self.assertNotIn(self.pick_move_b, self.picking.move_lines)
self.assertEqual(new_picking.move_lines, self.pick_move_b)
# Check states
self.assertEqual(self.picking.state, "assigned")
self.assertEqual(self.pick_move_b.state, "done")
self.assertEqual(new_picking.state, "done")

def test_extract_and_action_done_several_moves(self):
self.assertFalse(self.picking.backorder_ids)
self.assertEqual(self.picking.state, "assigned")
for move_line in self.picking.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
self.picking.move_lines.extract_and_action_done()
# No backorder as all moves of the picking have been validated
new_picking = self.picking.backorder_ids
self.assertFalse(new_picking)
# Check move lines repartition
self.assertEqual(len(self.picking.move_lines), 2)
# Check states
self.assertEqual(self.picking.state, "done")

0 comments on commit 4aafbf2

Please sign in to comment.