diff --git a/mrp_bom_hierarchy/__init__.py b/mrp_bom_hierarchy/__init__.py new file mode 100644 index 000000000..a8ed7470c --- /dev/null +++ b/mrp_bom_hierarchy/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2015 Eficent () +# +# +# 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 Affero 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 . +# +############################################################################## +from . import model \ No newline at end of file diff --git a/mrp_bom_hierarchy/__openerp__.py b/mrp_bom_hierarchy/__openerp__.py new file mode 100644 index 000000000..9f488449a --- /dev/null +++ b/mrp_bom_hierarchy/__openerp__.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2015 Eficent () +# +# +# 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 Affero 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 . +# +############################################################################## +{ + "name": "MRP BOM Hierarchy", + "version": "1.0", + "author": "Eficent", + "website": "www.eficent.com", + "category": "Manufacturing", + "depends": ["mrp"], + "description": """ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +MRP BOM Hierarchy +================= + +This module was written to extend the functionality of Bill of +Materials to support users to better maintain the BOM hierarchy. + +This module replaces the existing BOM tree views with a new one, from +which the user can create a complete BOM hierarchy. + +The user can navigate from the tree view to child BOM's, or to the +product's BOM components with a single click. + +The user can now search using the field 'Complete Reference' (or Name) to +find all the BOM hierarchy associated to a particular BOM Reference (or +Name) at once. + + +Installation +============ + +No specific installation steps are required. + +Configuration +============= + +No specific configuration steps are required. + +Usage +===== + +To use this module, you need to go to 'Manufacturing | Products | Bill of +Materials Hierarchy' + +Known issues / Roadmap +====================== + +No issues have been identified with this module. + +Credits +======= + +Contributors +------------ + +* Jordi Ballester Alomar + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://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 http://odoo-community.org. +""", + "website": "http://www.eficent.com/", + "license": "AGPL-3", + "demo": [], + "data": [ + "view/mrp.xml", + ], + "test": [], + "installable": True, + "auto_install": False, + "active": False +} \ No newline at end of file diff --git a/mrp_bom_hierarchy/model/__init__.py b/mrp_bom_hierarchy/model/__init__.py new file mode 100644 index 000000000..a2d2420eb --- /dev/null +++ b/mrp_bom_hierarchy/model/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2014 Eficent () +# +# +# 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 Affero 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 . +# +############################################################################## +from . import mrp \ No newline at end of file diff --git a/mrp_bom_hierarchy/model/mrp.py b/mrp_bom_hierarchy/model/mrp.py new file mode 100644 index 000000000..c9f8fda90 --- /dev/null +++ b/mrp_bom_hierarchy/model/mrp.py @@ -0,0 +1,258 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# 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 Affero 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 . +# +############################################################################## + +from openerp.osv import osv, fields, expression + + +class mrp_bom(osv.osv): + _inherit = 'mrp.bom' + + def get_child_boms(self, cr, uid, ids, context=None): + result = {} + if not ids: + return result + for curr_id in ids: + result[curr_id] = True + # Now add the children + cr.execute(''' + WITH RECURSIVE children AS ( + SELECT bom_id, id + FROM mrp_bom + WHERE bom_id IN %s + UNION ALL + SELECT a.bom_id, a.id + FROM mrp_bom a + JOIN children b ON(a.bom_id = b.id) + ) + SELECT * FROM children order by bom_id + ''', (tuple(ids),)) + res = cr.fetchall() + for x, y in res: + result[y] = True + return result + + def _get_boms_from_product(self, cr, uid, ids, context=None): + result = {} + bom_obj = self.pool.get('mrp.bom') + for p in ids: + product_bom_ids = bom_obj.search( + cr, uid, [('product_id', '=', p)]) + bom_ids = bom_obj.get_child_boms(cr, uid, product_bom_ids, + context=context) + for bom_id in bom_ids: + result[bom_id] = True + return result + + def _is_bom(self, cr, uid, ids, name, arg, context=None): + result = {} + if context is None: + context = {} + for bom in self.browse(cr, uid, ids, context=context): + result[bom.id] = False + if bom.bom_lines: + result[bom.id] = True + return result + + def _bom_hierarchy_indent_calc(self, cr, uid, ids, prop, unknow_none, + unknow_dict): + if not ids: + return [] + res = [] + for bom in self.browse(cr, uid, ids, context=None): + data = [] + b = bom + while b: + if b.name and b.bom_id: + data.insert(0, '>') + else: + data.insert(0, '') + + b = b.bom_id + data = ''.join(data) + res.append((bom.id, data)) + return dict(res) + + def _complete_bom_hierarchy_code_calc( + self, cr, uid, ids, prop, unknow_none, unknow_dict): + if not ids: + return [] + res = [] + for bom in self.browse(cr, uid, ids, context=None): + data = [] + b = bom + while b: + if b.code: + data.insert(0, b.code) + elif b.position: + data.insert(0, b.position) + elif b.product_id.default_code: + data.insert(0, b.product_id.default_code) + else: + data.insert(0, '') + + b = b.bom_id + data = ' / '.join(data) + data = '[' + data + '] ' + + res.append((bom.id, data)) + return dict(res) + + def _complete_bom_hierarchy_name_calc( + self, cr, uid, ids, prop, unknow_none, unknow_dict): + if not ids: + return [] + res = [] + for bom in self.browse(cr, uid, ids, context=None): + data = [] + b = bom + while b: + if b.name: + data.insert(0, b.name) + elif b.product_id.name: + data.insert(0, b.product_id.name) + else: + data.insert(0, '') + + b = b.bom_id + + data = ' / '.join(data) + res.append((bom.id, data)) + return dict(res) + + def _is_parent(self, cr, uid, ids, prop, unknow_none, unknow_dict): + res = {} + for bom in self.browse(cr, uid, ids, context=None): + if not bom.bom_id: + res[bom.id] = True + else: + res[bom.id] = False + return res + + def _product_has_own_bom(self, cr, uid, ids, prop, unknow_none, + unknow_dict): + res = {} + for bom in self.browse(cr, uid, ids, context=None): + bom_ids = self.pool.get('mrp.bom').search( + cr, uid, [('product_id', '=', bom.product_id.id), + ('bom_id', '=', False)], context=None) + if bom_ids: + res[bom.id] = True + else: + res[bom.id] = False + return res + + _columns = { + 'is_parent': fields.function(_is_parent, string="Is parent BOM", + type='boolean', readonly=True, + store=True), + 'has_child': fields.function(_is_bom, string="Has components", + type='boolean', readonly=True), + 'product_has_own_bom': fields.function(_product_has_own_bom, + string="Product has own BOM", + type='boolean', readonly=True), + 'bom_hierarchy_indent': fields.function(_bom_hierarchy_indent_calc, + method=True, + type='char', string='Level', + size=32, readonly=True), + 'complete_bom_hierarchy_code': fields.function( + _complete_bom_hierarchy_code_calc, method=True, type='char', + string='Complete Reference', size=250, + help='Describes the full path of this ' + 'component within the BOM hierarchy using the BOM reference.', + store={ + 'mrp.bom': (get_child_boms, ['name', 'code', 'position', + 'bom_id'], 20), + 'product.product': (_get_boms_from_product, ['default_code'], + 20), + }), + 'complete_bom_hierarchy_name': fields.function( + _complete_bom_hierarchy_name_calc, method=True, type='char', + string='Complete Name', size=250, + help='Describes the full path of this ' + 'component within the BOM hierarchy using the BOM name.', + store={ + 'mrp.bom': (get_child_boms, ['name', 'bom_id'], 20), + 'product.product': (_get_boms_from_product, ['name'], 20), + }, + ), + } + + _order = 'complete_bom_hierarchy_code' + + def action_openChildTreeView(self, cr, uid, ids, context=None): + """ + :return dict: dictionary value for created view + """ + if context is None: + context = {} + bom = self.browse(cr, uid, ids[0], context) + child_bom_ids = self.pool.get('mrp.bom').search( + cr, uid, [('bom_id', '=', bom.id)]) + res = self.pool.get('ir.actions.act_window').for_xml_id( + cr, uid, 'mrp_bom_hierarchy', 'action_mrp_bom_hierarchy_tree2', + context) + res['context'] = { + 'default_bom_id': bom.id, + } + res['domain'] = "[('id', 'in', ["+','.join( + map(str, child_bom_ids))+"])]" + res['nodestroy'] = False + return res + + def action_openParentTreeView(self, cr, uid, ids, context=None): + """ + :return dict: dictionary value for created view + """ + if context is None: + context = {} + bom = self.browse(cr, uid, ids[0], context) + res = self.pool.get('ir.actions.act_window').for_xml_id( + cr, uid, 'mrp_bom_hierarchy', 'action_mrp_bom_hierarchy_tree2', + context) + if bom.bom_id: + for parent_bom_id in self.pool.get('mrp.bom').search( + cr, uid, [('id', '=', + bom.bom_id.id)]): + res['domain'] = "[('id','=',"+str(parent_bom_id)+")]" + res['nodestroy'] = False + return res + + def action_openProductBOMTreeView(self, cr, uid, ids, context=None): + """ + :return dict: dictionary value for created view + """ + if context is None: + context = {} + bom = self.browse(cr, uid, ids[0], context) + product_bom_ids = self.pool.get('mrp.bom').search( + cr, uid, [('product_id', '=', bom.product_id.id), + ('bom_id', '=', False)], context=context) + res = self.pool.get('ir.actions.act_window').for_xml_id( + cr, uid, 'mrp', 'mrp_bom_form_action2', + context) + + res['context'] = { + 'default_product_id': bom.product_id.id, + } + res['domain'] = "[('id', 'in', ["+','.join( + map(str, product_bom_ids))+"])]" + res['nodestroy'] = False + return res \ No newline at end of file diff --git a/mrp_bom_hierarchy/static/description/icon.png b/mrp_bom_hierarchy/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/mrp_bom_hierarchy/static/description/icon.png differ diff --git a/mrp_bom_hierarchy/static/description/index.html b/mrp_bom_hierarchy/static/description/index.html new file mode 100644 index 000000000..82a9f1a8a --- /dev/null +++ b/mrp_bom_hierarchy/static/description/index.html @@ -0,0 +1,92 @@ +
+
+
+

MRP BOM Hierarchy

+

+This module was written to extend the functionality of Bill of +Materials to support users to better maintain the BOM hierarchy. + +This module replaces the existing BOM tree views with a new one, from +which the user can create a complete BOM hierarchy. + +The user can navigate from the tree view to child BOM's, or to the +product's BOM components with a single click. + +The user can now search using the field 'Complete Reference' (or Name) to +find all the BOM hierarchy associated to a particular BOM Reference (or +Name) at once. +

+
+
+
+ +
+
+
+

Installation

+
+
+

No specific installation steps are required.

+
+
+
+ +
+
+
+

Configuration

+
+
+

No specific configuration steps are required.

+
+
+
+ +
+
+
+

Usage

+
+
+

To use this module, you need to go to 'Manufacturing | Products | Bill of +Materials Hierarchy' +

+
+
+
+ +
+
+
+

Known issues / Roadmap

+
+
+

No issues have been identified with this module. +

+
+
+
+ +
+
+
+

Credits

+
+
+

Contributors

+ +
+
+

Maintainer

+

+ 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 http://odoo-community.org.
+ +

+
+
+
diff --git a/mrp_bom_hierarchy/view/mrp.xml b/mrp_bom_hierarchy/view/mrp.xml new file mode 100644 index 000000000..d17715095 --- /dev/null +++ b/mrp_bom_hierarchy/view/mrp.xml @@ -0,0 +1,95 @@ + + + + + + mrp.bom.form + mrp.bom + + + + + +