From 0a1aaba3c8d9ba4f99b19d936cb2cbcb44477cf5 Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Mon, 28 Aug 2017 19:41:10 -0700 Subject: [PATCH] [IMP] mrp: suggest correct serial number in next work order When producing multiple products tracked by serial number only the serial number was only set for the first one in every work order. This makes it so that when you create SN1, SN2 and SN3 in the first work order they show up as default in the following work orders. --- addons/mrp/models/__init__.py | 1 + addons/mrp/models/mrp_workorder.py | 14 ++++-- addons/mrp/models/stock_production_lot.py | 11 ++++ addons/mrp/tests/test_workorder_operation.py | 53 ++++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 addons/mrp/models/stock_production_lot.py diff --git a/addons/mrp/models/__init__.py b/addons/mrp/models/__init__.py index 7b3b3958084..295d045c1e8 100644 --- a/addons/mrp/models/__init__.py +++ b/addons/mrp/models/__init__.py @@ -16,5 +16,6 @@ from . import product from . import res_company from . import stock_move from . import stock_picking +from . import stock_production_lot from . import stock_scrap from . import stock_warehouse diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index 723f4c8f75a..4e8244da860 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -271,6 +271,10 @@ class MrpWorkorder(models.Model): 'location_dest_id': move.location_dest_id.id, }) + def _assign_default_final_lot_id(self): + self.final_lot_id = self.env['stock.production.lot'].search([('use_next_on_work_order_id', '=', self.id)], + order='create_date', limit=1) + @api.multi def record_production(self): self.ensure_one() @@ -308,8 +312,6 @@ class MrpWorkorder(models.Model): # One a piece is produced, you can launch the next work order if self.next_work_order_id.state == 'pending': self.next_work_order_id.state = 'ready' - if self.next_work_order_id and self.final_lot_id and not self.next_work_order_id.final_lot_id: - self.next_work_order_id.final_lot_id = self.final_lot_id.id self.move_line_ids.filtered( lambda move_line: not move_line.done_move and not move_line.lot_produced_id and move_line.qty_done > 0 @@ -342,18 +344,24 @@ class MrpWorkorder(models.Model): # Update workorder quantity produced self.qty_produced += self.qty_producing + if self.final_lot_id: + self.final_lot_id.use_next_on_work_order_id = self.next_work_order_id + self.final_lot_id = False + # Set a qty producing if self.qty_produced >= self.production_id.product_qty: self.qty_producing = 0 elif self.production_id.product_id.tracking == 'serial': + self._assign_default_final_lot_id() self.qty_producing = 1.0 self._generate_lot_ids() else: self.qty_producing = self.production_id.product_qty - self.qty_produced self._generate_lot_ids() - self.final_lot_id = False if self.qty_produced >= self.production_id.product_qty: + if self.next_work_order_id and self.production_id.product_id.tracking != 'none': + self.next_work_order_id._assign_default_final_lot_id() self.button_finish() return True diff --git a/addons/mrp/models/stock_production_lot.py b/addons/mrp/models/stock_production_lot.py new file mode 100644 index 00000000000..9c2470c64ef --- /dev/null +++ b/addons/mrp/models/stock_production_lot.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, exceptions, fields, models, _ + + +class StockProductionLot(models.Model): + _inherit = 'stock.production.lot' + + use_next_on_work_order_id = fields.Many2one('mrp.workorder', + help='Technical: used to figure out default serial number on work orders') diff --git a/addons/mrp/tests/test_workorder_operation.py b/addons/mrp/tests/test_workorder_operation.py index 15adcd236c8..bbbd8efd08d 100644 --- a/addons/mrp/tests/test_workorder_operation.py +++ b/addons/mrp/tests/test_workorder_operation.py @@ -408,3 +408,56 @@ class TestWorkOrderProcess(common.TransactionCase): # self.assertEqual(move_product_b.quant_ids.qty, move_product_b.product_qty) # self.assertEqual(move_product_c.quant_ids.qty, 3) # self.assertEqual(move_product_c.quant_ids.product_uom_id.id, kg) + + def test_03_test_serial_number_defaults(self): + """ Test that the correct serial number is suggested on consecutive work orders. """ + laptop = self.env.ref("product.product_product_25") + graphics_card = self.env.ref("product.product_product_24") + unit = self.env.ref("product.product_uom_unit") + three_step_routing = self.env.ref("mrp.mrp_routing_1") + + laptop.tracking = 'serial' + + bom_laptop = self.env['mrp.bom'].create({ + 'product_tmpl_id': laptop.product_tmpl_id.id, + 'product_qty': 1, + 'product_uom_id': unit.id, + 'bom_line_ids': [(0, 0, { + 'product_id': graphics_card.id, + 'product_qty': 1, + 'product_uom_id': unit.id + })], + 'routing_id': three_step_routing.id + }) + + mo_laptop = self.env['mrp.production'].create({ + 'product_id': laptop.id, + 'product_qty': 3, + 'product_uom_id': unit.id, + 'bom_id': bom_laptop.id + }) + + mo_laptop.button_plan() + workorders = mo_laptop.workorder_ids + self.assertEqual(len(workorders), 3) + + workorders[0].button_start() + serial_a = self.env['stock.production.lot'].create({'product_id': laptop.id}) + workorders[0].final_lot_id = serial_a + workorders[0].record_production() + serial_b = self.env['stock.production.lot'].create({'product_id': laptop.id}) + workorders[0].final_lot_id = serial_b + workorders[0].record_production() + serial_c = self.env['stock.production.lot'].create({'product_id': laptop.id}) + workorders[0].final_lot_id = serial_c + workorders[0].record_production() + self.assertEqual(workorders[0].state, 'done') + + for workorder in workorders - workorders[0]: + self.assertEqual(workorder.final_lot_id, serial_a) + workorder.record_production() + self.assertEqual(workorder.final_lot_id, serial_b) + workorder.record_production() + self.assertEqual(workorder.final_lot_id, serial_c) + workorder.record_production() + self.assertEqual(workorder.state, 'done')