diff --git a/CHANGELOG b/CHANGELOG index 6ffa3e82d7..5299d49c90 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Remove float_time widget +* Add TimeDelta field * search_global yields record instead of id * Add ModelTestCase * Add test for missing default model access diff --git a/doc/ref/models/fields.rst b/doc/ref/models/fields.rst index 2e1de08af1..e0efe48431 100644 --- a/doc/ref/models/fields.rst +++ b/doc/ref/models/fields.rst @@ -364,6 +364,20 @@ A time, represented in Python by a ``datetime.time`` instance. Same as :attr:`DateTime.format` +TimeDelta +--------- + +.. class::TimeDelta(string[, converter[, \**options]]) + +An interval, represented in Python by a ``datetime.timedelta`` instance. + +.. attribute:: TimeDelta.converter + + The name of the context key containing the time converter. + A time converter is a dictionary with the keys: ``s`` (second), ``m`` + (minute), ``h`` (hour), ``d`` (day), ``w`` (week), ``M`` (month), ``Y`` + (year) and the value in second. + Binary ------ diff --git a/trytond/backend/postgresql/database.py b/trytond/backend/postgresql/database.py index 16811f685d..4426ec0236 100644 --- a/trytond/backend/postgresql/database.py +++ b/trytond/backend/postgresql/database.py @@ -9,9 +9,9 @@ from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT from psycopg2.extensions import register_type, register_adapter from psycopg2.extensions import UNICODE, AsIs try: - from psycopg2.extensions import PYDATE, PYDATETIME, PYTIME + from psycopg2.extensions import PYDATE, PYDATETIME, PYTIME, PYINTERVAL except ImportError: - PYDATE, PYDATETIME, PYTIME = None, None, None + PYDATE, PYDATETIME, PYTIME, PYINTERVAL = None, None, None, None from psycopg2 import IntegrityError as DatabaseIntegrityError from psycopg2 import OperationalError as DatabaseOperationalError import time @@ -379,5 +379,7 @@ if PYDATETIME: register_type(PYDATETIME) if PYTIME: register_type(PYTIME) +if PYINTERVAL: + register_type(PYINTERVAL) register_adapter(float, lambda value: AsIs(repr(value))) register_adapter(Decimal, lambda value: AsIs(str(value))) diff --git a/trytond/backend/sqlite/database.py b/trytond/backend/sqlite/database.py index 83006faeeb..f117ee9798 100644 --- a/trytond/backend/sqlite/database.py +++ b/trytond/backend/sqlite/database.py @@ -419,3 +419,6 @@ sqlite.register_adapter(datetime.datetime, adapt_datetime) sqlite.register_adapter(datetime.time, lambda val: val.isoformat()) sqlite.register_converter('TIME', lambda val: datetime.time(*map(int, val.split(':')))) +sqlite.register_adapter(datetime.timedelta, lambda val: val.total_seconds()) +sqlite.register_converter('INTERVAL', lambda val: datetime.timedelta( + seconds=float(val))) diff --git a/trytond/ir/trigger.py b/trytond/ir/trigger.py index 29359868a2..f83729512b 100644 --- a/trytond/ir/trigger.py +++ b/trytond/ir/trigger.py @@ -2,7 +2,7 @@ # this repository contains the full copyright notices and license terms. import datetime import time -from sql import Literal +from sql import Literal, Null from sql.aggregate import Count, Max from ..model import ModelView, ModelSQL, fields @@ -45,9 +45,10 @@ class Trigger(ModelSQL, ModelView): limit_number = fields.Integer('Limit Number', required=True, help='Limit the number of call to "Action Function" by records.\n' '0 for no limit.') - minimum_delay = fields.Float('Minimum Delay', help='Set a minimum delay ' - 'in minutes between call to "Action Function" for the same record.\n' - '0 for no delay.') + minimum_time_delay = fields.TimeDelta('Minimum Delay', + help='Set a minimum time delay between call to "Action Function" ' + 'for the same record.\n' + 'empty for no delay.') action_model = fields.Many2One('ir.model', 'Action Model', required=True) action_function = fields.Char('Action Function', required=True) _get_triggers_cache = Cache('ir_trigger.get_triggers') @@ -66,6 +67,29 @@ class Trigger(ModelSQL, ModelView): }) cls._order.insert(0, ('name', 'ASC')) + @classmethod + def __register__(cls, module_name): + TableHandler = backend.get('TableHandler') + cursor = Transaction().cursor + table = TableHandler(cursor, cls, module_name) + sql_table = cls.__table__() + + super(Trigger, cls).__register__(module_name) + + # Migration from 3.4: + # change minimum_delay into timedelta minimu_time_delay + if table.column_exist('minimum_delay'): + cursor.execute(*sql_table.select( + sql_table.id, sql_table.minimum_delay, + where=sql_table.minimum_delay != Null)) + for id_, delay in cursor.fetchall(): + delay = datetime.timedelta(hours=delay) + cursor.execute(*sql_table.update( + [sql_table.minimu_time_delay], + [delay], + where=sql_table.id == id_)) + table.drop_column('minimum_delay') + @classmethod def validate(cls, triggers): super(Trigger, cls).validate(triggers) @@ -182,8 +206,8 @@ class Trigger(ModelSQL, ModelView): new_ids.append(record_id) ids = new_ids - # Filter on minimum_delay - if trigger.minimum_delay: + # Filter on minimum_time_delay + if trigger.minimum_time_delay: new_ids = [] for sub_ids in grouped_slice(ids): sub_ids = list(sub_ids) @@ -211,15 +235,14 @@ class Trigger(ModelSQL, ModelView): delay[record_id] = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds) if (datetime.datetime.now() - delay[record_id] - >= datetime.timedelta( - minutes=trigger.minimum_delay)): + >= trigger.minimum_time_delay): new_ids.append(record_id) ids = new_ids records = Model.browse(ids) if records: getattr(ActionModel, trigger.action_function)(records, trigger) - if trigger.limit_number or trigger.minimum_delay: + if trigger.limit_number or trigger.minimum_time_delay: to_create = [] for record in records: to_create.append({ diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc index dc953606e1..00fdc962a5 100644 --- a/trytond/ir/ui/form.rnc +++ b/trytond/ir/ui/form.rnc @@ -49,7 +49,7 @@ attlist.field &= | "selection" | "char" | "password" - | "float_time" + | "timedelta" | "boolean" | "reference" | "binary" @@ -98,7 +98,6 @@ attlist.field &= | "top_to_bottom" }? attlist.field &= attribute spell { text }? -attlist.field &= attribute float_time { text }? attlist.field &= [a:defaultValue = "0"] attribute filename_visible { "0" | "1" }? attlist.field &= [a:defaultValue = "0"] attribute pre_validate { "0" | "1" }? diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng index 171569b268..8b680158a0 100644 --- a/trytond/ir/ui/form.rng +++ b/trytond/ir/ui/form.rng @@ -148,7 +148,7 @@ selection char password - float_time + timedelta boolean reference binary @@ -327,11 +327,6 @@ - - - - - diff --git a/trytond/ir/ui/graph.rnc b/trytond/ir/ui/graph.rnc index 3a74cfc563..9373be300a 100644 --- a/trytond/ir/ui/graph.rnc +++ b/trytond/ir/ui/graph.rnc @@ -23,8 +23,7 @@ attlist.field &= attribute domain { text }? attlist.field &= attribute fill { "0" | "1" }? attlist.field &= attribute empty { "0" | "1" }? attlist.field &= attribute color { text }? -attlist.field &= attribute widget { "float_time" }? -attlist.field &= attribute float_time { text }? +attlist.field &= attribute timedelta { text }? attlist.field &= [ a:defaultValue = "linear" ] attribute interpolation { "constant-left" | "constant-right" | "constant-center" | "linear" }? diff --git a/trytond/ir/ui/graph.rng b/trytond/ir/ui/graph.rng index 125c49c339..eb55457bf0 100644 --- a/trytond/ir/ui/graph.rng +++ b/trytond/ir/ui/graph.rng @@ -115,14 +115,7 @@ - - float_time - - - - - - + diff --git a/trytond/ir/ui/tree.rnc b/trytond/ir/ui/tree.rnc index d24e8e54dd..e42ec0d214 100644 --- a/trytond/ir/ui/tree.rnc +++ b/trytond/ir/ui/tree.rnc @@ -27,7 +27,7 @@ attlist.field &= | "selection" | "float" | "numeric" - | "float_time" + | "timedelta" | "integer" | "datetime" | "time" @@ -58,7 +58,6 @@ attlist.field &= | "bottom_to_top" | "top_to_bottom" }? -attlist.field &= attribute float_time { text }? attlist.field &= [a:defaultValue = "0"] attribute pre_validate { "0" | "1" }? attlist.field &= [a:defaultValue = "1"] attribute completion { "0" | "1" }? attlist.field &= attribute string { text }? diff --git a/trytond/ir/ui/tree.rng b/trytond/ir/ui/tree.rng index 117f89b1fc..44a5d3c96d 100644 --- a/trytond/ir/ui/tree.rng +++ b/trytond/ir/ui/tree.rng @@ -97,7 +97,7 @@ selection float numeric - float_time + timedelta integer datetime time @@ -168,11 +168,6 @@ - - - - - diff --git a/trytond/ir/view/trigger_form.xml b/trytond/ir/view/trigger_form.xml index 5301e5953f..5077179304 100644 --- a/trytond/ir/view/trigger_form.xml +++ b/trytond/ir/view/trigger_form.xml @@ -22,8 +22,8 @@ this repository contains the full copyright notices and license terms. -->