changeset a6df735f91f4 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset;node=a6df735f91f4
description:
Store directly sequence type to sequence
issue10122
review351381002
diffstat:
CHANGELOG | 2 +
trytond/ir/message.xml | 3 +
trytond/ir/sequence.py | 92 ++++++++++++++++++++------------
trytond/ir/view/sequence_form.xml | 4 +-
trytond/ir/view/sequence_list.xml | 2 +-
trytond/ir/view/sequence_type_form.xml | 2 -
trytond/ir/view/sequence_type_list.xml | 1 -
trytond/res/__init__.py | 2 -
trytond/res/ir.py | 38 -------------
trytond/res/ir.xml | 4 +-
trytond/res/view/sequence_type_form.xml | 4 +-
trytond/tests/sequence.xml | 1 -
trytond/tests/test_ir.py | 12 +--
trytond/tests/test_sequence.py | 49 ++++++++++++-----
14 files changed, 106 insertions(+), 110 deletions(-)
diffs (506 lines):
diff -r 7007a9104464 -r a6df735f91f4 CHANGELOG
--- a/CHANGELOG Thu Mar 11 19:20:32 2021 +0100
+++ b/CHANGELOG Thu Mar 11 23:00:10 2021 +0100
@@ -1,3 +1,5 @@
+* Use instance method to get next sequence value
+* Store the sequence type directly on sequence
* Allow sending email with record's attachments
* Add which records to use for actions
* Add parent to group to inherit accesses
diff -r 7007a9104464 -r a6df735f91f4 trytond/ir/message.xml
--- a/trytond/ir/message.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/ir/message.xml Thu Mar 11 23:00:10 2021 +0100
@@ -264,6 +264,9 @@
<record model="ir.message" id="msg_sequence_last_timestamp_future">
<field name="text">The "Last Timestamp" cannot be in the future
for sequence "%s".</field>
</record>
+ <record model="ir.message" id="msg_sequence_change_sequence_type">
+ <field name="text">You cannot change the sequence type of a
sequence instead create a new sequence.</field>
+ </record>
<record model="ir.message" id="msg_language_invalid_grouping">
<field name="text">Invalid grouping "%(grouping)s" for language
"%(language)s".</field>
diff -r 7007a9104464 -r a6df735f91f4 trytond/ir/sequence.py
--- a/trytond/ir/sequence.py Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/ir/sequence.py Thu Mar 11 23:00:10 2021 +0100
@@ -9,7 +9,7 @@
from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.model import ModelView, ModelSQL, DeactivableMixin, fields, Check
-from trytond.model.exceptions import ValidationError
+from trytond.model.exceptions import ValidationError, AccessError
from trytond.pool import Pool
from trytond.pyson import Eval, And
from trytond.transaction import Transaction
@@ -34,7 +34,15 @@
__name__ = 'ir.sequence.type'
name = fields.Char('Sequence Name', required=True, translate=True)
- code = fields.Char('Sequence Code', required=True)
+
+ @classmethod
+ def __register__(cls, module):
+ super().__register__(module)
+ table_h = cls.__table_handler__(module)
+
+ # Migration from 5.8: remove code
+ # We keep the column until ir.sequence has been migrated
+ table_h.not_null_action('code', action='remove')
class Sequence(DeactivableMixin, ModelSQL, ModelView):
@@ -43,10 +51,13 @@
_strict = False
name = fields.Char('Sequence Name', required=True, translate=True)
- code = fields.Selection('code_get', 'Sequence Code', required=True,
+ sequence_type = fields.Many2One(
+ 'ir.sequence.type', "Sequence Type",
+ required=True, ondelete='RESTRICT',
states={
- 'readonly': Eval('context', {}).contains('code'),
- })
+ 'readonly': Eval('id', -1) >= 0,
+ },
+ depends=['id'])
prefix = fields.Char('Prefix')
suffix = fields.Char('Suffix')
type = fields.Selection([
@@ -100,6 +111,29 @@
'Timestamp rounding should be greater than 0'),
]
+ @classmethod
+ def __register__(cls, module):
+ pool = Pool()
+ SequenceType = pool.get('ir.sequence.type')
+ cursor = Transaction().connection.cursor()
+ table = cls.__table__()
+ sequence_type = SequenceType.__table__()
+
+ super().__register__(module)
+
+ table_h = cls.__table_handler__(module)
+
+ # Migration from 5.8: replace code by sequence_type
+ if table_h.column_exist('code'):
+ cursor.execute(*table.update(
+ [table.sequence_type],
+ sequence_type.select(
+ sequence_type.id,
+ where=sequence_type.code == table.code)))
+ table_h.drop_column('code')
+ sequence_type_h = SequenceType.__table_handler__(module)
+ sequence_type_h.drop_column('code')
+
@staticmethod
def default_type():
return 'incremental'
@@ -128,10 +162,6 @@
def default_last_timestamp():
return 0
- @staticmethod
- def default_code():
- return Transaction().context.get('code')
-
def get_number_next(self, name):
if self.type != 'incremental':
return
@@ -171,10 +201,17 @@
return sequences
@classmethod
- def write(cls, sequences, values, *args):
- super(Sequence, cls).write(sequences, values, *args)
+ def write(cls, *args):
+ transaction = Transaction()
+ if (transaction.user != 0
+ and transaction.context.get('_check_access')):
+ for values in args[1::2]:
+ if 'sequence_type' in values:
+ raise AccessError(gettext(
+ 'ir.msg_sequence_change_sequence_type'))
+ super().write(*args)
if sql_sequence and not cls._strict:
- actions = iter((sequences, values) + args)
+ actions = iter(args)
for sequences, values in zip(actions, actions):
for sequence in sequences:
sequence.update_sql_sequence(values.get('number_next'))
@@ -187,13 +224,6 @@
return super(Sequence, cls).delete(sequences)
@classmethod
- def code_get(cls):
- pool = Pool()
- SequenceType = pool.get('ir.sequence.type')
- sequence_types = SequenceType.search([])
- return [(x.code, x.name) for x in sequence_types]
-
- @classmethod
def validate(cls, sequences):
super(Sequence, cls).validate(sequences)
cls.check_affixes(sequences)
@@ -323,21 +353,16 @@
return hex(timestamp)[2:].upper()
return ''
- @classmethod
- def get_id(cls, domain, _lock=False):
- '''
- Return sequence value for the domain
+ def get(self, _lock=False):
'''
- if isinstance(domain, cls):
- domain = domain.id
- if isinstance(domain, int):
- domain = [('id', '=', domain)]
-
+ Return the next sequence value
+ '''
+ cls = self.__class__
# bypass rules on sequences
with Transaction().set_context(user=False, _check_access=False):
with Transaction().set_user(0):
try:
- sequence, = cls.search(domain, limit=1)
+ sequence = cls(self.id)
except TypeError:
raise MissingError(gettext('ir.msg_sequence_missing'))
if _lock:
@@ -360,10 +385,6 @@
cls._process(sequence.suffix, date=date),
)
- @classmethod
- def get(cls, code):
- return cls.get_id([('code', '=', code)])
-
class SequenceStrict(Sequence):
"Sequence Strict"
@@ -371,6 +392,5 @@
_table = None # Needed to reset Sequence._table
_strict = True
- @classmethod
- def get_id(cls, clause):
- return super(SequenceStrict, cls).get_id(clause, _lock=True)
+ def get(self, _lock=True):
+ return super().get(_lock=True)
diff -r 7007a9104464 -r a6df735f91f4 trytond/ir/view/sequence_form.xml
--- a/trytond/ir/view/sequence_form.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/ir/view/sequence_form.xml Thu Mar 11 23:00:10 2021 +0100
@@ -4,8 +4,8 @@
<form>
<label name="name"/>
<field name="name" colspan="3"/>
- <label name="code"/>
- <field name="code"/>
+ <label name="sequence_type"/>
+ <field name="sequence_type" widget="selection"/>
<label name="active"/>
<field name="active"/>
<label name="prefix"/>
diff -r 7007a9104464 -r a6df735f91f4 trytond/ir/view/sequence_list.xml
--- a/trytond/ir/view/sequence_list.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/ir/view/sequence_list.xml Thu Mar 11 23:00:10 2021 +0100
@@ -3,6 +3,6 @@
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="name" expand="2"/>
- <field name="code" expand="1"/>
+ <field name="sequence_type" expand="1"/>
<field name="type"/>
</tree>
diff -r 7007a9104464 -r a6df735f91f4 trytond/ir/view/sequence_type_form.xml
--- a/trytond/ir/view/sequence_type_form.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/ir/view/sequence_type_form.xml Thu Mar 11 23:00:10 2021 +0100
@@ -4,6 +4,4 @@
<form>
<label name="name"/>
<field name="name"/>
- <label name="code"/>
- <field name="code" readonly="1"/>
</form>
diff -r 7007a9104464 -r a6df735f91f4 trytond/ir/view/sequence_type_list.xml
--- a/trytond/ir/view/sequence_type_list.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/ir/view/sequence_type_list.xml Thu Mar 11 23:00:10 2021 +0100
@@ -3,5 +3,4 @@
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="name" expand="2"/>
- <field name="code" expand="1"/>
</tree>
diff -r 7007a9104464 -r a6df735f91f4 trytond/res/__init__.py
--- a/trytond/res/__init__.py Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/res/__init__.py Thu Mar 11 23:00:10 2021 +0100
@@ -36,8 +36,6 @@
ir.Lang,
ir.SequenceType,
ir.SequenceTypeGroup,
- ir.Sequence,
- ir.SequenceStrict,
ir.ModuleConfigWizardItem,
ir.Export,
ir.Export_Group,
diff -r 7007a9104464 -r a6df735f91f4 trytond/res/ir.py
--- a/trytond/res/ir.py Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/res/ir.py Thu Mar 11 23:00:10 2021 +0100
@@ -224,44 +224,6 @@
Rule._domain_get_cache.clear()
-class Sequence(metaclass=PoolMeta):
- __name__ = 'ir.sequence'
- groups = fields.Function(fields.Many2Many('res.group', None, None,
- 'User Groups'), 'get_groups', searcher='search_groups')
-
- @classmethod
- def get_groups(cls, sequences, name):
- SequenceType = Pool().get('ir.sequence.type')
- code2seq = {}
- for sequence in sequences:
- code2seq.setdefault(sequence.code, []).append(sequence.id)
-
- sequence_types = SequenceType.search([
- ('code', 'in', list(code2seq.keys())),
- ])
-
- groups = {}
- for sequence_type in sequence_types:
- seq_ids = code2seq[sequence_type.code]
- for seq_id in seq_ids:
- groups.setdefault(seq_id, []).append(sequence_type.id)
-
- return groups
-
- @staticmethod
- def search_groups(name, clause):
- SequenceType = Pool().get('ir.sequence.type')
- seq_types = SequenceType.search([clause], order=[])
- codes = set(st.code for st in seq_types)
- return [('code', 'in', list(codes))]
-
-
-class SequenceStrict(Sequence):
- # This empty class declaration is needed to inherit the groups
- # field
- __name__ = 'ir.sequence.strict'
-
-
class ModuleConfigWizardItem(metaclass=PoolMeta):
__name__ = 'ir.module.config_wizard.item'
diff -r 7007a9104464 -r a6df735f91f4 trytond/res/ir.xml
--- a/trytond/res/ir.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/res/ir.xml Thu Mar 11 23:00:10 2021 +0100
@@ -778,7 +778,7 @@
</record>
<record model="ir.rule" id="rule_sequence">
<field name="domain"
- eval="[('groups', 'in', Eval('groups', []))]"
+ eval="[('sequence_type.groups', 'in', Eval('groups', []))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_sequence"/>
</record>
@@ -791,7 +791,7 @@
</record>
<record model="ir.rule" id="rule_sequence_strict">
<field name="domain"
- eval="[('groups', 'in', Eval('groups', []))]"
+ eval="[('sequence_type.groups', 'in', Eval('groups', []))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_sequence_strict"/>
</record>
diff -r 7007a9104464 -r a6df735f91f4 trytond/res/view/sequence_type_form.xml
--- a/trytond/res/view/sequence_type_form.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/res/view/sequence_type_form.xml Thu Mar 11 23:00:10 2021 +0100
@@ -2,9 +2,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. -->
<data>
- <xpath
- expr="/form/field[@name='code']"
- position="after">
+ <xpath expr="/form" position="inside">
<field name="groups" colspan="4"/>
</xpath>
</data>
diff -r 7007a9104464 -r a6df735f91f4 trytond/tests/sequence.xml
--- a/trytond/tests/sequence.xml Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/tests/sequence.xml Thu Mar 11 23:00:10 2021 +0100
@@ -6,7 +6,6 @@
<record model="ir.sequence.type" id="sequence_type_test">
<field name="name">Test</field>
- <field name="code">test</field>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_test_group_admin">
diff -r 7007a9104464 -r a6df735f91f4 trytond/tests/test_ir.py
--- a/trytond/tests/test_ir.py Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/tests/test_ir.py Thu Mar 11 23:00:10 2021 +0100
@@ -31,20 +31,18 @@
except KeyError:
groups = []
- sequence_type = SequenceType(name='Test', code='test', groups=groups)
+ sequence_type = SequenceType(name='Test', groups=groups)
sequence_type.save()
- sequence = Sequence(name='Test Sequence', code='test')
+ sequence = Sequence(name='Test Sequence', sequence_type=sequence_type)
sequence.save()
- self.assertEqual(Sequence.get_id(sequence.id), '1')
+ self.assertEqual(sequence.get(), '1')
today = Date.today()
sequence.prefix = '${year}'
sequence.save()
- self.assertEqual(Sequence.get_id(sequence.id),
- '%s2' % str(today.year))
+ self.assertEqual(sequence.get(), '%s2' % str(today.year))
next_year = today + relativedelta(years=1)
with Transaction().set_context(date=next_year):
- self.assertEqual(Sequence.get_id(sequence.id),
- '%s3' % str(next_year.year))
+ self.assertEqual(sequence.get(), '%s3' % str(next_year.year))
@with_transaction()
def test_global_search(self):
diff -r 7007a9104464 -r a6df735f91f4 trytond/tests/test_sequence.py
--- a/trytond/tests/test_sequence.py Thu Mar 11 19:20:32 2021 +0100
+++ b/trytond/tests/test_sequence.py Thu Mar 11 23:00:10 2021 +0100
@@ -24,49 +24,59 @@
@with_transaction()
def test_incremental(self):
'Test incremental'
+ pool = Pool()
Sequence = self.get_model()
+ SequenceType = pool.get('ir.sequence.type')
+ sequence_type, = SequenceType.search([
+ ('name', '=', "Test"),
+ ], limit=1)
sequence, = Sequence.create([{
'name': 'Test incremental',
- 'code': 'test',
+ 'sequence_type': sequence_type.id,
'prefix': '',
'suffix': '',
'type': 'incremental',
}])
self.assertEqual(sequence.number_next, 1)
- self.assertEqual(Sequence.get_id(sequence), '1')
+ self.assertEqual(sequence.get(), '1')
Sequence.write([sequence], {
'number_increment': 10,
})
self.assertEqual(sequence.number_next, 2)
- self.assertEqual(Sequence.get_id(sequence), '2')
- self.assertEqual(Sequence.get_id(sequence), '12')
+ self.assertEqual(sequence.get(), '2')
+ self.assertEqual(sequence.get(), '12')
Sequence.write([sequence], {
'padding': 3,
})
self.assertEqual(sequence.number_next, 22)
- self.assertEqual(Sequence.get_id(sequence), '022')
+ self.assertEqual(sequence.get(), '022')
@with_transaction()
def test_decimal_timestamp(self):
'Test Decimal Timestamp'
+ pool = Pool()
Sequence = self.get_model()
+ SequenceType = pool.get('ir.sequence.type')
+ sequence_type, = SequenceType.search([
+ ('name', '=', "Test"),
+ ], limit=1)
sequence, = Sequence.create([{
'name': 'Test decimal timestamp',
- 'code': 'test',
+ 'sequence_type': sequence_type.id,
'prefix': '',
'suffix': '',
'type': 'decimal timestamp',
}])
- timestamp = Sequence.get_id(sequence)
+ timestamp = sequence.get()
self.assertEqual(timestamp, str(sequence.last_timestamp))
self.assertEqual(sequence.number_next, None)
- self.assertNotEqual(Sequence.get_id(sequence), timestamp)
+ self.assertNotEqual(sequence.get(), timestamp)
next_timestamp = Sequence._timestamp(sequence)
self.assertRaises(LastTimestampError, Sequence.write, [sequence], {
@@ -76,22 +86,27 @@
@with_transaction()
def test_hexadecimal_timestamp(self):
'Test Hexadecimal Timestamp'
+ pool = Pool()
Sequence = self.get_model()
+ SequenceType = pool.get('ir.sequence.type')
+ sequence_type, = SequenceType.search([
+ ('name', '=', "Test"),
+ ], limit=1)
sequence, = Sequence.create([{
'name': 'Test hexadecimal timestamp',
- 'code': 'test',
+ 'sequence_type': sequence_type.id,
'prefix': '',
'suffix': '',
'type': 'hexadecimal timestamp',
}])
- timestamp = Sequence.get_id(sequence)
+ timestamp = sequence.get()
self.assertEqual(timestamp,
hex(int(sequence.last_timestamp))[2:].upper())
self.assertEqual(sequence.number_next, None)
- self.assertNotEqual(Sequence.get_id(sequence), timestamp)
+ self.assertNotEqual(sequence.get(), timestamp)
next_timestamp = Sequence._timestamp(sequence)
self.assertRaises(LastTimestampError, Sequence.write, [sequence], {
@@ -101,16 +116,21 @@
@with_transaction()
def test_prefix_suffix(self):
'Test prefix/suffix'
+ pool = Pool()
Sequence = self.get_model()
+ SequenceType = pool.get('ir.sequence.type')
+ sequence_type, = SequenceType.search([
+ ('name', '=', "Test"),
+ ], limit=1)
sequence, = Sequence.create([{
'name': 'Test incremental',
- 'code': 'test',
+ 'sequence_type': sequence_type.id,
'prefix': 'prefix/',
'suffix': '/suffix',
'type': 'incremental',
}])
- self.assertEqual(Sequence.get_id(sequence),
+ self.assertEqual(sequence.get(),
'prefix/1/suffix')
Sequence.write([sequence], {
@@ -118,8 +138,7 @@
'suffix': '/${day}.${month}.${year}',
})
with Transaction().set_context(date=datetime.date(2010, 8, 15)):
- self.assertEqual(Sequence.get_id(sequence),
- '2010-08-15/2/15.08.2010')
+ self.assertEqual(sequence.get(), '2010-08-15/2/15.08.2010')
class SequenceStrictTestCase(SequenceTestCase):