summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Lejeune <sle@openerp.com>2018-07-09 15:34:08 +0200
committerlen-odoo <35492570+len-odoo@users.noreply.github.com>2018-08-09 08:38:17 +0200
commit252bc396b445d1635e8dac1f3cfa1dd5de8cc36e (patch)
treed6b850822e6cb4503b09cc3890b11e50db3dcb99
parentd92f17cebe048190679f7f86456d93aa98c0cb2a (diff)
[FIX] stock: button_validate: forced move lines
When a move line is not linked to a move, it'll be linked to the first move of the same product at validation time. We slightly improve this logic by linking it to the first non-completed move. To be completely correct, we should split the move line if necessary and link it to all needed moves, but at this time we don't want to make the logic too complex. Use case: create a sale order with three sale order lines of the same products, use the detailed operations view and add three move lines of the same products, validate the picking. Before the patch, all move lines were linked to the first move and thus only the first sale order line had delivered quantities. Fixes #25488 opw-1861765
-rw-r--r--addons/sale_stock/tests/test_sale_stock.py73
-rw-r--r--addons/stock/models/stock_picking.py7
2 files changed, 77 insertions, 3 deletions
diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py
index c4a32bbf4dc..1081e18f153 100644
--- a/addons/sale_stock/tests/test_sale_stock.py
+++ b/addons/sale_stock/tests/test_sale_stock.py
@@ -421,3 +421,76 @@ class TestSaleStock(TestSale):
# check the delivered quantity
self.assertEqual(so1.order_line.qty_delivered, 3.0)
+ def test_07_forced_qties(self):
+ """ Make multiple sale order lines of the same product which isn't available in stock. On
+ the picking, create new move lines (through the detailed operations view). See that the move
+ lines are correctly dispatched through the moves.
+ """
+ uom_unit = self.env.ref('product.product_uom_unit')
+ uom_dozen = self.env.ref('product.product_uom_dozen')
+ item1 = self.products['prod_order']
+
+ self.assertEqual(item1.uom_id.id, uom_unit.id)
+
+ # sell a dozen
+ so1 = self.env['sale.order'].create({
+ 'partner_id': self.partner.id,
+ 'order_line': [
+ (0, 0, {
+ 'name': item1.name,
+ 'product_id': item1.id,
+ 'product_uom_qty': 1,
+ 'product_uom': uom_dozen.id,
+ 'price_unit': item1.list_price,
+ }),
+ (0, 0, {
+ 'name': item1.name,
+ 'product_id': item1.id,
+ 'product_uom_qty': 1,
+ 'product_uom': uom_dozen.id,
+ 'price_unit': item1.list_price,
+ }),
+ (0, 0, {
+ 'name': item1.name,
+ 'product_id': item1.id,
+ 'product_uom_qty': 1,
+ 'product_uom': uom_dozen.id,
+ 'price_unit': item1.list_price,
+ }),
+ ],
+ })
+ so1.action_confirm()
+
+ self.assertEqual(len(so1.picking_ids.move_lines), 3)
+ so1.picking_ids.write({
+ 'move_line_ids': [
+ (0, 0, {
+ 'product_id': item1.id,
+ 'product_uom_qty': 0,
+ 'qty_done': 1,
+ 'product_uom_id': uom_dozen.id,
+ 'location_id': so1.picking_ids.location_id.id,
+ 'location_dest_id': so1.picking_ids.location_dest_id.id,
+ }),
+ (0, 0, {
+ 'product_id': item1.id,
+ 'product_uom_qty': 0,
+ 'qty_done': 1,
+ 'product_uom_id': uom_dozen.id,
+ 'location_id': so1.picking_ids.location_id.id,
+ 'location_dest_id': so1.picking_ids.location_dest_id.id,
+ }),
+ (0, 0, {
+ 'product_id': item1.id,
+ 'product_uom_qty': 0,
+ 'qty_done': 1,
+ 'product_uom_id': uom_dozen.id,
+ 'location_id': so1.picking_ids.location_id.id,
+ 'location_dest_id': so1.picking_ids.location_dest_id.id,
+ }),
+ ],
+ })
+ so1.picking_ids.button_validate()
+ self.assertEqual(so1.picking_ids.state, 'done')
+ self.assertEqual(so1.order_line.mapped('qty_delivered'), [1, 1, 1])
+
diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py
index 314fee31e06..f99e59b9c9b 100644
--- a/addons/stock/models/stock_picking.py
+++ b/addons/stock/models/stock_picking.py
@@ -631,8 +631,9 @@ class Picking(models.Model):
# # Link existing moves or add moves when no one is related
for ops in pick.move_line_ids.filtered(lambda x: not x.move_id):
# Search move with this product
- moves = pick.move_lines.filtered(lambda x: x.product_id == ops.product_id)
- if moves: #could search move that needs it the most (that has some quantities left)
+ moves = pick.move_lines.filtered(lambda x: x.product_id == ops.product_id)
+ moves = sorted(moves, key=lambda m: m.quantity_done < m.product_qty, reverse=True)
+ if moves:
ops.move_id = moves[0].id
else:
new_move = self.env['stock.move'].create({
@@ -802,7 +803,7 @@ class Picking(models.Model):
quantity_done[quant.product_id.id] += quant.qty
for pack in self.mapped('move_line_ids').filtered(lambda x: x.product_id and not x.move_id):
quantity_done.setdefault(pack.product_id.id, 0)
- quantity_done[pack.product_id.id] += pack.qty_done
+ quantity_done[pack.product_id.id] += pack.product_uom_id._compute_quantity(pack.qty_done, pack.product_id.uom_id)
return any(quantity_done[x] < quantity_todo.get(x, 0) for x in quantity_done)
@api.multi