Projet

Général

Profil

0001-do-not-add-an-evolution-on-static-jump-22236.patch

Thomas Noël, 01 mai 2018 23:27

Télécharger (15 ko)

Voir les différences:

Subject: [PATCH] do not add an evolution on static jump (#22236)

 tests/test_form_pages.py | 38 ++++++++++++++++++++++++++++++++++----
 tests/test_sql.py        |  2 ++
 wcs/admin/forms.py       |  4 +---
 wcs/formdata.py          | 24 +++++++++++++++++++-----
 wcs/sql.py               | 36 +++++++++++++++++++++++++++---------
 wcs/wf/jump.py           |  5 +----
 wcs/workflows.py         |  4 ++--
 7 files changed, 86 insertions(+), 27 deletions(-)
tests/test_form_pages.py
1 1
# -*- coding: utf-8 -*-
2 2

  
3
import datetime
3 4
import json
4 5
import pytest
5 6
import hashlib
......
3766 3767
    user.roles = [role.id]
3767 3768
    user.store()
3768 3769

  
3770
    assert len(formdef.data_class().get(formdata.id).evolution) == 1
3771
    assert formdef.data_class().get(formdata.id).evolution[0].last_jump_datetime is None
3772

  
3769 3773
    login(app, username='foo', password='foo')
3770 3774
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3775
    formdata = formdef.data_class().get(formdata.id)
3776
    # status is not changed: no new evolution, only a new last_jump_datetime
3777
    assert len(formdata.evolution) == 1
3778
    assert formdata.status == 'wf-st1'
3779
    assert formdata.evolution[0].last_jump_datetime is not None
3780

  
3781
    # add a comment to last evolution, forcing create a new one
3782
    formdata.evolution[-1].comment = 'new-evolution-1'
3783
    formdata.store()
3771 3784
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3785
    formdata = formdef.data_class().get(formdata.id)
3786
    assert len(formdata.evolution) == 2
3787
    assert formdata.status == 'wf-st1'
3788

  
3789
    # again
3790
    formdata.evolution[-1].comment = 'new-evolution-2'
3791
    formdata.store()
3772 3792
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3773 3793

  
3774
    assert len(formdef.data_class().get(formdata.id).evolution) == 4
3775
    assert formdef.data_class().get(formdata.id).status == 'wf-st1'
3794
    # last evolution is empty, this last trigger does not create a new one
3795
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3796

  
3797
    # finally, 3 evolutions: new-evolution-1, new-evolution-2, empty
3798
    formdata = formdef.data_class().get(formdata.id)
3799
    assert len(formdata.evolution) == 3
3800
    assert formdata.status == 'wf-st1'
3801
    assert formdata.evolution[0].comment == 'new-evolution-1'
3802
    assert formdata.evolution[1].comment == 'new-evolution-2'
3803
    assert formdata.evolution[2].comment is None
3776 3804

  
3777 3805
    resp = app.get(formdata.get_url())
3778
    assert resp.body.count('Status1') == 2 # once in summary and once in journal
3779
    assert resp.body.count('CSS-STATUS1') == 1
3806
    assert resp.body.count('Status1') == 3 # once in summary and two in journal
3807
    assert resp.body.count('CSS-STATUS1') == 2
3808
    assert resp.body.count('new-evolution-1') == 1
3809
    assert resp.body.count('new-evolution-2') == 1
3780 3810

  
3781 3811
def test_display_message(pub):
3782 3812
    user = create_user(pub)
tests/test_sql.py
1456 1456
    formdata1 = data_class()
1457 1457
    formdata1.status = 'wf-st1'
1458 1458
    formdata1.just_created()
1459
    formdata1.evolution[0].comment = 'comment'
1459 1460
    formdata1.jump_status('st1') # will add another evolution entry
1460 1461
    formdata1.evolution[0].time = datetime.datetime(2015, 1, 1, 0, 0, 0).timetuple()
1461 1462
    formdata1.evolution[1].time = datetime.datetime(2015, 1, 2, 0, 0, 0).timetuple()
......
1464 1465
    formdata2 = data_class()
1465 1466
    formdata2.status = 'wf-st1'
1466 1467
    formdata2.just_created()
1468
    formdata2.evolution[0].comment = 'comment'
1467 1469
    formdata2.jump_status('st1') # will add another evolution entry
1468 1470
    formdata2.evolution[0].time = datetime.datetime(2015, 1, 3, 0, 0, 0).timetuple()
1469 1471
    formdata2.evolution[1].time = datetime.datetime(2015, 1, 4, 0, 0, 0).timetuple()
wcs/admin/forms.py
1156 1156
                if form.get_widget('date').parse():
1157 1157
                    date = form.get_widget('date').parse()
1158 1158
                    date = time.strptime(date, misc.date_format())
1159
                    all_forms = [x for x in all_forms if (
1160
                        x.evolution and x.evolution[-1].time < date) or (
1161
                        x.receipt_time < date)]
1159
                    all_forms = [x for x in all_forms if x.last_update_time < date]
1162 1160

  
1163 1161
                self.fd = StringIO()
1164 1162
                t = tarfile.open('wcs.tar.gz', 'w:gz', fileobj=self.fd)
wcs/formdata.py
131 131
    who = None
132 132
    status = None
133 133
    time = None
134
    last_jump_datetime = None
134 135
    comment = None
135 136
    parts = None
136 137

  
......
179 180
    def get_json_export_dict(self, user, anonymise=False):
180 181
        data = {
181 182
            'time': self.time,
183
            'last_jump_datetime': self.last_jump_datetime,
182 184
        }
183 185
        if self.status:
184 186
            data['status'] = self.status[3:]
......
536 538
            previous_status = self.pop_previous_marked_status()
537 539
            assert previous_status, 'failed to compute previous status'
538 540
            status_id = previous_status.id
539
        evo = Evolution(self)
540
        evo.time = time.localtime()
541
        evo.status = 'wf-%s' % status_id
541
        status = 'wf-%s' % status_id
542 542
        if not self.evolution:
543 543
            self.evolution = []
544
        elif (self.status == status
545
              and self.evolution[-1].status == status
546
              and not self.evolution[-1].comment
547
              and not self.evolution[-1].display_parts()):
548
            # if status do not change and last evolution is empty,
549
            # just update last jump time on last evolution, do not add one
550
            self.evolution[-1].last_jump_datetime = datetime.datetime.now()
551
            self.store()
552
            return
553
        evo = Evolution(self)
554
        evo.time = time.localtime()
555
        evo.status = status
544 556
        self.evolution.append(evo)
545
        self.status = evo.status
557
        self.status = status
546 558
        self.store()
547 559

  
548 560
    def get_url(self, backoffice = False):
......
830 842
    def get_last_update_time(self):
831 843
        if hasattr(self, '_last_update_time'):
832 844
            return self._last_update_time
833
        if self.evolution and self.evolution[-1].time:
845
        if self.evolution and self.evolution[-1].last_jump_datetime:
846
            return self.evolution[-1].last_jump_datetime.timetuple()
847
        elif self.evolution and self.evolution[-1].time:
834 848
            return self.evolution[-1].time
835 849
        else:
836 850
            return self.receipt_time
wcs/sql.py
371 371
                                    who varchar,
372 372
                                    status varchar,
373 373
                                    time timestamp,
374
                                    last_jump_datetime timestamp,
374 375
                                    comment text,
375 376
                                    parts bytea,
376 377
                                    formdata_id integer REFERENCES %s (id) ON DELETE CASCADE)''' % (
......
463 464
    for field in (existing_fields - needed_fields):
464 465
        cur.execute('''ALTER TABLE %s DROP COLUMN %s CASCADE''' % (table_name, field))
465 466

  
467
    # migrations on _evolutions table
468
    cur.execute('''SELECT column_name FROM information_schema.columns
469
                    WHERE table_schema = 'public'
470
                      AND table_name = '%s_evolutions'
471
                ''' % table_name)
472
    evo_existing_fields = set([x[0] for x in cur.fetchall()])
473
    if 'last_jump_datetime' not in evo_existing_fields:
474
        cur.execute('''ALTER TABLE %s_evolutions ADD COLUMN last_jump_datetime timestamp''' % table_name)
475

  
466 476
    if rebuild_views or len(existing_fields - needed_fields):
467 477
        # views may have been dropped when dropping columns, so we recreate
468 478
        # them even if not asked to.
......
1192 1202
            self._evolution = []
1193 1203
            return self._evolution
1194 1204
        conn, cur = get_connection_and_cursor()
1195
        sql_statement = '''SELECT id, who, status, time, comment, parts FROM %s_evolutions
1205
        sql_statement = '''SELECT id, who, status, time, last_jump_datetime,
1206
                                  comment, parts FROM %s_evolutions
1196 1207
                            WHERE formdata_id = %%(id)s
1197 1208
                         ORDER BY id''' % self._table_name
1198 1209
        cur.execute(sql_statement, {'id': self.id})
......
1209 1220
    @classmethod
1210 1221
    def _row2evo(cls, row, formdata):
1211 1222
        o = wcs.formdata.Evolution(formdata)
1212
        o._sql_id, o.who, o.status, o.time, o.comment = [str_encode(x) for x in tuple(row[:5])]
1223
        o._sql_id, o.who, o.status, o.time, o.last_jump_datetime, o.comment = [
1224
                str_encode(x) for x in tuple(row[:6])]
1213 1225
        if o.time:
1214 1226
            o.time = o.time.timetuple()
1215
        if row[5]:
1216
            o.parts = cPickle.loads(str(row[5]))
1227
        if row[6]:
1228
            o.parts = cPickle.loads(str(row[6]))
1217 1229
        return o
1218 1230

  
1219 1231
    def set_evolution(self, value):
......
1234 1246
        if not object_dict:
1235 1247
            return
1236 1248
        conn, cur = get_connection_and_cursor()
1237
        sql_statement = '''SELECT id, who, status, time, comment, parts, formdata_id
1249
        sql_statement = '''SELECT id, who, status, time, last_jump_datetime,
1250
                                  comment, parts, formdata_id
1238 1251
                             FROM %s_evolutions''' % cls._table_name
1239 1252
        sql_statement += ''' WHERE formdata_id IN %(object_ids)s ORDER BY id'''
1240 1253
        cur.execute(sql_statement, {'object_ids': tuple(object_dict.keys())})
......
1246 1259
            row = cur.fetchone()
1247 1260
            if row is None:
1248 1261
                break
1249
            _sql_id, who, status, time, comment, parts, formdata_id = tuple(row[:7])
1262
            _sql_id, who, status, time, last_jump_datetime, comment, parts, formdata_id = tuple(row[:8])
1250 1263
            formdata = object_dict.get(formdata_id)
1251 1264
            if not formdata:
1252 1265
                continue
......
1340 1353
                    sql_dict.update({'id': evo._sql_id})
1341 1354
                    sql_statement = '''UPDATE %s_evolutions SET
1342 1355
                                        time = %%(time)s,
1356
                                        last_jump_datetime = %%(last_jump_datetime)s,
1343 1357
                                        status = %%(status)s,
1344 1358
                                        comment = %%(comment)s,
1345 1359
                                        parts = %%(parts)s
......
1348 1362
                else:
1349 1363
                    sql_statement = '''INSERT INTO %s_evolutions (
1350 1364
                                               id, who, status,
1351
                                               time, comment, parts,
1365
                                               time, last_jump_datetime,
1366
                                               comment, parts,
1352 1367
                                               formdata_id)
1353 1368
                                        VALUES (DEFAULT, %%(who)s, %%(status)s,
1354
                                                %%(time)s, %%(comment)s,
1369
                                                %%(time)s, %%(last_jump_datetime)s,
1370
                                                %%(comment)s,
1355 1371
                                                %%(parts)s, %%(formdata_id)s)
1356 1372
                                     RETURNING id''' % self._table_name
1357 1373
                sql_dict.update({
1358 1374
                        'who': evo.who,
1359 1375
                        'status': evo.status,
1360 1376
                        'time': datetime.datetime.fromtimestamp(time.mktime(evo.time)),
1377
                        'last_jump_datetime': evo.last_jump_datetime,
1361 1378
                        'comment': evo.comment,
1362 1379
                        'formdata_id': self.id,
1363 1380
                })
......
2105 2122
    return result
2106 2123

  
2107 2124

  
2108
SQL_LEVEL = 25
2125
SQL_LEVEL = 26
2109 2126

  
2110 2127
def migrate_global_views(conn, cur):
2111 2128
    cur.execute('''SELECT COUNT(*) FROM information_schema.tables
......
2179 2196
        # 19: add geolocation to views
2180 2197
        # 20: remove user hash stuff
2181 2198
        # 22: rebuild views
2199
        # 26: add last_jump_datetime in evolutions tables
2182 2200
        migrate_views(conn, cur)
2183 2201
    if sql_level < 21:
2184 2202
        # 3: introduction of _structured for user fields
wcs/wf/jump.py
235 235

  
236 236
        if self.timeout:
237 237
            timeout = int(self.compute(self.timeout))
238
            if formdata.evolution:
239
                last = formdata.evolution[-1].time
240
            else:
241
                last = formdata.receipt_time
238
            last = formdata.last_update_time
242 239
            if last:
243 240
                diff = time.time() - time.mktime(last)
244 241
                must_jump = (diff > timeout) and must_jump
wcs/workflows.py
1033 1033
            anchor_status = self.anchor_status_first or formdata.status
1034 1034
            for evolution in formdata.evolution:
1035 1035
                if evolution.status == anchor_status:
1036
                    anchor_date = evolution.time
1036
                    anchor_date = evolution.last_jump_datetime or evolution.time
1037 1037
                    break
1038 1038
        elif self.anchor == 'latest-arrival':
1039 1039
            anchor_status = self.anchor_status_latest or formdata.status
1040 1040
            for evolution in reversed(formdata.evolution):
1041 1041
                if evolution.status == anchor_status:
1042
                    anchor_date = evolution.time
1042
                    anchor_date = evolution.last_jump_datetime or evolution.time
1043 1043
                    break
1044 1044
        elif self.anchor == 'python':
1045 1045
            variables = get_publisher().substitutions.get_context_variables()
1046
-