From 6a093d1dec4333fd0970dade8e5acab5361e2487 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Sat, 30 Sep 2017 11:47:14 +0200 Subject: [PATCH] [REF] stock: when editing the initial demand of a receipt, run action assign We also display the "check availability" button if the move is ready but one of the move is partially available. --- addons/stock/models/stock_move.py | 6 +++ addons/stock/models/stock_picking.py | 5 +-- addons/stock/tests/test_move.py | 62 ++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 2ca5daad983..97c29b45aac 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -363,6 +363,7 @@ class StockMove(models.Model): def write(self, vals): # FIXME: pim fix your crap + receipt_moves_to_reassign = self.env['stock.move'] if 'product_uom_qty' in vals: for move in self.filtered(lambda m: m.state not in ('done', 'draft') and m.picking_id): if vals['product_uom_qty'] != move.product_uom_qty: @@ -371,6 +372,9 @@ class StockMove(models.Model): move_to_unreserve = self.filtered(lambda m: m.state not in ['draft', 'done', 'cancel'] and m.reserved_availability > vals.get('product_uom_qty')) move_to_unreserve._do_unreserve() (self - move_to_unreserve).filtered(lambda m: m.state == 'assigned').write({'state': 'partially_available'}) + # When editing the initial demand, directly run again action assign on receipt moves. + receipt_moves_to_reassign |= move_to_unreserve.filtered(lambda m: m.location_id.usage == 'supplier') + receipt_moves_to_reassign |= (self - move_to_unreserve).filtered(lambda m: m.location_id.usage == 'supplier' and m.state in ('partially_available', 'assigned')) # TDE CLEANME: it is a gros bordel + tracking Picking = self.env['stock.picking'] @@ -414,6 +418,8 @@ class StockMove(models.Model): res = super(StockMove, self).write(vals) if track_pickings: pickings.message_track(pickings.fields_get(['state']), initial_values) + if receipt_moves_to_reassign: + receipt_moves_to_reassign._action_assign() return res def action_show_details(self): diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index b6e61c05f49..bc543eecc6f 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -394,7 +394,7 @@ class Picking(models.Model): float_compare(move.product_uom_qty, 0, precision_rounding=move.product_uom.rounding) for move in picking.move_lines ) - picking.show_check_availability = picking.is_locked and picking.state in ('confirmed', 'waiting') and has_moves_to_reserve + picking.show_check_availability = picking.is_locked and picking.state in ('confirmed', 'waiting', 'assigned') and has_moves_to_reserve @api.multi @api.depends('state', 'move_lines') @@ -514,8 +514,7 @@ class Picking(models.Model): .filtered(lambda move: move.state == 'draft')\ ._action_confirm() # call `_action_assign` on every confirmed move which location_id bypasses the reservation - self.filtered(lambda picking: picking.location_id.usage in ('supplier', 'inventory', 'production'))\ - .filtered(lambda move: move.state == 'confirmed')\ + self.filtered(lambda picking: picking.location_id.usage in ('supplier', 'inventory', 'production') and picking.state == 'confirmed')\ .mapped('move_lines')._action_assign() return True diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index a83a6c87c41..3b899a0d290 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -2904,9 +2904,7 @@ class StockMove(TransactionCase): move1._action_confirm() move1._action_assign() move1.product_uom_qty = 15 - self.assertEqual(move1.state, 'partially_available') - - move1._action_assign() + # _action_assign is automatically called self.assertEqual(move1.state, 'assigned') self.assertEqual(move1.product_uom_qty, 15) self.assertEqual(len(move1.move_line_ids), 1) @@ -2927,15 +2925,63 @@ class StockMove(TransactionCase): }) move1._action_confirm() move1._action_assign() - move1.product_uom_qty = 5 - self.assertEqual(move1.state, 'confirmed') - self.assertEqual(len(move1.move_line_ids), 0) - - move1._action_assign() + self.assertEqual(move1.state, 'assigned') + move1.with_context(debug=True).product_uom_qty = 5 self.assertEqual(move1.state, 'assigned') self.assertEqual(move1.product_uom_qty, 5) self.assertEqual(len(move1.move_line_ids), 1) + def test_initial_demand_3(self): + """ Increase the initial demand on a receipt picking, the system should automatically + reserve the new quantity. + """ + picking = self.env['stock.picking'].create({ + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'picking_type_id': self.env.ref('stock.picking_type_in').id, + }) + move1 = self.env['stock.move'].create({ + 'name': 'test_transit_1', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 10.0, + 'picking_id': picking.id, + }) + picking._autoconfirm_picking() + self.assertEqual(picking.state, 'assigned') + move1.product_uom_qty = 12 + self.assertEqual(picking.state, 'assigned') + + def test_initial_demand_4(self): + """ Increase the initial demand on a delivery picking, the system should not automatically + reserve the new quantity. + """ + self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 12) + picking = self.env['stock.picking'].create({ + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'picking_type_id': self.env.ref('stock.picking_type_in').id, + }) + move1 = self.env['stock.move'].create({ + 'name': 'test_transit_1', + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 10.0, + 'picking_id': picking.id, + }) + picking.action_confirm() + picking.action_assign() + self.assertEqual(picking.state, 'assigned') + move1.product_uom_qty = 12 + self.assertEqual(picking.state, 'assigned') # actually, partially available + self.assertEqual(move1.state, 'partially_available') + picking.action_assign() + self.assertEqual(move1.state, 'assigned') + def test_change_product_type(self): """ Changing type of an existing product will raise a user error if some move are reserved.