diff --git a/mrp_production_hierarchy/README.rst b/mrp_production_hierarchy/README.rst new file mode 100644 index 000000000..88d67e140 --- /dev/null +++ b/mrp_production_hierarchy/README.rst @@ -0,0 +1,94 @@ +=========================== +Production Orders Hierarchy +=========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github + :target: https://github.com/OCA/manufacture/tree/10.0/mrp_production_hierarchy + :alt: OCA/manufacture +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/manufacture-10-0/manufacture-10-0-mrp_production_hierarchy + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/129/10.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to view the hierarchy of generated production orders +when several levels of bill of materials are involved. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Create a new production order (Manufacture / Operations / Manufacturing Orders) +with a multi-levels nomenclatured product, and related products configured with +'Manufacture' and 'Make To Order' routes: + +.. figure:: mrp_production_hierarchy/static/description/mrp_production_hierarchy_1.png + +Once saved, click on the 'Hierarchy' button at right: + +.. figure:: mrp_production_hierarchy/static/description/mrp_production_hierarchy_2.png + +.. figure:: mrp_production_hierarchy/static/description/mrp_production_hierarchy_3.png + +Known issues / Roadmap +====================== + +* Only new production orders will benefit from this feature, it is not compatible with existing orders. + +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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ABF OSIELL + +Contributors +~~~~~~~~~~~~ + +* Sébastien Alix (https://osiell.com) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/manufacture `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mrp_production_hierarchy/__init__.py b/mrp_production_hierarchy/__init__.py new file mode 100644 index 000000000..a0fdc10fe --- /dev/null +++ b/mrp_production_hierarchy/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import models diff --git a/mrp_production_hierarchy/__manifest__.py b/mrp_production_hierarchy/__manifest__.py new file mode 100644 index 000000000..6c87fe3a6 --- /dev/null +++ b/mrp_production_hierarchy/__manifest__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Production Orders Hierarchy", + "summary": "View the hierarchy of generated production orders", + "version": "10.0.1.0.0", + "category": "Manufacturing", + "website": "https://github.com/OCA/manufacture", + "author": "ABF OSIELL, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "mrp", + ], + "data": [ + "views/mrp_production.xml", + ], +} diff --git a/mrp_production_hierarchy/i18n/fr.po b/mrp_production_hierarchy/i18n/fr.po new file mode 100644 index 000000000..0af69a366 --- /dev/null +++ b/mrp_production_hierarchy/i18n/fr.po @@ -0,0 +1,60 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_hierarchy +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-05 13:37+0000\n" +"PO-Revision-Date: 2018-06-05 13:37+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_child_ids +msgid "Child orders" +msgstr "OF générés" + +#. module: mrp_production_hierarchy +#: code:addons/mrp_production_hierarchy/models/mrp_production.py:46 +#: model:ir.ui.view,arch_db:mrp_production_hierarchy.mrp_production_form_view +#, python-format +msgid "Hierarchy" +msgstr "Hiérarchie" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_parent_left +msgid "Left Parent" +msgstr "Parent gauche" + +#. module: mrp_production_hierarchy +#: model:ir.model,name:mrp_production_hierarchy.model_mrp_production +msgid "Manufacturing Order" +msgstr "Ordre de fabrication" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_parent_id +#: model:ir.ui.view,arch_db:mrp_production_hierarchy.view_mrp_production_filter +msgid "Parent order" +msgstr "OF d'origine" + +#. module: mrp_production_hierarchy +#: model:ir.model,name:mrp_production_hierarchy.model_procurement_order +msgid "Procurement" +msgstr "Approvisionnement" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_parent_right +msgid "Right Parent" +msgstr "Parent à droite" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_root_id +#: model:ir.ui.view,arch_db:mrp_production_hierarchy.view_mrp_production_filter +msgid "Root order" +msgstr "OF racine" diff --git a/mrp_production_hierarchy/i18n/mrp_production_hierarchy.pot b/mrp_production_hierarchy/i18n/mrp_production_hierarchy.pot new file mode 100644 index 000000000..d801fc85f --- /dev/null +++ b/mrp_production_hierarchy/i18n/mrp_production_hierarchy.pot @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_hierarchy +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-05-18 13:30+0000\n" +"PO-Revision-Date: 2018-05-18 13:30+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_child_ids +msgid "Child orders" +msgstr "" + +#. module: mrp_production_hierarchy +#: code:addons/mrp_production_hierarchy/models/mrp_production.py:37 +#: model:ir.ui.view,arch_db:mrp_production_hierarchy.mrp_production_form_view +#, python-format +msgid "Hierarchy" +msgstr "" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_parent_left +msgid "Left Parent" +msgstr "" + +#. module: mrp_production_hierarchy +#: model:ir.model,name:mrp_production_hierarchy.model_mrp_production +msgid "Manufacturing Order" +msgstr "" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_parent_id +msgid "Parent order" +msgstr "" + +#. module: mrp_production_hierarchy +#: model:ir.model,name:mrp_production_hierarchy.model_procurement_order +msgid "Procurement" +msgstr "" + +#. module: mrp_production_hierarchy +#: model:ir.model.fields,field_description:mrp_production_hierarchy.field_mrp_production_parent_right +msgid "Right Parent" +msgstr "" + diff --git a/mrp_production_hierarchy/models/__init__.py b/mrp_production_hierarchy/models/__init__.py new file mode 100644 index 000000000..36d8d6c54 --- /dev/null +++ b/mrp_production_hierarchy/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import mrp_production +from . import procurement_order diff --git a/mrp_production_hierarchy/models/mrp_production.py b/mrp_production_hierarchy/models/mrp_production.py new file mode 100644 index 000000000..dfa9d6727 --- /dev/null +++ b/mrp_production_hierarchy/models/mrp_production.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ + + +class MrpProduction(models.Model): + _inherit = 'mrp.production' + + root_id = fields.Many2one( + 'mrp.production', u"Root order", + index=True, ondelete='restrict', readonly=True) + parent_id = fields.Many2one( + 'mrp.production', u"Parent order", + index=True, ondelete='restrict', readonly=True) + child_ids = fields.One2many( + 'mrp.production', 'parent_id', u"Child orders", + domain=[('state', '!=', 'cancel')]) + + @api.multi + def _generate_moves(self): + """Overloaded to pass the created production order ID in the context. + It will be used by the 'procurement_order.make_mo()' overload to + set the parent relation between production orders. + """ + for prod in self: + # Set the initial root production order ID + if not prod.env.context.get('root_mrp_production_id'): + prod = prod.with_context(root_mrp_production_id=self.id) + # Set the parent production order ID + prod = prod.with_context(parent_mrp_production_id=self.id) + super(MrpProduction, prod)._generate_moves() + return True + + @api.multi + def open_production_tree(self): + self.ensure_one() + if self.child_ids: + return { + 'domain': "[('id', '=', %s)]" % self.id, + 'name': _(u"Hierarchy"), + 'view_type': 'tree', + 'view_mode': 'tree', + 'res_model': 'mrp.production', + 'view_id': self.env.ref( + 'mrp_production_hierarchy.' + 'mrp_production_tree_view_field_parent').id, + 'target': 'current', + 'type': 'ir.actions.act_window', + 'context': dict(self.env.context), + } + return False diff --git a/mrp_production_hierarchy/models/procurement_order.py b/mrp_production_hierarchy/models/procurement_order.py new file mode 100644 index 000000000..50b50d169 --- /dev/null +++ b/mrp_production_hierarchy/models/procurement_order.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class ProcurementOrder(models.Model): + _inherit = 'procurement.order' + + @api.multi + def make_mo(self): + """Overload to set the root and parent production order ID to the + children production orders. + """ + res = super(ProcurementOrder, self).make_mo() + production_ids = [id_ for id_ in res.values() if id_] + productions = self.env['mrp.production'].browse(production_ids) + for production in productions: + if self.env.context.get('parent_mrp_production_id'): + parent_id = self.env.context['parent_mrp_production_id'] + root_id = self.env.context['root_mrp_production_id'] + production.write({ + 'parent_id': parent_id, + 'root_id': root_id, + }) + return res diff --git a/mrp_production_hierarchy/readme/CONTRIBUTORS.rst b/mrp_production_hierarchy/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..68ca198d5 --- /dev/null +++ b/mrp_production_hierarchy/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Sébastien Alix (https://osiell.com) diff --git a/mrp_production_hierarchy/readme/DESCRIPTION.rst b/mrp_production_hierarchy/readme/DESCRIPTION.rst new file mode 100644 index 000000000..36bcd1a4e --- /dev/null +++ b/mrp_production_hierarchy/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows to view the hierarchy of generated production orders +when several levels of bill of materials are involved. diff --git a/mrp_production_hierarchy/readme/ROADMAP.rst b/mrp_production_hierarchy/readme/ROADMAP.rst new file mode 100644 index 000000000..bc2567d04 --- /dev/null +++ b/mrp_production_hierarchy/readme/ROADMAP.rst @@ -0,0 +1 @@ +* Only new production orders will benefit from this feature, it is not compatible with existing orders. diff --git a/mrp_production_hierarchy/readme/USAGE.rst b/mrp_production_hierarchy/readme/USAGE.rst new file mode 100644 index 000000000..34c59473f --- /dev/null +++ b/mrp_production_hierarchy/readme/USAGE.rst @@ -0,0 +1,11 @@ +Create a new production order (Manufacture / Operations / Manufacturing Orders) +with a multi-levels nomenclatured product, and related products configured with +'Manufacture' and 'Make To Order' routes: + +.. figure:: mrp_production_hierarchy/static/description/mrp_production_hierarchy_1.png + +Once saved, click on the 'Hierarchy' button at right: + +.. figure:: mrp_production_hierarchy/static/description/mrp_production_hierarchy_2.png + +.. figure:: mrp_production_hierarchy/static/description/mrp_production_hierarchy_3.png diff --git a/mrp_production_hierarchy/static/description/icon.png b/mrp_production_hierarchy/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/mrp_production_hierarchy/static/description/icon.png differ diff --git a/mrp_production_hierarchy/static/description/mrp_production_hierarchy_1.png b/mrp_production_hierarchy/static/description/mrp_production_hierarchy_1.png new file mode 100644 index 000000000..59b485a39 Binary files /dev/null and b/mrp_production_hierarchy/static/description/mrp_production_hierarchy_1.png differ diff --git a/mrp_production_hierarchy/static/description/mrp_production_hierarchy_2.png b/mrp_production_hierarchy/static/description/mrp_production_hierarchy_2.png new file mode 100644 index 000000000..b5abf1793 Binary files /dev/null and b/mrp_production_hierarchy/static/description/mrp_production_hierarchy_2.png differ diff --git a/mrp_production_hierarchy/static/description/mrp_production_hierarchy_3.png b/mrp_production_hierarchy/static/description/mrp_production_hierarchy_3.png new file mode 100644 index 000000000..c3b0607dd Binary files /dev/null and b/mrp_production_hierarchy/static/description/mrp_production_hierarchy_3.png differ diff --git a/mrp_production_hierarchy/tests/__init__.py b/mrp_production_hierarchy/tests/__init__.py new file mode 100644 index 000000000..b66615d8d --- /dev/null +++ b/mrp_production_hierarchy/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_mrp_production_hierarchy diff --git a/mrp_production_hierarchy/tests/test_mrp_production_hierarchy.py b/mrp_production_hierarchy/tests/test_mrp_production_hierarchy.py new file mode 100644 index 000000000..f9d9465c3 --- /dev/null +++ b/mrp_production_hierarchy/tests/test_mrp_production_hierarchy.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.addons.mrp.tests.common import TestMrpCommon + + +class TestMrpProductionHierarchy(TestMrpCommon): + + def setUp(self): + super(TestMrpProductionHierarchy, self).setUp() + self.bom_2.write({'type': 'normal'}) + route_manufacture = self.env.ref('mrp.route_warehouse0_manufacture') + route_mto = self.env.ref('stock.route_warehouse0_mto') + (self.bom_1 | self.bom_2 | self.bom_3).mapped('product_id').write( + {'route_ids': [(6, 0, [route_manufacture.id, route_mto.id])]}) + + def test_production_hierarchy(self): + # bom_3 (product_6) -> bom_2 (product_5) -> bom_1 (product_4) + man_order = self.env['mrp.production'].create({ + 'name': 'MO-Test', + 'product_id': self.product_6.id, + 'product_uom_id': self.product_6.uom_id.id, + 'product_qty': 2, + 'bom_id': self.bom_3.id, + }) + self.assertEqual(len(man_order.child_ids), 2) + self.assertIn( + self.bom_2.product_id, man_order.child_ids.mapped('product_id')) + for child in man_order.child_ids: + self.assertIn(child.product_id, [self.product_5, self.product_4]) + self.assertEqual(child.root_id, man_order) + self.assertEqual(child.parent_id, man_order) + if child.product_id == self.bom_2.product_id: + self.assertTrue(child.child_ids) + self.assertTrue(child.open_production_tree()) + for child2 in child.child_ids: + self.assertIn(child2.product_id, [self.product_4]) + self.assertEqual(child2.root_id, man_order) + self.assertEqual(child2.parent_id, child) + self.assertTrue(man_order.open_production_tree()) diff --git a/mrp_production_hierarchy/views/mrp_production.xml b/mrp_production_hierarchy/views/mrp_production.xml new file mode 100644 index 000000000..387d2ccbb --- /dev/null +++ b/mrp_production_hierarchy/views/mrp_production.xml @@ -0,0 +1,65 @@ + + + + + mrp.production.form + mrp.production + + +
+ +
+ + + + + +
+ + + mrp.production.tree + mrp.production + extension + + + + + + + + + + + mrp.production.search.inherit + mrp.production + + + + + + + + + + + + mrp.production.tree + mrp.production + child_ids + primary + + + + + + + +