Add sequence_ordered

issue5105
review25561002
This commit is contained in:
Sergi Almacellas Abellana committed 2016-09-13 14:01:17 +02:00
1 parent 44bd45546c
commit 828afc310d
8 files changed
+100 -20

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Add sequence_ordered
* Remove most country specific code in languages
* Add support for derivative translations
* Remove IDENTIFIER regexp on ir.model and ir.model.field
+13
View File
@@ -683,6 +683,19 @@ Class methods:
Return the SQL table and columns to use for the UNION for the model name.
================
sequence_ordered
================
.. method:: sequence_ordered([field_name, [field_label, [order, [null_first]]]])
Retuns a mixin_ class which defines the order of a :class:`ModelSQL` with an
:class:`trytond.model.fields.Integer` field. field_name indicates the name of
the field to be created and its default values is `sequence`. field_label
defines the label which will be used by the field and defaults to `Sequence`.
Order specifies the order direction and defaults to `ASC` and null first
if the null values should be ordered first and defaults to `True`.
.. _mixin: http://en.wikipedia.org/wiki/Mixin
.. _JSON: http://en.wikipedia.org/wiki/Json
+3 -18
View File
@@ -2,10 +2,7 @@
# this repository contains the full copyright notices and license terms.
from itertools import groupby
from sql import Null
from sql.conditionals import Case
from trytond.model import ModelView, ModelSQL, fields
from trytond.model import ModelView, ModelSQL, fields, sequence_ordered
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.rpc import RPC
@@ -72,12 +69,11 @@ CLIENT_ICONS = [(x, x) for x in (
SEPARATOR = ' / '
class UIMenu(ModelSQL, ModelView):
class UIMenu(sequence_ordered(), ModelSQL, ModelView):
"UI menu"
__name__ = 'ir.ui.menu'
name = fields.Char('Menu', required=True, translate=True)
sequence = fields.Integer('Sequence', required=True)
childs = fields.One2Many('ir.ui.menu', 'parent', 'Children')
parent = fields.Many2One('ir.ui.menu', 'Parent Menu', select=True,
ondelete='CASCADE')
@@ -102,7 +98,6 @@ class UIMenu(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(UIMenu, cls).__setup__()
cls._order.insert(0, ('sequence', 'ASC'))
cls._error_messages.update({
'wrong_name': ('"%%s" is not a valid menu name because it is '
'not allowed to contain "%s".' % SEPARATOR),
@@ -271,13 +266,12 @@ class UIMenu(ModelSQL, ModelView):
return menu2favorite
class UIMenuFavorite(ModelSQL, ModelView):
class UIMenuFavorite(sequence_ordered(), ModelSQL, ModelView):
"Menu Favorite"
__name__ = 'ir.ui.menu.favorite'
menu = fields.Many2One('ir.ui.menu', 'Menu', required=True,
ondelete='CASCADE')
sequence = fields.Integer('Sequence')
user = fields.Many2One('res.user', 'User', required=True,
ondelete='CASCADE')
@@ -289,15 +283,6 @@ class UIMenuFavorite(ModelSQL, ModelView):
'set': RPC(readonly=False),
'unset': RPC(readonly=False),
})
cls._order = [
('sequence', 'ASC'),
('id', 'DESC'),
]
@staticmethod
def order_sequence(tables):
table, _ = tables[None]
return [Case((table.sequence == Null, 0), else_=1), table.sequence]
@staticmethod
def default_user():
+2 -1
View File
@@ -10,8 +10,9 @@ from .dictschema import DictSchemaMixin
from .match import MatchMixin
from .union import UnionMixin
from .descriptors import dualmethod
from .order import sequence_ordered
__all__ = ['Model', 'ModelView', 'ModelStorage', 'ModelSingleton', 'ModelSQL',
'Check', 'Unique',
'Workflow', 'DictSchemaMixin', 'MatchMixin', 'UnionMixin', 'dualmethod',
'EvalEnvironment']
'EvalEnvironment', 'sequence_ordered']
+33
View File
@@ -0,0 +1,33 @@
# This file is part of Tryton. The COPYRIGHT file at the toplevel of this
# repository contains the full copyright notices and license terms.
from sql import Null, Column
from sql.operators import Equal, NotEqual
from sql.conditionals import Case
from trytond.model import fields
def sequence_ordered(field_name='sequence', field_label='Sequence',
order='ASC', null_first=True):
"Returns a mixin to order the model by order fields"
class SequenceOrderedMixin(object):
"Mixin to order model by a sequence field"
@classmethod
def __setup__(cls):
super(SequenceOrderedMixin, cls).__setup__()
cls._order = [(field_name, order)] + cls._order
setattr(SequenceOrderedMixin, field_name, fields.Integer(field_label))
@classmethod
def order_function(cls, tables):
table, _ = tables[None]
operator = Equal
if not null_first:
operator = NotEqual
field = Column(table, field_name)
return [Case((operator(field, Null), 0), else_=1), field]
setattr(SequenceOrderedMixin, 'order_%s' % field_name, order_function)
return SequenceOrderedMixin
+1
View File
@@ -120,6 +120,7 @@ def register():
Model4UnionTree1,
Model4UnionTree2,
UnionTree,
SequenceOrderedModel,
ModelViewChangedValues,
ModelViewChangedValuesTarget,
ModelViewButton,
+8 -1
View File
@@ -1,6 +1,7 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelSingleton, ModelSQL, UnionMixin, fields
from trytond.model import (ModelSingleton, ModelSQL, UnionMixin, fields,
sequence_ordered)
from trytond.transaction import Transaction
__all__ = [
@@ -11,6 +12,7 @@ __all__ = [
'Model4Union1', 'Model4Union2', 'Model4Union3', 'Model4Union4',
'Union', 'UnionUnion',
'Model4UnionTree1', 'Model4UnionTree2', 'UnionTree',
'SequenceOrderedModel',
]
@@ -154,3 +156,8 @@ class UnionTree(UnionMixin, ModelSQL):
@staticmethod
def union_models():
return ['test.model.union.tree1', 'test.model.union.tree2']
class SequenceOrderedModel(sequence_ordered(), ModelSQL):
'Sequence Ordered Model'
__name__ = 'test.order.sequence'
+39
View File
@@ -0,0 +1,39 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import unittest
from trytond.tests.test_tryton import install_module, with_transaction
from trytond.pool import Pool
class SequenceOrderedMixinTestCase(unittest.TestCase):
'Test SequenceOrderedMixin'
@classmethod
def setUpClass(cls):
install_module('tests')
@with_transaction()
def test_order(self):
'Test order'
pool = Pool()
Order = pool.get('test.order.sequence')
models = []
for i in reversed(range(1, 4)):
models.append(Order(sequence=i))
Order.save(models)
models.reverse()
self.assertListEqual(Order.search([]), models)
model = models.pop()
model.sequence = None
model.save()
models.insert(0, model)
self.assertListEqual(Order.search([]), models)
def suite():
return unittest.TestLoader().loadTestsFromTestCase(
SequenceOrderedMixinTestCase)