diff --git a/CHANGELOG b/CHANGELOG index 6b5d1b7c32..183b982e6b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add restore_history_before on ModelSQL * Remove img_{width,height} form attributes Version 3.4.0 - 2014-10-20 diff --git a/doc/ref/models/models.rst b/doc/ref/models/models.rst index 110636e99d..972a09529b 100644 --- a/doc/ref/models/models.rst +++ b/doc/ref/models/models.rst @@ -425,6 +425,15 @@ Class methods: No access rights are verified and the records are not validated. .. +.. classmethod:: ModelSQL.restore_history_before(ids, datetime) + + Restore the record ids from history before the specified date time. + Restoring a record will still generate an entry in the history table. + + .. warning:: + No access rights are verified and the records are not validated. + .. + .. classmethod:: ModelStorage.search(domain[, offset[, limit[, order[, count[, query]]]]]) Return a list of records that match the :ref:`domain ` or diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 4f3cf4380a..add50d1b9a 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -295,8 +295,7 @@ class ModelSQL(ModelStorage): [[id_, Now(), user] for id_ in sub_ids])) @classmethod - def restore_history(cls, ids, datetime): - 'Restore record ids from history at the date time' + def _restore_history(cls, ids, datetime, _before=False): if not cls._history: return transaction = Transaction() @@ -324,7 +323,11 @@ class ModelSQL(ModelStorage): to_update = [] for id_ in ids: column_datetime = Coalesce(history.write_date, history.create_date) - hwhere = (column_datetime <= datetime) & (history.id == id_) + if not _before: + hwhere = (column_datetime <= datetime) + else: + hwhere = (column_datetime < datetime) + hwhere &= (history.id == id_) horder = (column_datetime.desc, Column(history, '__id').desc) cursor.execute(*history.select(*hcolumns, where=hwhere, order_by=horder, limit=1)) @@ -352,6 +355,16 @@ class ModelSQL(ModelStorage): if to_update: cls.__insert_history(to_update) + @classmethod + def restore_history(cls, ids, datetime): + 'Restore record ids from history at the date time' + cls._restore_history(ids, datetime) + + @classmethod + def restore_history_before(cls, ids, datetime): + 'Restore record ids from history before the date time' + cls._restore_history(ids, datetime, _before=True) + @classmethod def __check_timestamp(cls, ids): transaction = Transaction() diff --git a/trytond/tests/test_history.py b/trytond/tests/test_history.py index 74c9176ec1..878c456ca3 100644 --- a/trytond/tests/test_history.py +++ b/trytond/tests/test_history.py @@ -193,6 +193,40 @@ class HistoryTestCase(unittest.TestCase): History.restore_history([history_id], datetime.datetime.max) self.assertRaises(UserError, History.read, [history_id]) + def test0041restore_history_before(self): + 'Test restore history before' + History = POOL.get('test.history') + + with Transaction().start(DB_NAME, USER, + context=CONTEXT) as transaction: + history = History(value=1) + history.save() + history_id = history.id + + transaction.cursor.commit() + + with Transaction().start(DB_NAME, USER, + context=CONTEXT) as transaction: + history = History(history_id) + history.value = 2 + history.save() + second = history.write_date + + transaction.cursor.commit() + + with Transaction().start(DB_NAME, USER, + context=CONTEXT) as transaction: + history = History(history_id) + history.value = 3 + history.save() + + transaction.cursor.commit() + + with Transaction().start(DB_NAME, USER, context=CONTEXT): + History.restore_history_before([history_id], second) + history = History(history_id) + self.assertEqual(history.value, 1) + @unittest.skipIf(backend.name() in ('sqlite', 'mysql'), 'now() is not the start of the transaction') def test0045restore_history_same_timestamp(self):