Allow date formating in sequences substitutions

Closes #8945
This commit is contained in:
Sergi Almacellas Abellana
2023-06-06 09:00:50 +00:00
parent d37e8d0990
commit 50cab67fab
4 changed files with 92 additions and 18 deletions
+1
View File
@@ -1,3 +1,4 @@
* Allow date formating in sequences substitutions
* Make ModelSQL based on table query read only by default
* Add email validation tools
* Remove overlapping indexes
+45 -10
View File
@@ -60,8 +60,12 @@ class Sequence(DeactivableMixin, ModelSQL, ModelView):
'readonly': Eval('id', -1) >= 0,
},
depends=['id'])
prefix = fields.Char('Prefix', strip='leading')
suffix = fields.Char('Suffix', strip='trailing')
prefix = fields.Char('Prefix', strip='leading',
help="The current date can be used formatted using strftime format "
"suffixed with underscores: i.e: ${date_Y}")
suffix = fields.Char('Suffix', strip='trailing',
help="The current date can be used formatted using strftime format "
"suffixed with underscores: i.e: ${date_Y}")
type = fields.Selection([
('incremental', 'Incremental'),
('decimal timestamp', 'Decimal Timestamp'),
@@ -319,11 +323,14 @@ class Sequence(DeactivableMixin, ModelSQL, ModelView):
@classmethod
def _process(cls, string, date=None):
return Template(string or '').substitute(
**cls._get_substitutions(date))
if not string:
return ''
substitutions = cls._get_substitutions(date)
return Template(string or '').safe_substitute(substitutions)
@classmethod
def _get_substitutions(cls, date):
def _get_substitutions(cls, date=None):
'''
Returns a dictionary with the keys and values of the substitutions
available to format the sequence
@@ -332,11 +339,39 @@ class Sequence(DeactivableMixin, ModelSQL, ModelView):
Date = pool.get('ir.date')
if not date:
date = Date.today()
return {
'year': date.strftime('%Y'),
'month': date.strftime('%m'),
'day': date.strftime('%d'),
}
class CustomFormatter(dict):
def __getitem__(self, name):
try:
value = super().__getitem__(name)
except KeyError:
value = cls._convert_substitution_key(self, name)
return value
return CustomFormatter({
'date': date,
})
@classmethod
def _convert_substitution_key(cls, substitutions, key):
"""
Converts a substitution key into a different (i.e: formated) value
Returns the updated value
"""
# Compatibilty with previous keywords
key = {
'year': 'date_Y',
'month': 'date_m',
'day': 'date_d',
}.get(key, key)
if key.startswith('date_'):
format_ = key[len('date'):].replace('_', '%')
value = substitutions['date'].strftime(format_)
if value == format_:
raise ValueError(
f"Unknown substitution format {format_}")
return value
@staticmethod
def _timestamp(sequence):
@@ -30,12 +30,4 @@ this repository contains the full copyright notices and license terms. -->
<label name="last_timestamp"/>
<field name="last_timestamp"/>
</group>
<separator string="Legend (Placeholders for prefix, suffix)" colspan="4"
id="legend"/>
<label string="Year:" id="label_year"/>
<label string="${year}" colspan="3" xalign="0.0" xexpand="1" id="year"/>
<label string="Month:" id="label_month"/>
<label string="${month}" colspan="3" xalign="0.0" xexpand="1" id="month"/>
<label string="Day:" id="label_day"/>
<label string="${day}" colspan="3" xalign="0.0" xexpand="1" id="day"/>
</form>
+46
View File
@@ -13,6 +13,7 @@ except ImportError:
from dateutil.relativedelta import relativedelta
from trytond.config import config
from trytond.ir.exceptions import SequenceAffixError
from trytond.ir.lang import _replace
from trytond.pool import Pool
from trytond.pyson import Eval, If, PYSONEncoder
@@ -118,6 +119,51 @@ class IrTestCase(ModuleTestCase):
with Transaction().set_context(date=next_year):
self.assertEqual(sequence.get(), '%s3' % str(next_year.year))
@with_transaction()
def test_sequence_format(self):
'Test Sequence Format'
pool = Pool()
Sequence = pool.get('ir.sequence')
SequenceType = pool.get('ir.sequence.type')
try:
Group = pool.get('res.group')
groups = Group.search([])
except KeyError:
groups = []
sequence_type = SequenceType(name='Test', groups=groups)
sequence_type.save()
sequence = Sequence(name='Test Sequence', sequence_type=sequence_type)
sequence.save()
sequence.prefix = '${date_y}-'
sequence.save()
today = datetime.date(2023, 1, 1)
with Transaction().set_context(date=today):
self.assertEqual(sequence.get(), '23-1')
@with_transaction()
def test_sequence_wrong_format(self):
'Test Sequence Wrong Format'
pool = Pool()
Sequence = pool.get('ir.sequence')
SequenceType = pool.get('ir.sequence.type')
try:
Group = pool.get('res.group')
groups = Group.search([])
except KeyError:
groups = []
sequence_type = SequenceType(name='Test', groups=groups)
sequence_type.save()
sequence = Sequence(name='Test Sequence', sequence_type=sequence_type)
sequence.save()
with self.assertRaises(SequenceAffixError):
sequence.prefix = '${date_K}'
sequence.save()
@with_transaction()
def test_global_search(self):
'Test Global Search'