Browse Source

[ADD] new module 'mass_sorting' to allow user to mass sort lines in any models; (#345)

pull/706/head
Sylvain LE GAL 8 years ago
parent
commit
d8bba4924e
  1. 2
      mass_sorting/__init__.py
  2. 44
      mass_sorting/__openerp__.py
  3. 179
      mass_sorting/i18n/fr.po
  4. 5
      mass_sorting/models/__init__.py
  5. 144
      mass_sorting/models/mass_sort_config.py
  6. 38
      mass_sorting/models/mass_sort_config_line.py
  7. 114
      mass_sorting/models/mass_sort_wizard.py
  8. 25
      mass_sorting/models/mass_sort_wizard_line.py
  9. 6
      mass_sorting/security/ir.model.access.csv
  10. BIN
      mass_sorting/static/description/1_mass_sort_config.png
  11. BIN
      mass_sorting/static/description/2_button.png
  12. BIN
      mass_sorting/static/description/3_mass_sort_wizard.png
  13. BIN
      mass_sorting/static/description/3_mass_sort_wizard_custom.png
  14. BIN
      mass_sorting/static/description/4_before.png
  15. BIN
      mass_sorting/static/description/5_after.png
  16. 17
      mass_sorting/views/action.xml
  17. 56
      mass_sorting/views/mass_sort_config_view.xml
  18. 36
      mass_sorting/views/mass_sort_wizard_view.xml
  19. 14
      mass_sorting/views/menu.xml

2
mass_sorting/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import models

44
mass_sorting/__openerp__.py

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Mass Sorting',
'version': '1.0',
'author': 'GRAP,Odoo Community Association (OCA)',
'category': 'Tools',
'website': 'http://www.grap.coop',
'license': 'AGPL-3',
"description": """
Mass Sorting
============
This module provides the functionality to sort an one2many fields in any model.
Typically, you can sort sale order line on a sale order, using any fields.
See screenshots in the description folder.
This module is highly inspired by 'mass_editing' module. (by OCA and SerpentCS)
""",
'depends': [
'base',
],
'data': [
'security/ir.model.access.csv',
'views/mass_sort_config_view.xml',
'views/mass_sort_wizard_view.xml',
'views/action.xml',
'views/menu.xml',
],
'images': [
'static/description/1_mass_sort_config.png',
'static/description/2_button.png',
'static/description/3_mass_sort_wizard.png',
'static/description/3_mass_sort_wizard_custom.png',
'static/description/4_before.png',
'static/description/5_after.png',
],
}

179
mass_sorting/i18n/fr.po

@ -0,0 +1,179 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * mass_sorting
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-02-08 09:48+0000\n"
"PO-Revision-Date: 2016-02-08 09:48+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: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_config.py:95
#, python-format
msgid "%s (copy)"
msgstr "%s (copie)"
#. module: mass_sorting
#: view:mass.sort.config:0
msgid "Add sidebar button"
msgstr "Ajouter un bouton"
#. module: mass_sorting
#: field:mass.sort.config,allow_custom_setting:0
#: field:mass.sort.wizard,allow_custom_setting:0
msgid "Allow Custom Setting"
msgstr "Autoriser un paramétrage personnalisé"
#. module: mass_sorting
#: view:mass.sort.wizard:0
msgid "Cancel"
msgstr "Annuler"
#. module: mass_sorting
#: view:mass.sort.wizard:0
msgid "Confirm"
msgstr "Confirmer"
#. module: mass_sorting
#: field:mass.sort.wizard,description:0
msgid "Description"
msgstr "Description"
#. module: mass_sorting
#: view:mass.sort.config:0
msgid "Display a button in the sidebar of related model to open a wizard"
msgstr "Afficher un bouton dans la barre de menu du modèle pour ouvrir un assistant"
#. module: mass_sorting
#: field:mass.sort.config.line,field_id:0
#: field:mass.sort.wizard.line,field_id:0
msgid "Field"
msgstr "Champ"
#. module: mass_sorting
#: field:mass.sort.config,one2many_field_id:0
msgid "Field to Sort"
msgstr "Champ à trier"
#. module: mass_sorting
#: help:mass.sort.config,allow_custom_setting:0
msgid "If checked, any user could have the possibility to change fields, and use others."
msgstr "Si la case est cochée, chaque utilisateur aura la possibilité de changer les champs et d'en utiliser d'autres."
#. module: mass_sorting
#: field:mass.sort.config.line,desc:0
#: field:mass.sort.wizard.line,desc:0
msgid "Inverse Order"
msgstr "Ordre inverse"
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_config.py:108
#, python-format
msgid "Mass Sort (%s)"
msgstr "Tri en masse (%s)"
#. module: mass_sorting
#: model:ir.actions.act_window,name:mass_sorting.action_mass_sort_config
#: model:ir.ui.menu,name:mass_sorting.menu_mass_sort_config
#: view:mass.sort.config:0
#: view:mass.sort.wizard:0
msgid "Mass Sorting"
msgstr "Tri en masse"
#. module: mass_sorting
#: field:mass.sort.config,model_id:0
msgid "Model"
msgstr "Modèle"
#. module: mass_sorting
#: field:mass.sort.config,one2many_model:0
#: field:mass.sort.wizard,one2many_model:0
msgid "Model Name of the Field to Sort"
msgstr "Nom du modèle du champ à trier"
#. module: mass_sorting
#: field:mass.sort.config,name:0
msgid "Name"
msgstr "Nom"
#. module: mass_sorting
#: constraint:mass.sort.wizard:0
msgid "Please Select at least ona Sorting Criteria."
msgstr "Veuillez renseigner au moins un critère de tri."
#. module: mass_sorting
#: model:mass.sort.config,name:mass_sorting.mass_sort_config
msgid "Recursive Demo Configuration"
msgstr "Configuration de démo (récursive)"
#. module: mass_sorting
#: view:mass.sort.config:0
msgid "Remove sidebar button"
msgstr "Retirer le bouton"
#. module: mass_sorting
#: field:mass.sort.config.line,sequence:0
#: field:mass.sort.wizard.line,sequence:0
msgid "Sequence"
msgstr "Séquence"
#. module: mass_sorting
#: field:mass.sort.config,ref_ir_act_window:0
msgid "Sidebar Action"
msgstr "Action"
#. module: mass_sorting
#: field:mass.sort.config,ref_ir_value:0
msgid "Sidebar Button"
msgstr "Bouton"
#. module: mass_sorting
#: field:mass.sort.config,line_ids:0
#: view:mass.sort.wizard:0
#: field:mass.sort.wizard,line_ids:0
msgid "Sorting Criterias"
msgstr "Critères de tri"
#. module: mass_sorting
#: constraint:mass.sort.config:0
msgid "The selected Field to Sort doesn't belong to the selected model."
msgstr "Le champ sélectionné pour le tri n'appartient pas au modèle sélectionné."
#. module: mass_sorting
#: constraint:mass.sort.config:0
msgid "The selected Field to Sort doesn't not have 'sequence' field defined."
msgstr "Le champ sélectionné pour le tri n'a pas de champ séquence défini."
#. module: mass_sorting
#: constraint:mass.sort.config.line:0
msgid "The selected criteria must belong to the parent model."
msgstr "Le critère sélectionné doit appartenir au modèle parent."
#. module: mass_sorting
#: field:mass.sort.config.line,config_id:0
#: field:mass.sort.wizard.line,wizard_id:0
msgid "Wizard"
msgstr "Assistant"
#. module: mass_sorting
#: constraint:mass.sort.config:0
msgid "You have to define field(s) in 'Sorting Criterias' if you uncheck 'Allow Custom Setting'."
msgstr "You have to define field(s) in 'Sorting Criterias' if you uncheck 'Allow Custom Setting'."
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_wizard.py:44
#, python-format
msgid "You will sort the field '%(field)s' for %(qty)d %(model)s(s). \n"
"\n"
"The sorting will be done by %(field_list)s."
msgstr "Vous allez trier le champ '%(field)s' pour %(qty)d %(model)s(s). \n"
"\n"
"Le tri sera réalisé par %(field_list)s."

5
mass_sorting/models/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from . import mass_sort_config
from . import mass_sort_config_line
from . import mass_sort_wizard
from . import mass_sort_wizard_line

144
mass_sorting/models/mass_sort_config.py

@ -0,0 +1,144 @@
# -*- coding: utf-8 -*-
# Copyright (C):
# * 2012-Today Serpent Consulting Services (<http://www.serpentcs.com>)
# * 2016-Today GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.osv import fields
from openerp.osv.orm import Model
from openerp.tools.translate import _
class MassSortConfig(Model):
_name = 'mass.sort.config'
# Column Section
_columns = {
'name': fields.char(
string='Name', translate=True, required=True),
'model_id': fields.many2one(
'ir.model', string='Model', required=True),
'allow_custom_setting': fields.boolean(
string='Allow Custom Setting', help="If checked, any user could"
" have the possibility to change fields, and use others."),
'one2many_field_id': fields.many2one(
'ir.model.fields', string='Field to Sort', required=True,
domain="[('model_id', '=', model_id),"
"('ttype', '=', 'one2many')]"),
'one2many_model': fields.related(
'one2many_field_id', 'relation', type='char',
string='Model Name of the Field to Sort', readonly=True),
'ref_ir_act_window': fields.many2one(
'ir.actions.act_window', 'Sidebar Action', readonly=True),
'ref_ir_value': fields.many2one(
'ir.values', 'Sidebar Button', readonly=True),
'line_ids': fields.one2many(
'mass.sort.config.line', 'config_id', 'Sorting Criterias'),
}
_defaults = {
'allow_custom_setting': True,
}
# Constraint Section
def _check_model_sequence(self, cr, uid, ids, context=None):
field_obj = self.pool['ir.model.fields']
for config in self.browse(cr, uid, ids, context=context):
if len(field_obj.search(cr, uid, [
('model', '=', config.one2many_field_id.relation),
('name', '=', 'sequence')], context=context)) != 1:
return False
return True
def _check_model_field(self, cr, uid, ids, context=None):
for config in self.browse(cr, uid, ids, context=context):
if config.model_id.id != config.one2many_field_id.model_id.id:
return False
return True
def _check_line_ids(self, cr, uid, ids, context=None):
for config in self.browse(cr, uid, ids, context=context):
if not config.allow_custom_setting and len(config.line_ids) == 0:
return False
return True
_constraints = [
(_check_model_sequence, "The selected Field to Sort doesn't not have"
" 'sequence' field defined.", ['one2many_field_id']),
(_check_model_field, "The selected Field to Sort doesn't belong to the"
" selected model.", ['model_id', 'one2many_field_id']),
(_check_line_ids, "You have to define field(s) in 'Sorting Criterias'"
" if you uncheck 'Allow Custom Setting'.",
['line_ids', 'allow_custom_setting']),
]
# View Section
def on_change_one2many_field_id(
self, cr, uid, ids, one2many_field_id, context=None):
field_obj = self.pool['ir.model.fields']
if not one2many_field_id:
return {'value': {'one2many_model': False}}
field = field_obj.browse(cr, uid, one2many_field_id, context=context)
return {'value': {'one2many_model': field.relation}}
# Overload Section
def unlink(self, cr, uid, ids, context=None):
self.unlink_action(cr, uid, ids, context=context)
return super(MassSortConfig, self).unlink(
cr, uid, ids, context=context)
def copy(self, cr, uid, id, value=None, context=None):
value = value or {}
config = self.browse(cr, uid, id, context=context)
value.update({
'name': _('%s (copy)') % config.name,
'ref_ir_act_window': False,
'ref_ir_value': False})
return super(MassSortConfig, self).copy(
cr, uid, id, value, context=context)
# Custom Section
def create_action(self, cr, uid, ids, context=None):
vals = {}
action_obj = self.pool['ir.actions.act_window']
values_obj = self.pool['ir.values']
for config in self.browse(cr, uid, ids, context=context):
src_obj = config.model_id.model
button_name = _('Mass Sort (%s)') % config.name
vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
'name': button_name,
'type': 'ir.actions.act_window',
'res_model': 'mass.sort.wizard',
'src_model': src_obj,
'view_type': 'form',
'context': "{'mass_sort_config_id' : %d}" % (config.id),
'view_mode': 'form,tree',
'target': 'new',
'auto_refresh': 1,
}, context)
vals['ref_ir_value'] = values_obj.create(cr, uid, {
'name': button_name,
'model': src_obj,
'key2': 'client_action_multi',
'value': (
"ir.actions.act_window,%s" % 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):
action_obj = self.pool['ir.actions.act_window']
values_obj = self.pool['ir.values']
for config in self.browse(cr, uid, ids, context=context):
if config.ref_ir_act_window:
action_obj.unlink(
cr, uid, config.ref_ir_act_window.id, context=context)
if config.ref_ir_value:
values_obj.unlink(
cr, uid, config.ref_ir_value.id, context=context)
return True

38
mass_sorting/models/mass_sort_config_line.py

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.osv import fields
from openerp.osv.orm import Model
class MassSortConfigLine(Model):
_name = 'mass.sort.config.line'
_order = 'config_id, sequence, id'
_columns = {
'sequence': fields.integer('Sequence', required=True),
'config_id': fields.many2one(
'mass.sort.config', string='Wizard'),
'field_id': fields.many2one(
'ir.model.fields', string='Field', required=True, domain="["
"('model', '=', parent.one2many_model)]"),
'desc': fields.boolean('Inverse Order'),
}
_defaults = {
'sequence': 1,
}
# Constraint Section
def _check_field_id(self, cr, uid, ids, context=None):
for line in self.browse(cr, uid, ids, context=context):
if line.field_id.model != line.config_id.one2many_model:
return False
return True
_constraints = [
(_check_field_id, "The selected criteria must belong to the parent"
" model.", ['config_id', 'field_id']),
]

114
mass_sorting/models/mass_sort_wizard.py

@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.osv import fields
from openerp.osv.orm import TransientModel
from openerp.tools.translate import _
class MassSortWizard(TransientModel):
_name = 'mass.sort.wizard'
_columns = {
'description': fields.text(
string='Description', readonly=True),
'allow_custom_setting': fields.boolean(
string='Allow Custom Setting', readonly=True),
'one2many_model': fields.char(
string='Model Name of the Field to Sort', readonly=True),
'line_ids': fields.one2many(
'mass.sort.wizard.line', 'wizard_id', 'Sorting Criterias'),
}
# Constraint Section
def _check_line_ids(self, cr, uid, ids, context=None):
for wizard in self.browse(cr, uid, ids, context=context):
if not len(wizard.line_ids):
return False
return True
_constraints = [(
_check_line_ids, "Please Select at least ona Sorting Criteria.",
['line_ids']),
]
# Default Section
def _default_description(self, cr, uid, context=None):
config_obj = self.pool['mass.sort.config']
config = config_obj.browse(
cr, uid, context.get('mass_sort_config_id'), context=context)
return _(
"You will sort the field '%(field)s' for %(qty)d %(model)s(s)"
". \n\nThe sorting will be done by %(field_list)s.") % ({
'field': config.one2many_field_id.field_description,
'qty': len(context.get('active_ids', False)),
'model': config.model_id.name,
'field_list': ', '.join(
[x.field_id.field_description for x in config.line_ids])
})
def _default_allow_custom_setting(self, cr, uid, context=None):
config_obj = self.pool['mass.sort.config']
return config_obj.browse(
cr, uid, context.get('mass_sort_config_id'), context=context)\
.allow_custom_setting
def _default_one2many_model(self, cr, uid, context=None):
config_obj = self.pool['mass.sort.config']
return config_obj.browse(
cr, uid, context.get('mass_sort_config_id'), context=context)\
.one2many_model
def _default_line_ids(self, cr, uid, context=None):
config_obj = self.pool['mass.sort.config']
res = []
config = config_obj.browse(
cr, uid, context.get('mass_sort_config_id'), context=context)
for line in config.line_ids:
res.append((0, 0, {
'sequence': line.sequence,
'field_id': line.field_id.id,
'desc': line.desc}))
return res
_defaults = {
'description': _default_description,
'allow_custom_setting': _default_allow_custom_setting,
'one2many_model': _default_one2many_model,
'line_ids': _default_line_ids,
}
# Action Section
def button_apply(self, cr, uid, ids, context=None):
config_obj = self.pool['mass.sort.config']
model_obj = self.pool[context.get('active_model')]
active_ids = context.get('active_ids')
config = config_obj.browse(
cr, uid, context.get('mass_sort_config_id'), context=context)
wizard = self.browse(cr, uid, ids[0], context=context)
one2many_obj = self.pool[config.one2many_field_id.relation]
parent_field = config.one2many_field_id.relation_field
order_list = []
for line in wizard.line_ids:
order_list.append(
line.desc and
'%s desc' % line.field_id.name or line.field_id.name)
order = ', '.join(order_list)
for item in model_obj.browse(cr, uid, active_ids, context=context):
# DB Query sort by the correct order
line_ids = one2many_obj.search(
cr, uid, [(parent_field, '=', item.id)], order=order,
context=context)
# Write new sequence to sort lines
sequence = 1
for id in line_ids:
one2many_obj.write(
cr, uid, [id], {'sequence': sequence}, context=context)
sequence += 1
return {'type': 'ir.actions.act_window_close'}

25
mass_sorting/models/mass_sort_wizard_line.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.osv import fields
from openerp.osv.orm import TransientModel
class TransientModelLine(TransientModel):
_name = 'mass.sort.wizard.line'
_columns = {
'sequence': fields.integer('Sequence', required=True),
'wizard_id': fields.many2one(
'mass.sort.wizard', string='Wizard'),
'field_id': fields.many2one(
'ir.model.fields', string='Field', required=True, domain="["
"('model', '=', parent.one2many_model)]"),
'desc': fields.boolean('Inverse Order'),
}
_defaults = {
'sequence': 1,
}

6
mass_sorting/security/ir.model.access.csv

@ -0,0 +1,6 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_mass_sort_config_user","Mass Sorting Configurations - User","model_mass_sort_config","base.group_user",1,0,0,0
"access_mass_sort_config_manager","Mass Sorting Configurations - Manager","model_mass_sort_config","base.group_system",1,1,1,1
"access_mass_sort_config_line_user","Mass Sorting Configuration Lines - User","model_mass_sort_config_line","base.group_user",1,0,0,0
"access_mass_sort_config_line_manager","Mass Sorting Configuration Lines - Manager","model_mass_sort_config_line","base.group_system",1,1,1,1

BIN
mass_sorting/static/description/1_mass_sort_config.png

After

Width: 770  |  Height: 283  |  Size: 25 KiB

BIN
mass_sorting/static/description/2_button.png

After

Width: 609  |  Height: 153  |  Size: 17 KiB

BIN
mass_sorting/static/description/3_mass_sort_wizard.png

After

Width: 443  |  Height: 189  |  Size: 19 KiB

BIN
mass_sorting/static/description/3_mass_sort_wizard_custom.png

After

Width: 718  |  Height: 251  |  Size: 15 KiB

BIN
mass_sorting/static/description/4_before.png

After

Width: 769  |  Height: 424  |  Size: 37 KiB

BIN
mass_sorting/static/description/5_after.png

After

Width: 771  |  Height: 420  |  Size: 37 KiB

17
mass_sorting/views/action.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2016-Today GRAP (http://www.grap.coop)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<openerp><data>
<record id="action_mass_sort_config" model="ir.actions.act_window">
<field name="name">Mass Sorting</field>
<field name="res_model">mass.sort.config</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
</data></openerp>

56
mass_sorting/views/mass_sort_config_view.xml

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2016-Today GRAP (http://www.grap.coop)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<openerp><data>
<record id="view_mass_sort_config_form" model="ir.ui.view">
<field name="model">mass.sort.config</field>
<field name="arch" type="xml">
<form string="Mass Sorting" version="7.0">
<sheet>
<div class="oe_title">
<div class="oe_edit_only"><label for="name"/></div>
<h1><field name="name"/></h1>
</div>
<group col="4">
<field name="model_id"/>
<field name="one2many_field_id" on_change="on_change_one2many_field_id(one2many_field_id)"/>
<field name="ref_ir_act_window" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"/>
<field name="ref_ir_value" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"/>
<button name="create_action" string="Add sidebar button" type="object" icon="gtk-execute"
colspan="2" attrs="{'invisible':[('ref_ir_act_window','!=',False)]}"
help="Display a button in the sidebar of related model to open a wizard"/>
<button name="unlink_action" string="Remove sidebar button" type="object" icon="gtk-delete"
attrs="{'invisible':[('ref_ir_act_window','=',False)]}" colspan="2" />
<field name="allow_custom_setting"/>
</group>
<group>
<field name="line_ids" colspan="4" nolabel="1">
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="field_id"/>
<field name="desc"/>
</tree>
</field>
<field name="one2many_model" invisible="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_mass_sort_config_tree" model="ir.ui.view">
<field name="model">mass.sort.config</field>
<field name="arch" type="xml">
<tree string="Mass Sorting">
<field name="name"/>
<field name="model_id"/>
</tree>
</field>
</record>
</data></openerp>

36
mass_sorting/views/mass_sort_wizard_view.xml

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2016-Today GRAP (http://www.grap.coop)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<openerp><data>
<record id="view_mass_sort_wizard_form" model="ir.ui.view">
<field name="model">mass.sort.wizard</field>
<field name="arch" type="xml">
<form string="Mass Sorting" version="7.0">
<group attrs="{'invisible': [('allow_custom_setting', '=', True)]}">
<field name="description" nolabel="1"/>
</group>
<group col="4" string="Sorting Criterias" attrs="{'invisible': [('allow_custom_setting', '=', False)]}">
<field name="line_ids" colspan="4" nolabel="1" >
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="field_id"/>
<field name="desc"/>
</tree>
</field>
</group>
<field name="allow_custom_setting" invisible="1"/>
<field name="one2many_model" invisible="1"/>
<footer>
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button name="button_apply" type="object" string="Confirm" class="oe_highlight"/>
</footer>
</form>
</field>
</record>
</data></openerp>

14
mass_sorting/views/menu.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2016-Today GRAP (http://www.grap.coop)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<openerp><data>
<menuitem id="menu_mass_sort_config"
action="action_mass_sort_config"
parent="base.menu_config" sequence="7"/>
</data></openerp>
Loading…
Cancel
Save