Projet

Général

Profil

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

Thomas Noël, 15 mai 2018 13:37

Télécharger (15,4 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               | 38 ++++++++++++++++++++++++++++----------
 wcs/wf/jump.py           |  5 +----
 wcs/workflows.py         |  4 ++--
 7 files changed, 87 insertions(+), 28 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
......
3821 3822
    user.roles = [role.id]
3822 3823
    user.store()
3823 3824

  
3825
    assert len(formdef.data_class().get(formdata.id).evolution) == 1
3826
    assert formdef.data_class().get(formdata.id).evolution[0].last_jump_datetime is None
3827

  
3824 3828
    login(app, username='foo', password='foo')
3825 3829
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3830
    formdata = formdef.data_class().get(formdata.id)
3831
    # status is not changed: no new evolution, only a new last_jump_datetime
3832
    assert len(formdata.evolution) == 1
3833
    assert formdata.status == 'wf-st1'
3834
    assert formdata.evolution[0].last_jump_datetime is not None
3835

  
3836
    # add a comment to last evolution, forcing create a new one
3837
    formdata.evolution[-1].comment = 'new-evolution-1'
3838
    formdata.store()
3826 3839
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3840
    formdata = formdef.data_class().get(formdata.id)
3841
    assert len(formdata.evolution) == 2
3842
    assert formdata.status == 'wf-st1'
3843

  
3844
    # again
3845
    formdata.evolution[-1].comment = 'new-evolution-2'
3846
    formdata.store()
3827 3847
    resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302)
3828 3848

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

  
3852
    # finally, 3 evolutions: new-evolution-1, new-evolution-2, empty
3853
    formdata = formdef.data_class().get(formdata.id)
3854
    assert len(formdata.evolution) == 3
3855
    assert formdata.status == 'wf-st1'
3856
    assert formdata.evolution[0].comment == 'new-evolution-1'
3857
    assert formdata.evolution[1].comment == 'new-evolution-2'
3858
    assert formdata.evolution[2].comment is None
3831 3859

  
3832 3860
    resp = app.get(formdata.get_url())
3833
    assert resp.body.count('Status1') == 2 # once in summary and once in journal
3834
    assert resp.body.count('CSS-STATUS1') == 1
3861
    assert resp.body.count('Status1') == 3 # once in summary and two in journal
3862
    assert resp.body.count('CSS-STATUS1') == 2
3863
    assert resp.body.count('new-evolution-1') == 1
3864
    assert resp.body.count('new-evolution-2') == 1
3835 3865

  
3836 3866
def test_display_message(pub):
3837 3867
    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
1187 1187
                if form.get_widget('date').parse():
1188 1188
                    date = form.get_widget('date').parse()
1189 1189
                    date = time.strptime(date, misc.date_format())
1190
                    all_forms = [x for x in all_forms if (
1191
                        x.evolution and x.evolution[-1].time < date) or (
1192
                        x.receipt_time < date)]
1190
                    all_forms = [x for x in all_forms if x.last_update_time < date]
1193 1191

  
1194 1192
                self.fd = StringIO()
1195 1193
                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:]
......
556 558
            previous_status = self.pop_previous_marked_status()
557 559
            assert previous_status, 'failed to compute previous status'
558 560
            status_id = previous_status.id
559
        evo = Evolution(self)
560
        evo.time = time.localtime()
561
        evo.status = 'wf-%s' % status_id
561
        status = 'wf-%s' % status_id
562 562
        if not self.evolution:
563 563
            self.evolution = []
564
        elif (self.status == status
565
              and self.evolution[-1].status == status
566
              and not self.evolution[-1].comment
567
              and not self.evolution[-1].display_parts()):
568
            # if status do not change and last evolution is empty,
569
            # just update last jump time on last evolution, do not add one
570
            self.evolution[-1].last_jump_datetime = datetime.datetime.now()
571
            self.store()
572
            return
573
        evo = Evolution(self)
574
        evo.time = time.localtime()
575
        evo.status = status
564 576
        self.evolution.append(evo)
565
        self.status = evo.status
577
        self.status = status
566 578
        self.store()
567 579

  
568 580
    def get_url(self, backoffice = False):
......
853 865
    def get_last_update_time(self):
854 866
        if hasattr(self, '_last_update_time'):
855 867
            return self._last_update_time
856
        if self.evolution and self.evolution[-1].time:
868
        if self.evolution and self.evolution[-1].last_jump_datetime:
869
            return self.evolution[-1].last_jump_datetime.timetuple()
870
        elif self.evolution and self.evolution[-1].time:
857 871
            return self.evolution[-1].time
858 872
        else:
859 873
            return self.receipt_time
wcs/sql.py
375 375
                                    who varchar,
376 376
                                    status varchar,
377 377
                                    time timestamp,
378
                                    last_jump_datetime timestamp,
378 379
                                    comment text,
379 380
                                    parts bytea,
380 381
                                    formdata_id integer REFERENCES %s (id) ON DELETE CASCADE)''' % (
......
471 472
    for field in (existing_fields - needed_fields):
472 473
        cur.execute('''ALTER TABLE %s DROP COLUMN %s CASCADE''' % (table_name, field))
473 474

  
475
    # migrations on _evolutions table
476
    cur.execute('''SELECT column_name FROM information_schema.columns
477
                    WHERE table_schema = 'public'
478
                      AND table_name = '%s_evolutions'
479
                ''' % table_name)
480
    evo_existing_fields = set([x[0] for x in cur.fetchall()])
481
    if 'last_jump_datetime' not in evo_existing_fields:
482
        cur.execute('''ALTER TABLE %s_evolutions ADD COLUMN last_jump_datetime timestamp''' % table_name)
483

  
474 484
    if rebuild_views or len(existing_fields - needed_fields):
475 485
        # views may have been dropped when dropping columns, so we recreate
476 486
        # them even if not asked to.
......
1201 1211
            self._evolution = []
1202 1212
            return self._evolution
1203 1213
        conn, cur = get_connection_and_cursor()
1204
        sql_statement = '''SELECT id, who, status, time, comment, parts FROM %s_evolutions
1214
        sql_statement = '''SELECT id, who, status, time, last_jump_datetime,
1215
                                  comment, parts FROM %s_evolutions
1205 1216
                            WHERE formdata_id = %%(id)s
1206 1217
                         ORDER BY id''' % self._table_name
1207 1218
        cur.execute(sql_statement, {'id': self.id})
......
1218 1229
    @classmethod
1219 1230
    def _row2evo(cls, row, formdata):
1220 1231
        o = wcs.formdata.Evolution(formdata)
1221
        o._sql_id, o.who, o.status, o.time, o.comment = [str_encode(x) for x in tuple(row[:5])]
1232
        o._sql_id, o.who, o.status, o.time, o.last_jump_datetime, o.comment = [
1233
                str_encode(x) for x in tuple(row[:6])]
1222 1234
        if o.time:
1223 1235
            o.time = o.time.timetuple()
1224
        if row[5]:
1225
            o.parts = cPickle.loads(str(row[5]))
1236
        if row[6]:
1237
            o.parts = cPickle.loads(str(row[6]))
1226 1238
        return o
1227 1239

  
1228 1240
    def set_evolution(self, value):
......
1243 1255
        if not object_dict:
1244 1256
            return
1245 1257
        conn, cur = get_connection_and_cursor()
1246
        sql_statement = '''SELECT id, who, status, time, comment, parts, formdata_id
1258
        sql_statement = '''SELECT id, who, status, time, last_jump_datetime,
1259
                                  comment, parts, formdata_id
1247 1260
                             FROM %s_evolutions''' % cls._table_name
1248 1261
        sql_statement += ''' WHERE formdata_id IN %(object_ids)s ORDER BY id'''
1249 1262
        cur.execute(sql_statement, {'object_ids': tuple(object_dict.keys())})
......
1255 1268
            row = cur.fetchone()
1256 1269
            if row is None:
1257 1270
                break
1258
            _sql_id, who, status, time, comment, parts, formdata_id = tuple(row[:7])
1271
            _sql_id, who, status, time, last_jump_datetime, comment, parts, formdata_id = tuple(row[:8])
1259 1272
            formdata = object_dict.get(formdata_id)
1260 1273
            if not formdata:
1261 1274
                continue
......
1354 1367
                    sql_dict.update({'id': evo._sql_id})
1355 1368
                    sql_statement = '''UPDATE %s_evolutions SET
1356 1369
                                        time = %%(time)s,
1370
                                        last_jump_datetime = %%(last_jump_datetime)s,
1357 1371
                                        status = %%(status)s,
1358 1372
                                        comment = %%(comment)s,
1359 1373
                                        parts = %%(parts)s
......
1362 1376
                else:
1363 1377
                    sql_statement = '''INSERT INTO %s_evolutions (
1364 1378
                                               id, who, status,
1365
                                               time, comment, parts,
1379
                                               time, last_jump_datetime,
1380
                                               comment, parts,
1366 1381
                                               formdata_id)
1367 1382
                                        VALUES (DEFAULT, %%(who)s, %%(status)s,
1368
                                                %%(time)s, %%(comment)s,
1383
                                                %%(time)s, %%(last_jump_datetime)s,
1384
                                                %%(comment)s,
1369 1385
                                                %%(parts)s, %%(formdata_id)s)
1370 1386
                                     RETURNING id''' % self._table_name
1371 1387
                sql_dict.update({
1372 1388
                        'who': evo.who,
1373 1389
                        'status': evo.status,
1374 1390
                        'time': datetime.datetime.fromtimestamp(time.mktime(evo.time)),
1391
                        'last_jump_datetime': evo.last_jump_datetime,
1375 1392
                        'comment': evo.comment,
1376 1393
                        'formdata_id': self.id,
1377 1394
                })
......
2119 2136
    return result
2120 2137

  
2121 2138

  
2122
SQL_LEVEL = 26
2139
SQL_LEVEL = 27
2123 2140

  
2124 2141
def migrate_global_views(conn, cur):
2125 2142
    cur.execute('''SELECT COUNT(*) FROM information_schema.tables
......
2197 2214
        raise RuntimeError()
2198 2215
    if sql_level < 1: # 1: introduction of tracking_code table
2199 2216
        do_tracking_code_table()
2200
    if sql_level < 26:
2217
    if sql_level < 27:
2201 2218
        # 2: introduction of formdef_id in views
2202 2219
        # 5: add concerned_roles_array, is_at_endpoint and fts to views
2203 2220
        # 7: add backoffice_submission to tables
......
2212 2229
        # 20: remove user hash stuff
2213 2230
        # 22: rebuild views
2214 2231
        # 26: add digest to formdata
2232
        # 27: add last_jump_datetime in evolutions tables
2215 2233
        migrate_views(conn, cur)
2216 2234
    if sql_level < 21:
2217 2235
        # 3: introduction of _structured for user fields
wcs/wf/jump.py
243 243

  
244 244
        if self.timeout:
245 245
            timeout = int(self.compute(self.timeout))
246
            if formdata.evolution:
247
                last = formdata.evolution[-1].time
248
            else:
249
                last = formdata.receipt_time
246
            last = formdata.last_update_time
250 247
            if last:
251 248
                diff = time.time() - time.mktime(last)
252 249
                must_jump = (diff > timeout) and must_jump
wcs/workflows.py
1040 1040
            anchor_status = self.anchor_status_first or formdata.status
1041 1041
            for evolution in formdata.evolution:
1042 1042
                if evolution.status == anchor_status:
1043
                    anchor_date = evolution.time
1043
                    anchor_date = evolution.last_jump_datetime or evolution.time
1044 1044
                    break
1045 1045
        elif self.anchor == 'latest-arrival':
1046 1046
            anchor_status = self.anchor_status_latest or formdata.status
1047 1047
            for evolution in reversed(formdata.evolution):
1048 1048
                if evolution.status == anchor_status:
1049
                    anchor_date = evolution.time
1049
                    anchor_date = evolution.last_jump_datetime or evolution.time
1050 1050
                    break
1051 1051
        elif self.anchor == 'python':
1052 1052
            variables = get_publisher().substitutions.get_context_variables()
1053
-