304 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
| # -*- coding: utf-8 -*-
 | |
| # © 2016 Serpent Consulting Services Pvt. Ltd. (support@serpentcs.com)
 | |
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 | |
| 
 | |
| from lxml import etree
 | |
| 
 | |
| import odoo.tools as tools
 | |
| from odoo import api, models
 | |
| 
 | |
| 
 | |
| class MassEditingWizard(models.TransientModel):
 | |
|     _name = 'mass.editing.wizard'
 | |
| 
 | |
|     @api.model
 | |
|     def fields_view_get(self, view_id=None, view_type='form', toolbar=False,
 | |
|                         submenu=False):
 | |
|         result =\
 | |
|             super(MassEditingWizard, self).fields_view_get(view_id=view_id,
 | |
|                                                            view_type=view_type,
 | |
|                                                            toolbar=toolbar,
 | |
|                                                            submenu=submenu)
 | |
|         context = self._context
 | |
|         if context.get('mass_editing_object'):
 | |
|             mass_obj = self.env['mass.object']
 | |
|             editing_data = mass_obj.browse(context.get('mass_editing_object'))
 | |
|             all_fields = {}
 | |
|             xml_form = etree.Element('form', {
 | |
|                 'string': tools.ustr(editing_data.name)
 | |
|             })
 | |
|             xml_group = etree.SubElement(xml_form, 'group', {
 | |
|                 'colspan': '6',
 | |
|                 'col': '6',
 | |
|             })
 | |
|             etree.SubElement(xml_group, 'label', {
 | |
|                 'string': '',
 | |
|                 'colspan': '2',
 | |
|             })
 | |
|             xml_group = etree.SubElement(xml_form, 'group', {
 | |
|                 'colspan': '6',
 | |
|                 'col': '6',
 | |
|             })
 | |
|             model_obj = self.env[context.get('active_model')]
 | |
|             field_info = model_obj.fields_get()
 | |
|             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': '6',
 | |
|                         'col': '6',
 | |
|                     })
 | |
|                     etree.SubElement(xml_group, 'separator', {
 | |
|                         'string': field_info[field.name]['string'],
 | |
|                         'colspan': '6',
 | |
|                     })
 | |
|                     etree.SubElement(xml_group, 'field', {
 | |
|                         'name': "selection__" + field.name,
 | |
|                         'colspan': '6',
 | |
|                         'nolabel': '1'
 | |
|                     })
 | |
|                     etree.SubElement(xml_group, 'field', {
 | |
|                         'name': field.name,
 | |
|                         'colspan': '6',
 | |
|                         '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': '4',
 | |
|                     })
 | |
|                     etree.SubElement(xml_group, 'field', {
 | |
|                         'name': field.name,
 | |
|                         'colspan': '6',
 | |
|                         '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': '4',
 | |
|                         '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',
 | |
|                     })
 | |
|                     etree.SubElement(xml_group, 'field', {
 | |
|                         'name': field.name,
 | |
|                         'nolabel': '1',
 | |
|                         'attrs': ("{'invisible':[('selection__" +
 | |
|                                   field.name + "','=','remove')]}"),
 | |
|                         'colspan': '4',
 | |
|                     })
 | |
|                 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': '4',
 | |
|                         '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')]
 | |
|                     }
 | |
|                     if field.ttype == 'text':
 | |
|                         xml_group = etree.SubElement(xml_group, 'group', {
 | |
|                             'colspan': '6',
 | |
|                             'col': '6',
 | |
|                         })
 | |
|                         etree.SubElement(xml_group, 'separator', {
 | |
|                             'string': all_fields[field.name]['string'],
 | |
|                             'colspan': '6',
 | |
|                         })
 | |
|                         etree.SubElement(xml_group, 'field', {
 | |
|                             'name': "selection__" + field.name,
 | |
|                             'colspan': '6',
 | |
|                             'nolabel': '1',
 | |
|                         })
 | |
|                         etree.SubElement(xml_group, 'field', {
 | |
|                             'name': field.name,
 | |
|                             'colspan': '6',
 | |
|                             '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': '4',
 | |
|                         })
 | |
|             # Patch fields with required extra data
 | |
|             for field in all_fields.values():
 | |
|                 field.setdefault("views", {})
 | |
|             etree.SubElement(xml_form, 'separator', {
 | |
|                 'string': '',
 | |
|                 'colspan': '6',
 | |
|                 'col': '6',
 | |
|             })
 | |
|             xml_group3 = etree.SubElement(xml_form, 'footer', {})
 | |
|             etree.SubElement(xml_group3, 'button', {
 | |
|                 'string': 'Apply',
 | |
|                 'class': 'btn-primary',
 | |
|                 'type': 'object',
 | |
|                 'name': 'action_apply',
 | |
|             })
 | |
|             etree.SubElement(xml_group3, 'button', {
 | |
|                 'string': 'Close',
 | |
|                 'class': 'btn-default',
 | |
|                 'special': 'cancel',
 | |
|             })
 | |
|             root = xml_form.getroottree()
 | |
|             result['arch'] = etree.tostring(root)
 | |
|             result['fields'] = all_fields
 | |
|         return result
 | |
| 
 | |
|     @api.model
 | |
|     def create(self, vals):
 | |
|         if (self._context.get('active_model') and
 | |
|                 self._context.get('active_ids')):
 | |
|             model_obj = self.env[self._context.get('active_model')]
 | |
|             model_field_obj = self.env['ir.model.fields']
 | |
|             translation_obj = self.env['ir.translation']
 | |
| 
 | |
|             values = {}
 | |
|             for key, val in vals.items():
 | |
|                 if key.startswith('selection_'):
 | |
|                     split_key = key.split('__', 1)[1]
 | |
|                     if val == 'set':
 | |
|                         values.update({split_key: vals.get(split_key, False)})
 | |
|                     elif val == 'remove':
 | |
|                         values.update({split_key: False})
 | |
| 
 | |
|                         # If field to remove is translatable,
 | |
|                         # its translations have to be removed
 | |
|                         model_field = model_field_obj.search([
 | |
|                             ('model', '=', self._context.get('active_model')),
 | |
|                             ('name', '=', split_key)])
 | |
|                         if model_field and model_field.translate:
 | |
|                             translation_ids = translation_obj.search([
 | |
|                                 ('res_id', 'in', self._context.get(
 | |
|                                     'active_ids')),
 | |
|                                 ('type', '=', 'model'),
 | |
|                                 ('name', '=', u"{0},{1}".format(
 | |
|                                     self._context.get('active_model'),
 | |
|                                     split_key))])
 | |
|                             translation_ids.unlink()
 | |
| 
 | |
|                     elif val == 'remove_m2m':
 | |
|                         m2m_list = []
 | |
|                         if vals.get(split_key):
 | |
|                             for m2m_id in vals.get(split_key)[0][2]:
 | |
|                                 m2m_list.append((3, m2m_id))
 | |
|                         if m2m_list:
 | |
|                             values.update({split_key: m2m_list})
 | |
|                         else:
 | |
|                             values.update({split_key: [(5, 0, [])]})
 | |
|                     elif val == 'add':
 | |
|                         m2m_list = []
 | |
|                         for m2m_id in vals.get(split_key, False)[0][2]:
 | |
|                             m2m_list.append((4, m2m_id))
 | |
|                         values.update({split_key: m2m_list})
 | |
|             if values:
 | |
|                 model_obj.browse(self._context.get('active_ids')).write(values)
 | |
|         return super(MassEditingWizard, self).create({})
 | |
| 
 | |
|     @api.multi
 | |
|     def action_apply(self):
 | |
|         return {'type': 'ir.actions.act_window_close'}
 | |
| 
 | |
|     def read(self, fields, load='_classic_read'):
 | |
|         """ Without this call, dynamic fields build by fields_view_get()
 | |
|             generate a log warning, i.e.:
 | |
|             odoo.models:mass.editing.wizard.read() with unknown field 'myfield'
 | |
|             odoo.models:mass.editing.wizard.read()
 | |
|                 with unknown field 'selection__myfield'
 | |
|         """
 | |
|         real_fields = fields
 | |
|         if fields:
 | |
|             # We remove fields which are not in _fields
 | |
|             real_fields = [x for x in fields if x in self._fields]
 | |
|         result = super(MassEditingWizard, self).read(real_fields, load=load)
 | |
|         # adding fields to result
 | |
|         [result[0].update({x: False}) for x in fields if x not in real_fields]
 | |
|         return result
 |