diff options
| author | Simon Lejeune <sle@openerp.com> | 2018-07-09 15:34:08 +0200 |
|---|---|---|
| committer | len-odoo <35492570+len-odoo@users.noreply.github.com> | 2018-08-09 08:38:17 +0200 |
| commit | 252bc396b445d1635e8dac1f3cfa1dd5de8cc36e (patch) | |
| tree | d6b850822e6cb4503b09cc3890b11e50db3dcb99 | |
| parent | d92f17cebe048190679f7f86456d93aa98c0cb2a (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.py | 73 | ||||
| -rw-r--r-- | addons/stock/models/stock_picking.py | 7 |
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 |
