Browse Source

Merge pull request #706 from grap/10.0_PORT_mass_sorting

10.0 port mass sorting
pull/762/head
Sylvain LE GAL 8 years ago
committed by GitHub
parent
commit
83ee5f322d
  1. 108
      mass_sorting/README.rst
  2. 2
      mass_sorting/__init__.py
  3. 38
      mass_sorting/__manifest__.py
  4. 12
      mass_sorting/demo/function.xml
  5. 16
      mass_sorting/demo/mass_sort_config.xml
  6. 20
      mass_sorting/demo/mass_sort_config_line.xml
  7. 268
      mass_sorting/i18n/fr.po
  8. 5
      mass_sorting/models/__init__.py
  9. 118
      mass_sorting/models/mass_sort_config.py
  10. 32
      mass_sorting/models/mass_sort_config_line.py
  11. 100
      mass_sorting/models/mass_sort_wizard.py
  12. 21
      mass_sorting/models/mass_sort_wizard_line.py
  13. 6
      mass_sorting/security/ir.model.access.csv
  14. BIN
      mass_sorting/static/description/1_mass_sort_config.png
  15. BIN
      mass_sorting/static/description/2_button.png
  16. BIN
      mass_sorting/static/description/3_mass_sort_wizard.png
  17. BIN
      mass_sorting/static/description/3_mass_sort_wizard_custom.png
  18. BIN
      mass_sorting/static/description/4_before.png
  19. BIN
      mass_sorting/static/description/5_after.png
  20. BIN
      mass_sorting/static/description/icon.png
  21. 17
      mass_sorting/views/action.xml
  22. 14
      mass_sorting/views/menu.xml
  23. 68
      mass_sorting/views/view_mass_sort_config.xml
  24. 37
      mass_sorting/views/view_mass_sort_wizard.xml

108
mass_sorting/README.rst

@ -0,0 +1,108 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
============
Mass Sorting
============
This module extends the functionality of odoo to allow users to sort an
one2many fields in any model.
Typically, you can sort sale order lines on a sale order, using any fields.
Configuration
=============
To configure this module, you need to:
* Go to Settings / Technical / Mass Sorting
* Create a new item and define:
* a name
* the model you want to sort
* the field of the model, you want to sort
* The lists of the fields, by which the sort will be done
.. image:: /mass_sorting/static/description/1_mass_sort_config.png
:width: 70%
(You can allow users to change or not the values, by checking 'Allow custom Setting')
* Click on the button 'Add sidebar button'
Usage
=====
* Go to the form view of the given model, in this sample, a sale order. (or select items in a tree view)
.. image:: /mass_sorting/static/description/4_before.png
* click on the button 'Action' and then select the according action.
If you just created your action, please refresh the page
to see the new action appear.
.. image:: /mass_sorting/static/description/2_button.png
* On the pop up (depending of the configuration), change the fields and the order
.. image:: /mass_sorting/static/description/3_mass_sort_wizard_custom.png
(If changing configuration is not allowed, a simple message is displayed.)
.. image:: /mass_sorting/static/description/3_mass_sort_wizard.png
* The items will be reordered.
.. image:: /mass_sorting/static/description/5_after.png
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/149/10.0
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/server-tools/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Sylvain LE GAL (https://twitter.com/legalsylvain)
Funders
-------
The development of this module has been financially supported by:
* GRAP (http://www.grap.coop)
This module is highly inspired by 'mass_editing' module. (by OCA and SerpentCS)
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://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 https://odoo-community.org.

2
mass_sorting/__init__.py

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

38
mass_sorting/__manifest__.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).
{
'name': 'Mass Sorting',
'version': "10.0.1.0.0",
'author': 'GRAP,Odoo Community Association (OCA)',
'summary': 'Sort any models by any fields list',
'category': 'Tools',
'website': 'http://www.grap.coop',
'license': 'AGPL-3',
'depends': [
'base',
],
'data': [
'security/ir.model.access.csv',
'views/view_mass_sort_config.xml',
'views/view_mass_sort_wizard.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',
],
'demo': [
'demo/mass_sort_config.xml',
'demo/mass_sort_config_line.xml',
'demo/function.xml',
],
}

12
mass_sorting/demo/function.xml

@ -0,0 +1,12 @@
<?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).
-->
<odoo noupdate="1">
<function model="mass.sort.config" name="create_action" eval="[ref('mass_sort_config_demo')]"/>
</odoo>

16
mass_sorting/demo/mass_sort_config.xml

@ -0,0 +1,16 @@
<?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).
-->
<odoo>
<record id="mass_sort_config_demo" model="mass.sort.config">
<field name="name">Self Mass Sort Demo</field>
<field name="model_id" ref="mass_sorting.model_mass_sort_config"/>
<field name="one2many_field_id" ref="mass_sorting.field_mass_sort_config_line_ids"/>
</record>
</odoo>

20
mass_sorting/demo/mass_sort_config_line.xml

@ -0,0 +1,20 @@
<?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).
-->
<odoo>
<record id="mass_sort_config_demo_line_1" model="mass.sort.config.line">
<field name="config_id" ref="mass_sort_config_demo"/>
<field name="field_id" ref="mass_sorting.field_mass_sort_config_line_field_id"/>
</record>
<record id="mass_sort_config_demo_line_2" model="mass.sort.config.line">
<field name="config_id" ref="mass_sort_config_demo"/>
<field name="field_id" ref="mass_sorting.field_mass_sort_config_line_desc"/>
</record>
</odoo>

268
mass_sorting/i18n/fr.po

@ -0,0 +1,268 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * mass_sorting
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-19 16:46+0000\n"
"PO-Revision-Date: 2017-01-19 16:46+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:84
#, python-format
msgid "%s (copy)"
msgstr "%s (copie)"
#. module: mass_sorting
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_config_form
msgid "Add sidebar button"
msgstr "Ajouter un bouton"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_allow_custom_setting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_allow_custom_setting
msgid "Allow Custom Setting"
msgstr "Autoriser un paramétrage personnalisé"
#. module: mass_sorting
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_wizard_form
msgid "Cancel"
msgstr "Annuler"
#. module: mass_sorting
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_wizard_form
msgid "Confirm"
msgstr "Confirmer"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_create_uid
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_create_uid
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_create_uid
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_create_uid
msgid "Created by"
msgstr "Créé par"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_create_date
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_create_date
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_create_date
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_create_date
msgid "Created on"
msgstr "Créé le"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_description
msgid "Description"
msgstr "Description"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_display_name
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_display_name
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_display_name
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: mass_sorting
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_config_form
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
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_field_id
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_field_id
msgid "Field"
msgstr "Champ"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_one2many_field_id
msgid "Field to Sort"
msgstr "Champ à trier"
#. module: mass_sorting
#: model:ir.model.fields,help:mass_sorting.field_mass_sort_config_one2many_model
#: model:ir.model.fields,help:mass_sorting.field_mass_sort_wizard_one2many_model
msgid "For relationship fields, the technical name of the target model"
msgstr "Pour les champs de relation, le nom technique du modèle cible"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_id
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_id
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_id
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_id
msgid "ID"
msgstr "ID"
#. module: mass_sorting
#: model:ir.model.fields,help:mass_sorting.field_mass_sort_config_allow_custom_setting
#: model:ir.model.fields,help:mass_sorting.field_mass_sort_wizard_allow_custom_setting
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
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_desc
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_desc
msgid "Inverse Order"
msgstr "Ordre inverse"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config___last_update
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line___last_update
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard___last_update
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line___last_update
msgid "Last Modified on"
msgstr "Dernière Modification le"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_write_uid
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_write_uid
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_write_uid
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_write_date
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_write_date
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_write_date
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_config.py:93
#, 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
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_config_tree
msgid "Mass Sorting"
msgstr "Tri en masse"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_model_id
msgid "Model"
msgstr "Modèle"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_one2many_model
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_one2many_model
msgid "Model Name of the Field to Sort"
msgstr "Nom du modèle du champ à trier"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_name
msgid "Name"
msgstr "Nom"
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_wizard.py:71
#, python-format
msgid "Please Select at least one Sorting Criteria."
msgstr "Veuillez renseigner au moins un critère de tri."
#. module: mass_sorting
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_config_form
msgid "Remove sidebar button"
msgstr "Retirer le bouton"
#. module: mass_sorting
#: model:mass.sort.config,name:mass_sorting.mass_sort_config_demo
msgid "Self Mass Sort Demo"
msgstr "Self Mass Sort Demo"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_sequence
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_sequence
msgid "Sequence"
msgstr "Séquence"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_action_id
msgid "Sidebar Action"
msgstr "Action"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_value_id
msgid "Sidebar Button"
msgstr "Bouton de la barre latérale"
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_ids
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_ids
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_config_form
#: model:ir.ui.view,arch_db:mass_sorting.view_mass_sort_wizard_form
msgid "Sorting Criterias"
msgstr "Critères de tri"
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_config.py:63
#, python-format
msgid "The selected Field to Sort '%s' doesn't belong to the selected model '%s'."
msgstr "Le champ sélectionné pour le tri '%s' n'appartient pas au modèle sélectionné '%s'."
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_config.py:55
#, python-format
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
#: code:addons/mass_sorting/models/mass_sort_config_line.py:30
#, python-format
msgid "The selected criteria '%s' must belong to the model of the Field to Sort."
msgstr "Le critère sélectionné '%s' doit appartenir au modèle du champ à trier."
#. module: mass_sorting
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_config_line_config_id
#: model:ir.model.fields,field_description:mass_sorting.field_mass_sort_wizard_line_wizard_id
msgid "Wizard"
msgstr "Assistant"
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_config.py:72
#, python-format
msgid "You have to define field(s) in 'Sorting Criterias' if you uncheck 'Allow Custom Setting'."
msgstr "Vous devez définir des champs dans 'Critères de Tri', si vous décochez 'Autoriser un paramétrage personnalisé'."
#. module: mass_sorting
#: code:addons/mass_sorting/models/mass_sort_wizard.py:54
#, 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."
#. module: mass_sorting
#: model:ir.model,name:mass_sorting.model_mass_sort_config
msgid "mass.sort.config"
msgstr "mass.sort.config"
#. module: mass_sorting
#: model:ir.model,name:mass_sorting.model_mass_sort_config_line
msgid "mass.sort.config.line"
msgstr "mass.sort.config.line"
#. module: mass_sorting
#: model:ir.model,name:mass_sorting.model_mass_sort_wizard
msgid "mass.sort.wizard"
msgstr "mass.sort.wizard"
#. module: mass_sorting
#: model:ir.model,name:mass_sorting.model_mass_sort_wizard_line
msgid "mass.sort.wizard.line"
msgstr "mass.sort.wizard.line"

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

118
mass_sorting/models/mass_sort_config.py

@ -0,0 +1,118 @@
# -*- 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 odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class MassSortConfig(models.Model):
_name = 'mass.sort.config'
# Column Section
name = fields.Char(string='Name', translate=True, required=True)
model_id = fields.Many2one(
comodel_name='ir.model', string='Model', required=True)
allow_custom_setting = fields.Boolean(
string='Allow Custom Setting', default=True, help="If checked, any"
" user could have the possibility to change fields, and use others.")
one2many_field_id = fields.Many2one(
comodel_name='ir.model.fields', string='Field to Sort', required=True,
domain="[('model_id', '=', model_id),('ttype', '=', 'one2many')]")
one2many_model = fields.Char(
related='one2many_field_id.relation', readonly=True,
string='Model Name of the Field to Sort', hel="Technical field,"
"used in the model 'mass.sort.config.line'", store=True)
action_id = fields.Many2one(
comodel_name='ir.actions.act_window', string='Sidebar Action',
readonly=True, copy=False, oldname='ref_ir_act_window')
value_id = fields.Many2one(
comodel_name='ir.values', string='Sidebar Button', readonly=True,
copy=False, oldname='ref_ir_value')
line_ids = fields.One2many(
comodel_name='mass.sort.config.line', inverse_name='config_id',
string='Sorting Criterias')
# Constraint Section
@api.constrains('one2many_field_id')
def _check_model_sequence(self):
field_obj = self.env['ir.model.fields']
for config in self:
if field_obj.search_count([
('model', '=', config.one2many_field_id.relation),
('name', '=', 'sequence')]) == 0:
raise ValidationError(
_("The selected Field to Sort doesn't not have"
" 'sequence' field defined."))
@api.constrains('model_id', 'one2many_field_id')
def _check_model_field(self):
for config in self:
if config.model_id != config.one2many_field_id.model_id:
raise ValidationError(
_("The selected Field to Sort '%s' doesn't belong to the"
" selected model '%s'.") % (
config.one2many_field_id.model_id.name,
config.model_id.name))
@api.constrains('allow_custom_setting', 'line_ids')
def _check_line_ids(self):
for config in self:
if not config.allow_custom_setting and not len(config.line_ids):
raise ValidationError(_(
"You have to define field(s) in 'Sorting Criterias' if"
" you uncheck 'Allow Custom Setting'."))
# Overload Section
def unlink(self):
self.unlink_action()
return super(MassSortConfig, self).unlink()
def copy(self, default=None):
default = default or {}
default.update({
'name': _('%s (copy)') % self.name})
return super(MassSortConfig, self).copy(default=default)
# Custom Section
@api.multi
def create_action(self):
action_obj = self.env['ir.actions.act_window']
values_obj = self.env['ir.values']
for config in self:
button_name = _('Mass Sort (%s)') % config.name
config.action_id = action_obj.create({
'name': button_name,
'type': 'ir.actions.act_window',
'res_model': 'mass.sort.wizard',
'src_model': config.model_id.model,
'view_type': 'form',
'context': "{'mass_sort_config_id' : %d}" % (config.id),
'view_mode': 'form,tree',
'target': 'new',
})
config.value_id = values_obj.create({
'name': button_name,
'model': config.model_id.model,
'key2': 'client_action_multi',
'value': (
"ir.actions.act_window,%s" % config.action_id.id),
})
@api.multi
def unlink_action(self):
for config in self:
if config.action_id:
config.action_id.unlink()
if config.value_id:
config.value_id.unlink()

32
mass_sorting/models/mass_sort_config_line.py

@ -0,0 +1,32 @@
# -*- 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 odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class MassSortConfigLine(models.Model):
_name = 'mass.sort.config.line'
_order = 'config_id, sequence, id'
sequence = fields.Integer(string='Sequence', required=True, default=1)
config_id = fields.Many2one(
comodel_name='mass.sort.config', string='Wizard')
field_id = fields.Many2one(
comodel_name='ir.model.fields', string='Field', required=True,
domain="[('model', '=', parent.one2many_model)]")
desc = fields.Boolean(string='Inverse Order')
# Constraint Section
@api.constrains('field_id', 'config_id')
def _check_field_id(self):
for line in self:
if line.field_id.model != line.config_id.one2many_model:
raise ValidationError(_(
"The selected criteria '%s' must belong to the model of"
" the Field to Sort.") % (line.field_id.field_description))

100
mass_sorting/models/mass_sort_wizard.py

@ -0,0 +1,100 @@
# -*- 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 odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class MassSortWizard(models.TransientModel):
_name = 'mass.sort.wizard'
# Default Section
def _default_config_id(self):
return self._context.get('mass_sort_config_id', False)
def _default_line_ids(self):
config_obj = self.env['mass.sort.config']
line_ids = []
config = config_obj.browse(
self._context.get('mass_sort_config_id', False))
if config:
for line in config.line_ids:
line_ids.append((0, 0, {
'sequence': line.sequence,
'field_id': line.field_id.id,
'desc': line.desc}))
return line_ids
# Column Section
config_id = fields.Many2one(
comodel_name='mass.sort.config', default=_default_config_id,
required=True)
description = fields.Text(
string='Description', readonly=True, compute='_compute_description')
allow_custom_setting = fields.Boolean(
string='Allow Custom Setting', readonly=True,
related='config_id.allow_custom_setting')
one2many_model = fields.Char(
string='Model Name of the Field to Sort', readonly=True,
related='config_id.one2many_model')
line_ids = fields.One2many(
comodel_name='mass.sort.wizard.line', inverse_name='wizard_id',
string='Sorting Criterias', default=_default_line_ids)
# Compute Section
@api.depends('config_id')
def _compute_description(self):
for wizard in self:
wizard.description = _(
"You will sort the field '%(field)s' for %(qty)d %(model)s(s)"
". \n\nThe sorting will be done by %(field_list)s.") % ({
'field':
wizard.config_id.one2many_field_id.field_description,
'qty': len(self._context.get('active_ids', [])),
'model': wizard.config_id.model_id.name,
'field_list': ', '.join(
[x.field_id.field_description
for x in wizard.line_ids])
})
# Constraint Section
@api.constrains('line_ids')
def _check_line_ids(self):
for wizard in self:
if not len(wizard.line_ids):
raise ValidationError(_(
"Please Select at least one Sorting Criteria."))
# Action Section
def button_apply(self):
self.ensure_one()
wizard = self
active_ids = self._context.get('active_ids')
model_obj = self.env[wizard.config_id.model_id.model]
one2many_obj = self.env[wizard.config_id.one2many_field_id.relation]
parent_field = wizard.config_id.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(active_ids):
# DB Query sort by the correct order
lines = one2many_obj.search(
[(parent_field, '=', item.id)], order=order)
# Write new sequence to sort lines
sequence = 1
for line in lines:
line.sequence = sequence
sequence += 1

21
mass_sorting/models/mass_sort_wizard_line.py

@ -0,0 +1,21 @@
# -*- 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 odoo import fields, models
class TransientModelLine(models.TransientModel):
_name = 'mass.sort.wizard.line'
sequence = fields.Integer(string='Sequence', required=True, default=1)
wizard_id = fields.Many2one(
comodel_name='mass.sort.wizard', string='Wizard')
field_id = fields.Many2one(
comodel_name='ir.model.fields', string='Field', required=True,
domain="[('model', '=', parent.one2many_model)]")
desc = fields.Boolean('Inverse Order')

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: 798  |  Height: 386  |  Size: 43 KiB

BIN
mass_sorting/static/description/2_button.png

After

Width: 357  |  Height: 123  |  Size: 11 KiB

BIN
mass_sorting/static/description/3_mass_sort_wizard.png

After

Width: 276  |  Height: 177  |  Size: 9.5 KiB

BIN
mass_sorting/static/description/3_mass_sort_wizard_custom.png

After

Width: 776  |  Height: 318  |  Size: 17 KiB

BIN
mass_sorting/static/description/4_before.png

After

Width: 676  |  Height: 415  |  Size: 51 KiB

BIN
mass_sorting/static/description/5_after.png

After

Width: 679  |  Height: 412  |  Size: 50 KiB

BIN
mass_sorting/static/description/icon.png

After

Width: 256  |  Height: 256  |  Size: 6.2 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>

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).
-->
<odoo>
<menuitem id="menu_mass_sort_config"
action="action_mass_sort_config"
parent="base.menu_custom" sequence="30"/>
</odoo>

68
mass_sorting/views/view_mass_sort_config.xml

@ -0,0 +1,68 @@
<?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).
-->
<odoo>
<record id="view_mass_sort_config_search" model="ir.ui.view">
<field name="model">mass.sort.config</field>
<field name="arch" type="xml">
<search>
<field name="model_id"/>
</search>
</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>
<record id="view_mass_sort_config_form" model="ir.ui.view">
<field name="model">mass.sort.config</field>
<field name="arch" type="xml">
<form>
<header>
<button name="create_action" string="Add sidebar button" type="object" class="btn btn-primary"
attrs="{'invisible':[('action_id', '!=', 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" class="btn btn-default"
attrs="{'invisible':[('action_id', '=', False)]}"/>
</header>
<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"/>
<field name="action_id" attrs="{'invisible':[('action_id', '=', False)]}"/>
<field name="value_id" attrs="{'invisible':[('action_id', '=', False)]}"/>
<field name="allow_custom_setting"/>
</group>
<group string="Sorting Criterias">
<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>
</odoo>

37
mass_sorting/views/view_mass_sort_wizard.xml

@ -0,0 +1,37 @@
<?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).
-->
<odoo>
<record id="view_mass_sort_wizard_form" model="ir.ui.view">
<field name="model">mass.sort.wizard</field>
<field name="arch" type="xml">
<form>
<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="config_id" invisible="1"/>
<field name="allow_custom_setting" invisible="1"/>
<field name="one2many_model" invisible="1"/>
<footer>
<button string="Confirm" name="button_apply" type="object" class="btn btn-primary"/>
<button string="Cancel" special="cancel" class="btn-default"/>
</footer>
</form>
</field>
</record>
</odoo>
Loading…
Cancel
Save