diff --git a/mass_editing/__openerp__.py b/mass_editing/__openerp__.py index 011e0be..4d96073 100644 --- a/mass_editing/__openerp__.py +++ b/mass_editing/__openerp__.py @@ -2,7 +2,8 @@ ############################################################################## # # This module uses OpenERP, Open Source Management Solution Framework. -# Copyright (C) 2012-Today Serpent Consulting Services () +# Copyright (C): +# 2012-Today Serpent Consulting Services () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,16 +20,21 @@ # ############################################################################## { - "name" : "Mass Editing", - "version" : "1.3", - "author" : "Serpent Consulting Services", - "category" : "Tools", - "website" : "http://www.serpentcs.com", - "description": """This module provides the functionality to add, update or remove the values of more than one records on the fly at the same time. - You can configure mass editing for any OpenERP model. - The video explaining the features and how-to for OpenERP Version 6 is here http://t.co/wukYMx1A - The video explaining the features and how-to for OpenERP Version 7 is here : http://www.youtube.com/watch?v=9BH0o74A748&feature=youtu.be - For more details/customization/feedback contact us on contact@serpentcs.com. + "name": "Mass Editing", + "version": "1.3", + "author": "Serpent Consulting Services", + "category": "Tools", + "website": "http://www.serpentcs.com", + "description": """ +This module provides the functionality to add, update or remove the values""" + """of more than one records on the fly at the same time. + You can configure mass editing for any OpenERP model. + The video explaining the features and how-to for OpenERP Version 6""" + """ is here http://t.co/wukYMx1A + The video explaining the features and how-to for OpenERP Version 7 is""" + """ here : http://www.youtube.com/watch?v=9BH0o74A748&feature=youtu.be + For more details/customization/feedback contact us on""" + """ contact@serpentcs.com. """, 'depends': ['base'], 'data': [ diff --git a/mass_editing/mass_editing.py b/mass_editing/mass_editing.py index 9426ec9..9f72457 100644 --- a/mass_editing/mass_editing.py +++ b/mass_editing/mass_editing.py @@ -2,7 +2,8 @@ ############################################################################## # # This module uses OpenERP, Open Source Management Solution Framework. -# Copyright (C) 2012-Today Serpent Consulting Services () +# Copyright (C): +# 2012-Today Serpent Consulting Services () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,37 +20,48 @@ # ############################################################################## -from openerp.osv import orm, fields -import openerp.tools +from openerp.osv import orm, fields, osv from openerp.tools.translate import _ -from lxml import etree + class ir_model_fields(orm.Model): _inherit = 'ir.model.fields' - - def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False): + + def search( + self, cr, uid, args, offset=0, limit=0, order=None, context=None, + count=False): model_domain = [] for domain in args: - if domain[0] == 'model_id' and domain[2] and type(domain[2]) != list: - model_domain += [('model_id', 'in', map(int, domain[2][1:-1].split(',')))] + if domain[0] == 'model_id' and domain[2]\ + and type(domain[2]) != list: + model_domain += [( + 'model_id', 'in', map(int, domain[2][1:-1].split(',')))] else: model_domain.append(domain) - return super(ir_model_fields, self).search(cr, uid, model_domain, offset=offset, limit=limit, order=order, context=context, count=count) + return super(ir_model_fields, self).search( + cr, uid, model_domain, offset=offset, limit=limit, order=order, + context=context, count=count) ir_model_fields() + class mass_object(orm.Model): _name = "mass.object" _columns = { - 'name' : fields.char("Name", size=64, required=True, select=1), - 'model_id' : fields.many2one('ir.model', 'Model', required=True, select=1), - 'field_ids' : fields.many2many('ir.model.fields', 'mass_field_rel', 'mass_id', 'field_id', 'Fields'), - 'ref_ir_act_window':fields.many2one('ir.actions.act_window', 'Sidebar Action', readonly=True, - help="Sidebar action to make this template available on records \ - of the related document model"), - 'ref_ir_value':fields.many2one('ir.values', 'Sidebar Button', readonly=True, - help="Sidebar button to open the sidebar action"), + 'name': fields.char("Name", size=64, required=True, select=1), + 'model_id': fields.many2one( + 'ir.model', 'Model', required=True, select=1), + 'field_ids': fields.many2many( + 'ir.model.fields', 'mass_field_rel', 'mass_id', 'field_id', + 'Fields'), + 'ref_ir_act_window': fields.many2one( + 'ir.actions.act_window', 'Sidebar Action', readonly=True, + help="Sidebar action to make this template available on records \ + of the related document model"), + 'ref_ir_value': fields.many2one( + 'ir.values', 'Sidebar Button', readonly=True, + help="Sidebar button to open the sidebar action"), 'model_ids': fields.many2many('ir.model', string='Model List') } @@ -58,60 +70,68 @@ class mass_object(orm.Model): ] def onchange_model(self, cr, uid, ids, model_id, context=None): - if context is None: context = {} + if context is None: + context = {} if not model_id: return {'value': {'model_ids': [(6, 0, [])]}} model_ids = [model_id] model_obj = self.pool.get('ir.model') - active_model_obj = self.pool.get(model_obj.browse(cr, uid, model_id).model) + active_model_obj = self.pool.get(model_obj.browse( + cr, uid, model_id).model) if active_model_obj._inherits: for key, val in active_model_obj._inherits.items(): - found_model_ids = model_obj.search(cr, uid, [('model', '=', key)], context=context) + found_model_ids = model_obj.search( + cr, uid, [('model', '=', key)], context=context) model_ids += found_model_ids return {'value': {'model_ids': [(6, 0, model_ids)]}} def create_action(self, cr, uid, ids, context=None): vals = {} action_obj = self.pool.get('ir.actions.act_window') - data_obj = self.pool.get('ir.model.data') ir_values_obj = self.pool.get('ir.values') for data in self.browse(cr, uid, ids, context=context): src_obj = data.model_id.model button_name = _('Mass Editing (%s)') % data.name vals['ref_ir_act_window'] = action_obj.create(cr, uid, { - 'name': button_name, - 'type': 'ir.actions.act_window', - 'res_model': 'mass.editing.wizard', - 'src_model': src_obj, - 'view_type': 'form', - 'context': "{'mass_editing_object' : %d}" % (data.id), - 'view_mode':'form,tree', - 'target': 'new', - 'auto_refresh':1 - }, context) + 'name': button_name, + 'type': 'ir.actions.act_window', + 'res_model': 'mass.editing.wizard', + 'src_model': src_obj, + 'view_type': 'form', + 'context': "{'mass_editing_object' : %d}" % (data.id), + 'view_mode': 'form,tree', + 'target': 'new', + 'auto_refresh': 1, + }, context) vals['ref_ir_value'] = ir_values_obj.create(cr, uid, { - 'name': button_name, - 'model': src_obj, - 'key2': 'client_action_multi', - 'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']), - 'object': True, - }, context) - self.write(cr, uid, ids, { - 'ref_ir_act_window': vals.get('ref_ir_act_window', False), - 'ref_ir_value': vals.get('ref_ir_value', False), + 'name': button_name, + 'model': src_obj, + 'key2': 'client_action_multi', + 'value': ( + "ir.actions.act_window," + + str(vals['ref_ir_act_window'])), + 'object': True, }, context) + self.write(cr, uid, ids, { + 'ref_ir_act_window': vals.get('ref_ir_act_window', False), + 'ref_ir_value': vals.get('ref_ir_value', False), + }, context) return True def unlink_action(self, cr, uid, ids, context=None): for template in self.browse(cr, uid, ids, context=context): try: if template.ref_ir_act_window: - self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context) + self.pool.get('ir.actions.act_window').unlink( + cr, uid, template.ref_ir_act_window.id, context) if template.ref_ir_value: ir_values_obj = self.pool.get('ir.values') - ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context) + ir_values_obj.unlink( + cr, uid, template.ref_ir_value.id, context) except: - raise osv.except_osv(_("Warning"), _("Deletion of the action record failed.")) + raise osv.except_osv( + _("Warning"), + _("Deletion of the action record failed.")) return True def unlink(self, cr, uid, ids, context=None): @@ -121,9 +141,9 @@ class mass_object(orm.Model): def copy(self, cr, uid, record_id, default=None, context=None): if default is None: default = {} - - default.update({'name':'','field_ids': []}) - return super(mass_object, self).copy(cr, uid, record_id, default, context) + default.update({'name': '', 'field_ids': []}) + return super(mass_object, self).copy( + cr, uid, record_id, default, context) mass_object() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/mass_editing/wizard/mass_editing_wizard.py b/mass_editing/wizard/mass_editing_wizard.py index 8bf88cf..64c6683 100644 --- a/mass_editing/wizard/mass_editing_wizard.py +++ b/mass_editing/wizard/mass_editing_wizard.py @@ -2,7 +2,8 @@ ############################################################################## # # This module uses OpenERP, Open Source Management Solution Framework. -# Copyright (C) 2012-Today Serpent Consulting Services () +# Copyright (C): +# 2012-Today Serpent Consulting Services () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,80 +20,165 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp.osv import orm import openerp.tools as tools from lxml import etree + class mass_editing_wizard(orm.TransientModel): _name = 'mass.editing.wizard' _columns = { } - def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): - result = super(mass_editing_wizard, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu) + def fields_view_get( + self, cr, uid, view_id=None, view_type='form', context=None, + toolbar=False, submenu=False): + result = super(mass_editing_wizard, self).fields_view_get( + cr, uid, view_id, view_type, context, toolbar, submenu) if context.get('mass_editing_object'): - mass_object = self.pool.get('mass.object') - editing_data = mass_object.browse(cr, uid, context.get('mass_editing_object'), context) + mass_object = self.pool.get('mass.object') + editing_data = mass_object.browse( + cr, uid, context.get('mass_editing_object'), context) all_fields = {} - xml_form = etree.Element('form', {'string': tools.ustr(editing_data.name), 'version':'7.0'}) + xml_form = etree.Element('form', { + 'string': tools.ustr(editing_data.name), 'version': '7.0'}) xml_group = etree.SubElement(xml_form, 'group', {'colspan': '4'}) - etree.SubElement(xml_group, 'label', {'string': '', 'colspan': '2'}) + etree.SubElement(xml_group, 'label', { + 'string': '', 'colspan': '2'}) xml_group = etree.SubElement(xml_form, 'group', {'colspan': '4'}) model_obj = self.pool.get(context.get('active_model')) field_info = model_obj.fields_get(cr, uid, [], context) for field in editing_data.field_ids: if field.ttype == "many2many": - all_fields[field.name] = field_info[field.name] - all_fields["selection__" + field.name] = {'type':'selection', 'string': field_info[field.name]['string'], 'selection':[('set', 'Set'), ('remove_m2m', 'Remove'), ('add', 'Add')]} - xml_group = etree.SubElement(xml_group, 'group', {'colspan': '4'}) - etree.SubElement(xml_group, 'separator', {'string': field_info[field.name]['string'], 'colspan': '2'}) - etree.SubElement(xml_group, 'field', {'name': "selection__" + field.name, 'colspan': '2', 'nolabel':'1'}) - etree.SubElement(xml_group, 'field', {'name': field.name, 'colspan':'4', 'nolabel':'1', 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove_m2m')]}"}) + all_fields[field.name] = field_info[field.name] + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [ + ('set', 'Set'), ('remove_m2m', 'Remove'), + ('add', 'Add')]} + xml_group = etree.SubElement(xml_group, 'group', { + 'colspan': '4'}) + etree.SubElement(xml_group, 'separator', { + 'string': field_info[field.name]['string'], + 'colspan': '2'}) + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, + 'colspan': '2', 'nolabel': '1'}) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'colspan': '4', 'nolabel': '1', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove_m2m')]}")}) elif field.ttype == "one2many": - all_fields["selection__" + field.name] = {'type':'selection', - 'string': field_info[field.name]['string'], - 'selection':[('set', 'Set'), - ('remove', 'Remove')]} - all_fields[field.name] = {'type':field.ttype, - 'string': field.field_description, - 'relation': field.relation} - etree.SubElement(xml_group, 'field', - {'name': "selection__" + field.name, 'colspan':'2'}) - etree.SubElement(xml_group, 'field', - {'name': field.name, 'colspan':'4', 'nolabel':'1', - 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove_o2m')]}"}) + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [('set', 'Set'), ('remove', 'Remove')]} + all_fields[field.name] = { + 'type': field.ttype, 'string': field.field_description, + 'relation': field.relation} + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, 'colspan': '2'}) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'colspan': '4', 'nolabel': '1', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove_o2m')]}")}) elif field.ttype == "many2one": - all_fields["selection__" + field.name] = {'type':'selection', 'string': field_info[field.name]['string'], 'selection':[('set', 'Set'), ('remove', 'Remove')]} - all_fields[field.name] = {'type':field.ttype, 'string': field.field_description, 'relation': field.relation} - etree.SubElement(xml_group, 'field', {'name': "selection__" + field.name, 'colspan':'2'}) - etree.SubElement(xml_group, 'field', {'name': field.name, 'nolabel':'1', 'colspan':'2', 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove')]}"}) + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [('set', 'Set'), ('remove', 'Remove')]} + all_fields[field.name] = { + 'type': field.ttype, 'string': field.field_description, + 'relation': field.relation} + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, 'colspan': '2'}) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'nolabel': '1', 'colspan': '2', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove')]}")}) elif field.ttype == "char": - all_fields["selection__" + field.name] = {'type':'selection', 'string': field_info[field.name]['string'], 'selection':[('set', 'Set'), ('remove', 'Remove')]} - all_fields[field.name] = {'type':field.ttype, 'string': field.field_description, 'size': field.size or 256} - etree.SubElement(xml_group, 'field', {'name': "selection__" + field.name, 'colspan':'2', 'colspan':'2'}) - etree.SubElement(xml_group, 'field', {'name': field.name, 'nolabel':'1', 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove')]}", 'colspan':'2'}) + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [('set', 'Set'), ('remove', 'Remove')]} + all_fields[field.name] = { + 'type': field.ttype, 'string': field.field_description, + 'size': field.size or 256} + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, + 'colspan': '2', + 'colspan': '2'}) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'nolabel': '1', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove')]}"), + 'colspan': '2'}) elif field.ttype == 'selection': - all_fields["selection__" + field.name] = {'type':'selection', 'string': field_info[field.name]['string'], 'selection':[('set', 'Set'), ('remove', 'Remove')]} - etree.SubElement(xml_group, 'field', {'name': "selection__" + field.name, 'colspan':'2'}) - etree.SubElement(xml_group, 'field', {'name': field.name, 'nolabel':'1', 'colspan':'2', 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove')]}"}) - all_fields[field.name] = {'type':field.ttype, 'string': field.field_description, 'selection': field_info[field.name]['selection']} + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [('set', 'Set'), ('remove', 'Remove')]} + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, 'colspan': '2'}) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'nolabel': '1', 'colspan': '2', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove')]}")}) + all_fields[field.name] = { + 'type': field.ttype, + 'string': field.field_description, + 'selection': field_info[field.name]['selection']} else: - all_fields[field.name] = {'type':field.ttype, 'string': field.field_description} - all_fields["selection__" + field.name] = {'type':'selection', 'string': field_info[field.name]['string'], 'selection':[('set', 'Set'), ('remove', 'Remove')]} + all_fields[field.name] = { + 'type': field.ttype, 'string': field.field_description} + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [('set', 'Set'), ('remove', 'Remove')]} if field.ttype == 'text': - xml_group = etree.SubElement(xml_group, 'group', {'colspan': '6'}) - etree.SubElement(xml_group, 'separator', {'string': all_fields[field.name]['string'], 'colspan': '2'}) - etree.SubElement(xml_group, 'field', {'name': "selection__" + field.name, 'colspan': '2', 'nolabel':'1'}) - etree.SubElement(xml_group, 'field', {'name': field.name, 'colspan':'4', 'nolabel':'1', 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove')]}"}) + xml_group = etree.SubElement(xml_group, 'group', { + 'colspan': '6'}) + etree.SubElement(xml_group, 'separator', { + 'string': all_fields[field.name]['string'], + 'colspan': '2'}) + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, + 'colspan': '2', 'nolabel': '1'}) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'colspan': '4', 'nolabel': '1', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove')]}")}) else: - all_fields["selection__" + field.name] = {'type':'selection', 'string': field_info[field.name]['string'], 'selection':[('set', 'Set'), ('remove', 'Remove')]} - etree.SubElement(xml_group, 'field', {'name': "selection__" + field.name, 'colspan': '2', }) - etree.SubElement(xml_group, 'field', {'name': field.name, 'nolabel':'1', 'attrs':"{'invisible':[('selection__" + field.name + "','=','remove')]}", 'colspan': '2', }) - etree.SubElement(xml_form, 'separator', {'string' : '', 'colspan': '4'}) + all_fields["selection__" + field.name] = { + 'type': 'selection', + 'string': field_info[field.name]['string'], + 'selection': [( + 'set', 'Set'), ('remove', 'Remove')]} + etree.SubElement(xml_group, 'field', { + 'name': "selection__" + field.name, + 'colspan': '2', }) + etree.SubElement(xml_group, 'field', { + 'name': field.name, 'nolabel': '1', + 'attrs': ( + "{'invisible':[('selection__" + + field.name + "','=','remove')]}"), + 'colspan': '2', }) + etree.SubElement( + xml_form, 'separator', {'string': '', 'colspan': '4'}) xml_group3 = etree.SubElement(xml_form, 'footer', {}) - etree.SubElement(xml_group3, 'button', {'string' :'Close', 'icon': "gtk-close", 'special' :'cancel'}) - etree.SubElement(xml_group3, 'button', {'string' :'Apply', 'icon': "gtk-execute", 'type' :'object', 'name':"action_apply"}) + etree.SubElement(xml_group3, 'button', { + 'string': 'Close', 'icon': "gtk-close", 'special': 'cancel'}) + etree.SubElement(xml_group3, 'button', { + 'string': 'Apply', 'icon': "gtk-execute", + 'type': 'object', 'name': "action_apply"}) root = xml_form.getroottree() result['arch'] = etree.tostring(root) result['fields'] = all_fields @@ -102,7 +188,7 @@ class mass_editing_wizard(orm.TransientModel): if context.get('active_model') and context.get('active_ids'): model_obj = self.pool.get(context.get('active_model')) dict = {} - for key , val in vals.items(): + for key, val in vals.items(): if key.startswith('selection__'): split_key = key.split('__', 1)[1] if val == 'set': @@ -110,19 +196,22 @@ class mass_editing_wizard(orm.TransientModel): elif val == 'remove': dict.update({split_key: False}) elif val == 'remove_m2m': - dict.update({split_key: [(3, id) for id in vals.get(split_key, False)[0][2]]}) + dict.update({split_key: [ + (3, id) for id in vals.get( + split_key, False)[0][2]]}) elif val == 'add': m2m_list = [] for m2m_id in vals.get(split_key, False)[0][2]: m2m_list.append((4, m2m_id)) dict.update({split_key: m2m_list}) if dict: - model_obj.write(cr, uid, context.get('active_ids'), dict, context) + model_obj.write( + cr, uid, context.get('active_ids'), dict, context) result = super(mass_editing_wizard, self).create(cr, uid, {}, context) return result def action_apply(self, cr, uid, ids, context=None): - return {'type': 'ir.actions.act_window_close'} + return {'type': 'ir.actions.act_window_close'} mass_editing_wizard() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: