diff --git a/mrp_operations_project/README.rst b/mrp_operations_project/README.rst new file mode 100644 index 000000000..0b249fc98 --- /dev/null +++ b/mrp_operations_project/README.rst @@ -0,0 +1,80 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +================================== +MRP Project Link (with operations) +================================== + +This module links manufacturing operations with projects. It performs the +following actions: + +* Auto-create tasks for work orders with assigned operators. +* Add a tab where to encode task for the work order. +* Add a link on task for the work order scheduled product. + +Installation +============ + +This modules is auto-installed when you install *mrp_operations_extension* and +*mrp_project*. + +Usage +===== + +In a manufacturing order (MO) containing work orders with at least one operator +assigned, when a work order is started, a task is created and assigned to the +operator. + +In the work order form, a new tab "Operators time" is added to input the the +work log. + +Besides, in the related tasks, the products scheduled in the work order are +listed. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/129/8.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed `feedback +`_. + +Credits +======= + +Contributors +------------ + +* Daniel Campos +* Pedro M. Baeza + +Images +------ + +* Original Odoo icons. +* Thanks to https://openclipart.org/detail/15193/Arrow%20set%20%28Comic%29 +* Thanks to https://openclipart.org/detail/151831/work-bench + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/mrp_operations_project/__init__.py b/mrp_operations_project/__init__.py new file mode 100644 index 000000000..ba6a70dfa --- /dev/null +++ b/mrp_operations_project/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Pedro M. Baeza - Serv. Tecnol. Avanzados +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import models diff --git a/mrp_operations_project/__openerp__.py b/mrp_operations_project/__openerp__.py new file mode 100644 index 000000000..7f919e4dd --- /dev/null +++ b/mrp_operations_project/__openerp__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Pedro M. Baeza - Serv. Tecnol. Avanzados +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +{ + "name": "MRP Project Link (with operations)", + "summary": "Create task for work orders with operators", + "version": "8.0.1.0.0", + "depends": [ + "mrp_project", + "mrp_operations_extension", + ], + 'license': 'AGPL-3', + "author": "OdooMRP team," + "AvanzOSC," + "Serv. Tecnol. Avanzados - Pedro M. Baeza," + "Antiun Ingeniería," + "Odoo Community Association (OCA)", + "category": "Manufacturing", + 'data': [ + "views/mrp_production_view.xml", + "views/project_task_view.xml", + ], + 'installable': True, + 'auto_install': True, +} diff --git a/mrp_operations_project/i18n/es.po b/mrp_operations_project/i18n/es.po new file mode 100644 index 000000000..c1b8a0495 --- /dev/null +++ b/mrp_operations_project/i18n/es.po @@ -0,0 +1,168 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_project +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-09 10:50+0000\n" +"Last-Translator: Pedro M. Baeza \n" +"Language-Team: Spanish (http://www.transifex.com/oca/odoomrp-wip-8-0/language/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: mrp_project +#: code:addons/mrp_project/models/mrp_production.py:51 +#, python-format +msgid "" +"\n" +" Manufacturing Order: %s\n" +" Product to Produce: [%s]%s\n" +" Quantity to Produce: %s\n" +" Bill of Material: %s\n" +" Planned Date: %s\n" +" " +msgstr "\n Orden de fabricación: %s\n Producto a producir: [%s]%s\n Cantidad a producir: %s\n Lista de materiales: %s\n Fecha planificada: %s\n " + +#. module: mrp_project +#: code:addons/mrp_project/models/mrp_production.py:103 +#, python-format +msgid "" +"\n" +" Manufacturing Order: %s\n" +" Work Order: %s\n" +" Workcenter: %s\n" +" Cycle: %s\n" +" Hour: %s\n" +" " +msgstr "\n Orden de fabricación: %s\n Orden de trabajo: %s\n Centro de producción: %s\n Ciclo: %s\n Hora: %s\n " + +#. module: mrp_project +#: code:addons/mrp_project/models/mrp_production.py:129 +#, python-format +msgid "%s:: WO%s-%s:: %s" +msgstr "%s:: OT%s-%s:: %s" + +#. module: mrp_project +#: view:account.analytic.line:mrp_project.account_analytic_line_mrp_search_view +#: field:mrp.production,analytic_account_id:0 +msgid "Analytic Account" +msgstr "Cuenta analítica" + +#. module: mrp_project +#: model:ir.model,name:mrp_project.model_account_analytic_line +msgid "Analytic Line" +msgstr "Línea analítica" + +#. module: mrp_project +#: view:account.analytic.line:mrp_project.account_analytic_line_mrp_form_view +msgid "General Accounting" +msgstr "Contabilidad general" + +#. module: mrp_project +#: view:account.analytic.line:mrp_project.account_analytic_line_mrp_form_view +#: view:project.task:mrp_project.project_task_mrp_form_view +msgid "MRP Data" +msgstr "Información de fabricación" + +#. module: mrp_project +#: field:procurement.order,main_project_id:0 +#: field:stock.move,main_project_id:0 +msgid "Main Project" +msgstr "Proyecto principal" + +#. module: mrp_project +#: view:account.analytic.line:mrp_project.account_analytic_line_mrp_search_view +#: view:project.project:mrp_project.project_mrp_procurement_shortcut_form_view +#: view:project.task:mrp_project.project_task_mrp_inh_search_view +msgid "Manufacturing" +msgstr "Fabricación" + +#. module: mrp_project +#: field:account.analytic.line,mrp_production_id:0 +#: model:ir.model,name:mrp_project.model_mrp_production +#: field:project.task,mrp_production_id:0 +msgid "Manufacturing Order" +msgstr "Orden de fabricación" + +#. module: mrp_project +#: model:ir.actions.act_window,name:mrp_project.act_project_2_production_all +msgid "Manufacturing Orders" +msgstr "Órdenes de fabricación" + +#. module: mrp_project +#: model:ir.model,name:mrp_project.model_procurement_order +msgid "Procurement" +msgstr "Abastecimiento" + +#. module: mrp_project +#: model:ir.actions.act_window,name:mrp_project.act_project_2_procurement_all +#: view:project.project:mrp_project.project_mrp_procurement_shortcut_form_view +msgid "Procurements" +msgstr "Abastecimientos" + +#. module: mrp_project +#: view:project.task:mrp_project.project_task_mrp_form_view +#: view:project.task:mrp_project.project_task_mrp_inh_tree_view +msgid "Product to Produce" +msgstr "Producto a producir" + +#. module: mrp_project +#: model:ir.model,name:mrp_project.model_mrp_production_product_line +msgid "Production Scheduled Product" +msgstr "Producto planificado de la fabricación" + +#. module: mrp_project +#: model:ir.model,name:mrp_project.model_project_project +#: field:mrp.production,project_id:0 +msgid "Project" +msgstr "Proyecto" + +#. module: mrp_project +#: field:account.analytic.line,task_id:0 +msgid "Project Task" +msgstr "Tarea de proyecto" + +#. module: mrp_project +#: view:project.task:mrp_project.project_task_mrp_form_view +msgid "Scheduled Products" +msgstr "Productos planificados" + +#. module: mrp_project +#: view:project.task:mrp_project.project_task_mrp_inh_search_view +msgid "Stage" +msgstr "Etapa" + +#. module: mrp_project +#: model:ir.model,name:mrp_project.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de stock" + +#. module: mrp_project +#: model:ir.model,name:mrp_project.model_project_task +#: field:mrp.production.product.line,task_id:0 +msgid "Task" +msgstr "Tarea" + +#. module: mrp_project +#: field:account.analytic.line,workorder:0 +#: model:ir.model,name:mrp_project.model_mrp_production_workcenter_line +msgid "Work Order" +msgstr "Orden de trabajo" + +#. module: mrp_project +#: view:account.analytic.line:mrp_project.account_analytic_line_mrp_search_view +#: view:project.task:mrp_project.project_task_mrp_inh_search_view +msgid "Workorder" +msgstr "Orden de trabajo" + +#. module: mrp_project +#: view:account.analytic.line:mrp_project.account_analytic_line_mrp_search_view +msgid "group_analytic_account" +msgstr "" diff --git a/mrp_operations_project/models/__init__.py b/mrp_operations_project/models/__init__.py new file mode 100644 index 000000000..2c2ef74ce --- /dev/null +++ b/mrp_operations_project/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Pedro M. Baeza - Serv. Tecnol. Avanzados +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import mrp_production +from . import project_task diff --git a/mrp_operations_project/models/mrp_production.py b/mrp_operations_project/models/mrp_production.py new file mode 100644 index 000000000..428c02100 --- /dev/null +++ b/mrp_operations_project/models/mrp_production.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# (c) 2014 Daniel Campos +# (c) 2015 Pedro M. Baeza - Serv. Tecnol. Avanzados +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp import api, fields, models, _ + + +class MrpProductionWorkcenterLine(models.Model): + _inherit = 'mrp.production.workcenter.line' + + @api.multi + def _compute_task_m2m(self): + for record in self: + record.task_m2m = record.task_ids + + # needed because the one2many can't be part of a domain directly + task_m2m = fields.Many2many( + comodel_name="project.task", compute="_compute_task_m2m") + + @api.model + def _prepare_workorder_task(self, workorder): + task_domain = [ + ('mrp_production_id', '=', workorder.production_id.id), + ('workorder', '=', False)] + production_tasks = self.env['project.task'].search(task_domain) + task_descr = _(""" + Manufacturing Order: %s + Work Order: %s + Workcenter: %s + Cycle: %s + Hour: %s + """) % (workorder.production_id.name, workorder.name, + workorder.workcenter_id.name, workorder.cycle, + workorder.hour) + return { + 'mrp_production_id': workorder.production_id.id, + 'workorder': workorder.id, + 'reviewer_id': workorder.production_id.user_id.id, + 'description': task_descr, + 'project_id': workorder.production_id.project_id.id, + 'parent_ids': [(6, 0, production_tasks.ids)] + } + + @api.model + def _prepare_tasks_vals(self, workorder, task_vals): + """Method to be inheritable for having the possibility of creating + multiple tasks from one work order. + :param workorder: Work order + :param task_vals: Template task values + :return: List of dictionaries with each of the task values to create. + """ + tasks_vals = [] + wk_operation = workorder.routing_wc_line.op_wc_lines.filtered( + lambda r: r.workcenter == workorder.workcenter_id)[:1] + count = (wk_operation.op_number or + workorder.workcenter_id.op_number) + op_list = workorder.workcenter_id.operators + for i in range(count): + # Create a task for each employee + if len(op_list) > i: + task_vals['user_id'] = op_list[i].id + task_name = (_("%s:: WO%s-%s:: %s") % + (workorder.production_id.name, + str(workorder.sequence).zfill(3), + str(i).zfill(3), workorder.name)) + task_vals['name'] = task_name + tasks_vals.append(task_vals) + return tasks_vals + + @api.multi + def action_start_working(self): + res = super(MrpProductionWorkcenterLine, self).action_start_working() + task_obj = self.env['project.task'] + for workorder in self: + task_vals = self._prepare_workorder_task(workorder) + tasks_vals = self._prepare_tasks_vals(workorder, task_vals) + for task_vals in tasks_vals: + task_obj.create(task_vals) + return res diff --git a/mrp_operations_project/models/project_task.py b/mrp_operations_project/models/project_task.py new file mode 100644 index 000000000..e152ac382 --- /dev/null +++ b/mrp_operations_project/models/project_task.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# (c) 2014 Daniel Campos (danielcampos@avanzosc.es) +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp import fields, models + + +class ProjectTask(models.Model): + _inherit = 'project.task' + + workorder_scheduled_products = fields.One2many( + comodel_name="mrp.production.product.line", inverse_name='task_id', + related='workorder.product_line', store=False, + string='Scheduled Products') diff --git a/mrp_operations_project/static/description/icon.png b/mrp_operations_project/static/description/icon.png new file mode 100644 index 000000000..450d2183c Binary files /dev/null and b/mrp_operations_project/static/description/icon.png differ diff --git a/mrp_operations_project/static/description/icon.svg b/mrp_operations_project/static/description/icon.svg new file mode 100644 index 000000000..4fa867f8e --- /dev/null +++ b/mrp_operations_project/static/description/icon.svg @@ -0,0 +1,260 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mrp_operations_project/tests/__init__.py b/mrp_operations_project/tests/__init__.py new file mode 100644 index 000000000..6db718e98 --- /dev/null +++ b/mrp_operations_project/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Pedro M. Baeza - Serv. Tecnol. Avanzados +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_mrp_operations_project diff --git a/mrp_operations_project/tests/test_mrp_operations_project.py b/mrp_operations_project/tests/test_mrp_operations_project.py new file mode 100644 index 000000000..472e90ded --- /dev/null +++ b/mrp_operations_project/tests/test_mrp_operations_project.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Pedro M. Baeza - Serv. Tecnol. Avanzados +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp.addons.mrp_project.tests import test_mrp_project + + +class TestMrpOperationsProject(test_mrp_project.TestMrpProject): + def setUp(self): + super(TestMrpOperationsProject, self).setUp() + self.workcenter = self.env['mrp.workcenter'].create( + {'name': 'Test work center'}) + self.routing = self.env['mrp.routing'].create( + { + 'name': 'Test routing', + 'workcenter_lines': [ + (0, 0, {'name': 'Test workcenter line', + 'do_production': True, + 'workcenter_id': self.workcenter.id})], + }) + self.production.routing_id = self.routing.id + + def test_workcenter_tasks(self): + self.workcenter.op_number = 1 + self.production.signal_workflow('button_confirm') + self.production.force_production() + # start the MO (and this starts the first WO) + self.assertFalse(self.production.project_id.task_ids) + self.production.signal_workflow('button_produce') + self.assertEqual(len(self.production.workcenter_lines[0].task_m2m), 1) + self.assertEqual(len(self.production.project_id.task_ids), 2) + + def test_project_full(self): + """Don't repeat this test.""" + pass + + def test_preservation_project_with_works(self): + """Don't repeat this test.""" + pass + + def test_onchange_task(self): + """Don't repeat this test.""" + pass + + def test_button_end_work(self): + """Don't repeat this test.""" + pass diff --git a/mrp_operations_project/views/mrp_production_view.xml b/mrp_operations_project/views/mrp_production_view.xml new file mode 100644 index 000000000..710d16f1d --- /dev/null +++ b/mrp_operations_project/views/mrp_production_view.xml @@ -0,0 +1,56 @@ + + + + Project task work view for MRP + project.task.work + + + + + + + +