diff --git a/mrp_operations_extension/__init__.py b/mrp_operations_extension/__init__.py index 3543e95f4..ecfcca241 100644 --- a/mrp_operations_extension/__init__.py +++ b/mrp_operations_extension/__init__.py @@ -1,11 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution -# Copyright (C) 2008-2014 AvanzOSC (Daniel). All Rights Reserved -# Date: 10/07/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -22,3 +17,4 @@ ############################################################################## from . import models +from . import wizard diff --git a/mrp_operations_extension/__openerp__.py b/mrp_operations_extension/__openerp__.py index 67c4d8ce7..23e882640 100644 --- a/mrp_operations_extension/__openerp__.py +++ b/mrp_operations_extension/__openerp__.py @@ -2,10 +2,6 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution -# Copyright (C) 2008-2014 AvanzOSC (Daniel). All Rights Reserved -# Date: 10/07/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -25,29 +21,45 @@ "name": "MRP Operations Extension", "version": "1.0", "description": """ - This module adds: +This module adds: - New table to store operations to avoid typing them again. - Adds a relation from WorkcenterLines to BOM Lists. - Adds a relation from WorkcenterLines to Manufacturing Orders in Scheduled/Consumed/Finished Products. - - - Add a relation between Routing Work Center Lines and Work Center extra + - Adds a relation between Routing Work Center Lines and Work Center extra Info. """, - 'author': 'OdooMRP team', - 'website': "http://www.odoomrp.com", - "depends": ['mrp_operations', 'mrp'], "category": "Manufacturing", + "data": ['wizard/mrp_workorder_produce_view.xml', + 'views/mrp_workcenter_view.xml', + 'views/mrp_routing_operation_view.xml', + 'views/mrp_production_view.xml', + 'views/mrp_bom_view.xml', + 'views/mrp_routing_workcenter_view.xml', + 'security/ir.model.access.csv' + ], + "author": "OdooMRP team", + "website": "http://www.odoomrp.com", + "contributors": [ + "Daniel Campos ", + "Mikel Arregi ", + "Oihane Crucelaegui ", + ], + "depends": [ + "mrp_operations", + "mrp", + "stock", + ], "data": [ - 'views/mrp_workcenter_view.xml', - 'views/mrp_routing_operation_view.xml', - 'views/mrp_production_view.xml', - 'views/mrp_bom_view.xml', - 'views/mrp_workcenter_view.xml', - 'views/mrp_routing_workcenter_view.xml', - 'security/ir.model.access.csv', + "wizard/mrp_workorder_produce_view.xml", + "views/mrp_workcenter_view.xml", + "views/mrp_routing_operation_view.xml", + "views/mrp_production_view.xml", + "views/mrp_bom_view.xml", + "views/mrp_routing_workcenter_view.xml", + "security/ir.model.access.csv", ], "installable": True } diff --git a/mrp_operations_extension/models/__init__.py b/mrp_operations_extension/models/__init__.py index b83c5acde..f8074ae68 100644 --- a/mrp_operations_extension/models/__init__.py +++ b/mrp_operations_extension/models/__init__.py @@ -1,4 +1,3 @@ - # -*- encoding: utf-8 -*- ############################################################################## # @@ -17,9 +16,9 @@ # ############################################################################## -from . import mrp_routing_operation -from . import stock_move from . import mrp_routing_workcenter from . import mrp_production from . import mrp_bom from . import mrp_workcenter +from . import mrp_routing_operation +from . import stock_move diff --git a/mrp_operations_extension/models/mrp_bom.py b/mrp_operations_extension/models/mrp_bom.py index db5ba33fa..ecc52b489 100644 --- a/mrp_operations_extension/models/mrp_bom.py +++ b/mrp_operations_extension/models/mrp_bom.py @@ -1,11 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution -# Copyright (C) 2008-2014 AvanzOSC (Daniel). All Rights Reserved -# Date: 10/07/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -21,39 +16,42 @@ # ############################################################################## -from openerp import models, fields, tools +from openerp import models, fields, tools, api class MrpBom(models.Model): _inherit = 'mrp.bom' - def _bom_explode(self, cr, uid, bom, product, factor, properties=None, - level=0, routing_id=False, previous_products=None, - master_bom=None, context=None): - routing_line_obj = self.pool['mrp.routing.workcenter'] - res = super(MrpBom, self)._bom_explode(cr, uid, bom, product, factor, - properties=None, level=0, - routing_id=False, - previous_products=None, - master_bom=None, - context=context) - result, result2 = res + @api.model + def _bom_explode(self, bom, product, factor, properties=None, level=0, + routing_id=False, previous_products=None, + master_bom=None): + routing_id = bom.routing_id.id or routing_id + result, result2 = super(MrpBom, self)._bom_explode( + bom, product, factor, properties=properties, level=level, + routing_id=routing_id, previous_products=previous_products, + master_bom=master_bom) + result2 = self._get_workorder_operations(result2, level=level, + routing_id=routing_id) + return result, result2 + + def _get_workorder_operations(self, result2, level=0, routing_id=False): + routing_line_obj = self.env['mrp.routing.workcenter'] for work_order in result2: seq = work_order['sequence'] - level - routing_lines = routing_line_obj.search(cr, uid, [ + routing_lines = routing_line_obj.search([ ('routing_id', '=', routing_id), ('sequence', '=', seq)]) routing_line_id = False if len(routing_lines) == 1: - routing_line_id = routing_lines[0] + routing_line_id = routing_lines[0].id elif len(routing_lines) > 1: - for routing_line in routing_line_obj.browse(cr, uid, - routing_lines): + for routing_line in routing_line_obj.browse(routing_lines): name_val = tools.ustr(routing_line.name) + ' - ' if name_val in work_order['name']: routing_line_id = routing_line.id break work_order['routing_wc_line'] = routing_line_id - return result, result2 + return result2 class MrpBomLine(models.Model): diff --git a/mrp_operations_extension/models/mrp_production.py b/mrp_operations_extension/models/mrp_production.py index 5428a345c..f9d9ca5e9 100644 --- a/mrp_operations_extension/models/mrp_production.py +++ b/mrp_operations_extension/models/mrp_production.py @@ -1,9 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# Daniel Campos (danielcampos@avanzosc.es) Date: 28/08/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -19,7 +16,7 @@ # ############################################################################## -from openerp import models, fields, api +from openerp import models, fields, api, exceptions, _ class MrpProduction(models.Model): @@ -29,27 +26,46 @@ class MrpProduction(models.Model): def _action_compute_lines(self, properties=None): res = super(MrpProduction, self)._action_compute_lines(properties=properties) - workcenter_lines = self.workcenter_lines - product_lines = self.product_lines + self._get_workorder_in_product_lines(self.workcenter_lines, + self.product_lines) + return res + + def _get_workorder_in_product_lines(self, workcenter_lines, product_lines): for p_line in product_lines: - mrp_bom = self.env['mrp.bom'].search([ - ('routing_id', '=', self.routing_id.id), - ('product_tmpl_id', '=', self.product_id.product_tmpl_id.id)]) - for bom_line in mrp_bom[0].bom_line_ids: + for bom_line in self.bom_id.bom_line_ids: if bom_line.product_id.id == p_line.product_id.id: for wc_line in workcenter_lines: if wc_line.routing_wc_line.id == bom_line.operation.id: p_line.work_order = wc_line.id break - return res + + def _get_workorder_in_move_lines(self, product_lines, move_lines): + for move_line in move_lines: + for product_line in product_lines: + if product_line.product_id.id == move_line.product_id.id: + move_line.work_order = product_line.work_order.id @api.multi def action_confirm(self): + produce = False + for workcenter_line in self.workcenter_lines: + if workcenter_line.do_production: + produce = True + break + if not produce: + raise exceptions.Warning( + _('Produce Operation'), _('At least one operation ' + 'must have checked ' + '"Move produced quantity to stock"' + 'field')) res = super(MrpProduction, self).action_confirm() - for move_line in self.move_lines: - for product_line in self.product_lines: - if product_line.product_id.id == move_line.product_id.id: - move_line.work_order = product_line.work_order.id + self._get_workorder_in_move_lines(self.product_lines, self.move_lines) + return res + + @api.multi + def action_compute(self, properties=None): + res = super(MrpProduction, self).action_compute(properties=properties) + self._get_workorder_in_move_lines(self.product_lines, self.move_lines) return res @@ -60,10 +76,22 @@ class MrpProductionProductLine(models.Model): 'Work Order') -class mrp_production_workcenter_line(models.Model): +class MrpProductionWorkcenterLine(models.Model): _inherit = 'mrp.production.workcenter.line' product_line = fields.One2many('mrp.production.product.line', 'work_order', string='Product Lines') routing_wc_line = fields.Many2one('mrp.routing.workcenter', string='Routing WC Line') + do_production = fields.Boolean( + string='Move Final Product to Stock') + + @api.model + def create(self, data): + workcenter_obj = self.env['mrp.routing.workcenter'] + if 'routing_wc_line' in data: + routing_wc_line_id = data.get('routing_wc_line') + work = workcenter_obj.browse(routing_wc_line_id) + data.update({'do_production': + work.operation.do_production}) + return super(MrpProductionWorkcenterLine, self).create(data) diff --git a/mrp_operations_extension/models/mrp_routing_operation.py b/mrp_operations_extension/models/mrp_routing_operation.py index 7bc4027b7..5106eebf7 100644 --- a/mrp_operations_extension/models/mrp_routing_operation.py +++ b/mrp_operations_extension/models/mrp_routing_operation.py @@ -1,9 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# Daniel Campos (danielcampos@avanzosc.es) Date: 12/09/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -64,3 +61,7 @@ class MrpRoutingOperation(models.Model): 'mrp.workcenter', 'mrp_operation_workcenter_rel', 'operation', 'workcenter', 'Work centers') op_number = fields.Integer('NĂºmero de Persona', default='0') + do_production = fields.Boolean( + string='Move Final Product to Stock') + picking_type_id = fields.Many2one( + 'stock.picking.type', string='Picking Type') diff --git a/mrp_operations_extension/models/mrp_routing_workcenter.py b/mrp_operations_extension/models/mrp_routing_workcenter.py index 037cfcb83..bfbf08d7e 100644 --- a/mrp_operations_extension/models/mrp_routing_workcenter.py +++ b/mrp_operations_extension/models/mrp_routing_workcenter.py @@ -1,11 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution -# Copyright (C) 2008-2014 AvanzOSC (Daniel). All Rights Reserved -# Date: 10/07/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -16,7 +11,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see http://www.gnu.org/licenses/. # ############################################################################## @@ -31,6 +26,8 @@ class MrpRoutingWorkcenter(models.Model): op_wc_lines = fields.One2many('mrp.operation.workcenter', 'routing_workcenter', 'Workcenter Info Lines') + do_production = fields.Boolean( + string='Move produced quantity to stock') @api.one @api.onchange('operation') diff --git a/mrp_operations_extension/models/mrp_workcenter.py b/mrp_operations_extension/models/mrp_workcenter.py index 4adde98a4..b1eddc7bf 100644 --- a/mrp_operations_extension/models/mrp_workcenter.py +++ b/mrp_operations_extension/models/mrp_workcenter.py @@ -1,11 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution -# Copyright (C) 2008-2014 AvanzOSC (Daniel). All Rights Reserved -# Date: 10/07/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or diff --git a/mrp_operations_extension/models/stock_move.py b/mrp_operations_extension/models/stock_move.py index 42ebe1fec..e1b8f5e71 100644 --- a/mrp_operations_extension/models/stock_move.py +++ b/mrp_operations_extension/models/stock_move.py @@ -1,9 +1,6 @@ - # -*- encoding: utf-8 -*- ############################################################################## # -# Daniel Campos (danielcampos@avanzosc.es) Date: 25/08/2014 -# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or diff --git a/mrp_operations_extension/views/mrp_production_view.xml b/mrp_operations_extension/views/mrp_production_view.xml index ce5a20c13..75821e6d3 100644 --- a/mrp_operations_extension/views/mrp_production_view.xml +++ b/mrp_operations_extension/views/mrp_production_view.xml @@ -72,10 +72,25 @@ expr="//field[@name='workcenter_lines']/form//field[@name='hour']" position="replace"> + + + + + + + + + + Work centre line inh mrp.production.workcenter.line - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mrp_operations_extension/views/mrp_routing_operation_view.xml b/mrp_operations_extension/views/mrp_routing_operation_view.xml index 43c41b4b7..792d90300 100644 --- a/mrp_operations_extension/views/mrp_routing_operation_view.xml +++ b/mrp_operations_extension/views/mrp_routing_operation_view.xml @@ -9,6 +9,7 @@ + @@ -22,7 +23,9 @@ - + + + diff --git a/mrp_operations_extension/views/mrp_workcenter_view.xml b/mrp_operations_extension/views/mrp_workcenter_view.xml index 220c7214f..2100aa0b4 100644 --- a/mrp_operations_extension/views/mrp_workcenter_view.xml +++ b/mrp_operations_extension/views/mrp_workcenter_view.xml @@ -20,6 +20,5 @@ - diff --git a/mrp_operations_extension/wizard/__init__.py b/mrp_operations_extension/wizard/__init__.py new file mode 100644 index 000000000..0383abe4b --- /dev/null +++ b/mrp_operations_extension/wizard/__init__.py @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from . import mrp_product_produce diff --git a/mrp_operations_extension/wizard/mrp_product_produce.py b/mrp_operations_extension/wizard/mrp_product_produce.py new file mode 100644 index 000000000..2c08e9fba --- /dev/null +++ b/mrp_operations_extension/wizard/mrp_product_produce.py @@ -0,0 +1,142 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from openerp import fields, models + + +class MrpWorkOrderProduce(models.TransientModel): + _name = "mrp.work.order.produce" + + def default_get(self, cr, uid, fields, context=None): + a = super(MrpWorkOrderProduce, self).default_get( + cr, uid, fields, context=context) + work = self.pool['mrp.production.workcenter.line'].browse( + cr, uid, context.get('active_ids'), context=context)[0] + a.update({'final_product': work.do_production}) + return a + + def _get_product_id(self): + """ To obtain product id + @return: id + """ + prod = False + if self.env.context.get("active_id"): + work_line = self.env['mrp.production.workcenter.line'].browse( + self.env.context.get("active_id")) + prod = work_line.production_id + return prod and prod.product_id or False + + def _get_track(self): + prod = self._get_product_id() + return prod and prod.track_production or False + + def do_produce(self, cr, uid, ids, context=None): + work_line = self.pool['mrp.production.workcenter.line'].browse( + cr, uid, context.get("active_id"), context=context) + production_id = work_line.production_id.id + assert production_id + data = self.browse(cr, uid, ids[0], context=context) + self.pool['mrp.production'].action_produce( + cr, uid, production_id, False, data.mode, data, context=context) + return {} + + def do_consume(self, cr, uid, ids, context=None): + work_line = self.pool['mrp.production.workcenter.line'].browse( + cr, uid, context.get("active_id"), context=context) + production_id = work_line.production_id.id + assert production_id + data = self.browse(cr, uid, ids[0], context=context) + self.pool['mrp.production'].action_produce( + cr, uid, production_id, False, 'consume', data, context=context) + return {} + + def do_consume_produce(self, cr, uid, ids, context=None): + work_line = self.pool['mrp.production.workcenter.line'].browse( + cr, uid, context.get("active_id"), context=context) + production_id = work_line.production_id.id + assert production_id + data = self.browse(cr, uid, ids[0], context=context) + self.pool['mrp.production'].action_produce( + cr, uid, production_id, False, 'consume_produce', data, + context=context) + return {} + + def on_change_qty(self, cr, uid, ids, product_qty, consume_lines, + context=None): + """ + When changing the quantity of products to be producedit will + recalculate the number of raw materials needed according to + the scheduled products and the already consumed/produced products + It will return the consume lines needed for the products + to be produced which the user can still adapt + """ + prod_obj = self.pool["mrp.production"] + work_line = self.pool['mrp.production.workcenter.line'].browse( + cr, uid, context.get("active_id"), context=context) + production = work_line.production_id + consume_lines = [] + new_consume_lines = [] + if product_qty > 0.0: + consume_lines = prod_obj._calculate_qty( + cr, uid, production, product_qty=product_qty, context=context) + line_ids = [i.product_id.id for i in work_line.product_line] + for consume in consume_lines: + if consume['product_id'] in line_ids: + new_consume_lines.append([0, False, consume]) + return {'value': {'consume_lines': new_consume_lines}} + + def _get_product_qty(self): + """ To obtain product quantity + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param context: A standard dictionary + @return: Quantity + """ + work_line = self.env['mrp.production.workcenter.line'].browse( + self.env.context.get("active_id")) + prod = work_line.production_id + done = 0.0 + for move in prod.move_created_ids2: + if move.product_id == prod.product_id: + if not move.scrapped: + done += move.product_qty + return (prod.product_qty - done) or prod.product_qty + + product_id = fields.Many2one('product.product', + string='Product', default=_get_product_id) + product_qty = fields.Float('Select Quantity', + digits=(12, 6), required=True, + default=_get_product_qty) + mode = fields.Selection([('consume_produce', 'Consume & Produce'), + ('consume', 'Consume Only')], + string='Mode', required=True, + default='consume') + lot_id = fields.Many2one('stock.production.lot', 'Lot') + consume_lines = fields.One2many('mrp.product.produce.line', + 'work_produce_id', + string='Products Consumed') + track_production = fields.Boolean('Track production', default=_get_track) + + final_product = fields.Boolean(string='Final Product to Stock') + + +class MrpProductProduceLine(models.TransientModel): + _inherit = "mrp.product.produce.line" + + work_produce_id = fields.Many2one('mrp.work.order.produce') diff --git a/mrp_operations_extension/wizard/mrp_workorder_produce_view.xml b/mrp_operations_extension/wizard/mrp_workorder_produce_view.xml new file mode 100644 index 000000000..67be6b803 --- /dev/null +++ b/mrp_operations_extension/wizard/mrp_workorder_produce_view.xml @@ -0,0 +1,106 @@ + + + + + + + + + MRP Work Order Produce + mrp.work.order.produce + +
+ + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + + + MRP Work Order Produce + mrp.work.order.produce + +
+ + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + + Produce + ir.actions.act_window + mrp.work.order.produce + form + form + new + + + + Consume + ir.actions.act_window + mrp.work.order.produce + form + form + new + + + + +
+