diff options
| author | Simon Lejeune <sle@openerp.com> | 2019-09-16 15:45:01 +0000 |
|---|---|---|
| committer | Simon Lejeune <sle@openerp.com> | 2019-09-18 07:15:32 +0000 |
| commit | d1814891fe5e89a482476b4cd1a5700cb0b3fed3 (patch) | |
| tree | 68c185ad8417b529df15a4cfa6dbf54409ace21a /addons | |
| parent | deeb17cef0057571986e21f2fd0d88821aaf99bd (diff) | |
[REF] mrp_subcontracting: manage backorder
closes odoo/odoo#37046
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/mrp_subcontracting/models/stock_move.py | 24 | ||||
| -rw-r--r-- | addons/mrp_subcontracting/models/stock_picking.py | 16 | ||||
| -rw-r--r-- | addons/mrp_subcontracting/tests/test_subcontracting.py | 30 |
3 files changed, 59 insertions, 11 deletions
diff --git a/addons/mrp_subcontracting/models/stock_move.py b/addons/mrp_subcontracting/models/stock_move.py index 73b454d22ee..264f8efe1ea 100644 --- a/addons/mrp_subcontracting/models/stock_move.py +++ b/addons/mrp_subcontracting/models/stock_move.py @@ -11,7 +11,7 @@ from odoo.tools.float_utils import float_compare, float_is_zero class StockMove(models.Model): _inherit = 'stock.move' - is_subcontract = fields.Boolean('The move is a subcontract receipt', copy=False) + is_subcontract = fields.Boolean('The move is a subcontract receipt') show_subcontracting_details_visible = fields.Boolean( compute='_compute_show_subcontracting_details_visible' ) @@ -38,12 +38,23 @@ class StockMove(models.Model): move.show_details_visible = True return res + def copy(self, default=None): + self.ensure_one() + if not self.is_subcontract or 'location_id' in default: + return super(StockMove, self).copy(default=default) + if not default: + default = {} + default['location_id'] = self.picking_id.location_id.id + return super(StockMove, self).copy(default=default) + def write(self, values): """ If the initial demand is updated then also update the linked subcontract order to the new quantity. """ res = super(StockMove, self).write(values) if 'product_uom_qty' in values: + if self.env.context.get('cancel_backorder') is False: + return res self.filtered(lambda m: m.is_subcontract and m.state not in ['draft', 'cancel', 'done'])._update_subcontract_order_qty() return res @@ -88,11 +99,14 @@ class StockMove(models.Model): for move in self: if move.location_id.usage != 'supplier' or move.location_dest_id.usage == 'supplier': continue - if not move.picking_id or self.env.context.get('do_not_create_subcontract_order'): + if move.move_orig_ids.production_id: continue bom = move._get_subcontract_bom() if not bom: continue + if float_is_zero(move.product_qty, precision_rounding=move.product_uom.rounding) and\ + move.picking_id.immediate_transfer is True: + raise UserError(_("To subcontract, use a planned transfer.")) subcontract_details_per_picking[move.picking_id].append((move, bom)) move.write({ 'is_subcontract': True, @@ -154,6 +168,11 @@ operations.""") % ('\n'.join(overprocessed_moves.mapped('product_id.display_name self.ensure_one() return any(m.has_tracking != 'none' for m in self.move_orig_ids.production_id.move_raw_ids) + def _prepare_extra_move_vals(self, qty): + vals = super(StockMove, self)._prepare_extra_move_vals(qty) + vals['location_id'] = self.location_id.id + return vals + def _should_bypass_reservation(self): """ If the move is subcontracted then ignore the reservation. """ should_bypass_reservation = super(StockMove, self)._should_bypass_reservation() @@ -169,3 +188,4 @@ operations.""") % ('\n'.join(overprocessed_moves.mapped('product_id.display_name 'mo_id': production.id, 'product_qty': move.product_uom_qty }).change_prod_qty() + diff --git a/addons/mrp_subcontracting/models/stock_picking.py b/addons/mrp_subcontracting/models/stock_picking.py index 7c366b9720c..f638eda03a4 100644 --- a/addons/mrp_subcontracting/models/stock_picking.py +++ b/addons/mrp_subcontracting/models/stock_picking.py @@ -43,12 +43,7 @@ class StockPicking(models.Model): return super(StockPicking, self).action_cancel() def action_done(self): - # action_done with an extra move will trigger two methods that - # create/modify a subcontracting order, _action_confirm and a write on - # product_uom_qty. This context will be used by _action_confirm and it - # will not create a subcontract order. Instead the existing order will - # be updated in the stock.move write during the merge move. - res = super(StockPicking, self.with_context(do_not_create_subcontract_order=True)).action_done() + res = super(StockPicking, self).action_done() productions = self.env['mrp.production'] for picking in self: for move in picking.move_lines: @@ -56,8 +51,8 @@ class StockPicking(models.Model): continue production = move.move_orig_ids.production_id if move._has_tracked_subcontract_components(): - move.move_orig_ids.move_line_ids.unlink() - move_finished_ids = move.move_orig_ids + move.move_orig_ids.filtered(lambda m: m.state not in ('done', 'cancel')).move_line_ids.unlink() + move_finished_ids = move.move_orig_ids.filtered(lambda m: m.state not in ('done', 'cancel')) for ml in move.move_line_ids: ml.copy({ 'picking_id': False, @@ -81,7 +76,10 @@ class StockPicking(models.Model): produce._record_production() productions |= production for subcontracted_production in productions: - subcontracted_production.button_mark_done() + if subcontracted_production.state == 'progress': + subcontracted_production.post_inventory() + else: + subcontracted_production.button_mark_done() # For concistency, set the date on production move before the date # on picking. (Tracability report + Product Moves menu item) minimum_date = min(picking.move_line_ids.mapped('date')) diff --git a/addons/mrp_subcontracting/tests/test_subcontracting.py b/addons/mrp_subcontracting/tests/test_subcontracting.py index 029d9e3a71f..41ffda20acd 100644 --- a/addons/mrp_subcontracting/tests/test_subcontracting.py +++ b/addons/mrp_subcontracting/tests/test_subcontracting.py @@ -510,6 +510,36 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon): self.assertEqual(move_comp1.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).lot_produced_ids.name, 'LOT F2') self.assertEqual(move_comp2.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).lot_produced_ids.name, 'LOT F2') + def test_flow_8(self): + resupply_sub_on_order_route = self.env['stock.location.route'].search([('name', '=', 'Resupply Subcontractor on Order')]) + (self.comp1 + self.comp2).write({'route_ids': [(4, resupply_sub_on_order_route.id, None)]}) + + # Create a receipt picking from the subcontractor + picking_form = Form(self.env['stock.picking']) + picking_form.picking_type_id = self.env.ref('stock.picking_type_in') + picking_form.partner_id = self.subcontractor_partner1 + with picking_form.move_ids_without_package.new() as move: + move.product_id = self.finished + move.product_uom_qty = 5 + picking_receipt = picking_form.save() + picking_receipt.action_confirm() + + picking_receipt.move_lines.quantity_done = 3 + backorder_wiz = picking_receipt.button_validate() + backorder_wiz = self.env['stock.backorder.confirmation'].browse(backorder_wiz['res_id']) + backorder_wiz.process() + + backorder = self.env['stock.picking'].search([('backorder_id', '=', picking_receipt.id)]) + self.assertTrue(backorder) + self.assertEqual(backorder.move_lines.product_uom_qty, 2) + subcontract_order = backorder.move_lines.move_orig_ids.production_id.filtered(lambda p: p.state != 'done') + self.assertTrue(subcontract_order) + self.assertEqual(subcontract_order.product_uom_qty, 5) + self.assertEqual(subcontract_order.qty_produced, 3) + backorder.move_lines.quantity_done = 2 + backorder.action_done() + self.assertTrue(picking_receipt.move_lines.move_orig_ids.production_id.state == 'done') + class TestSubcontractingTracking(TransactionCase): def setUp(self): super(TestSubcontractingTracking, self).setUp() |
