Projet

Général

Profil

0003-workflows-add-target-roles-in-commenter-workflow-ite.patch

Nicolas Roche, 16 février 2021 21:04

Télécharger (17,4 ko)

Voir les différences:

Subject: [PATCH 3/3] workflows: add target roles in commenter workflow item
 (#38254)

 tests/form_pages/test_formdata.py | 88 +++++++++++++++++++++++++++++
 tests/test_formdata.py            |  4 +-
 tests/test_workflow_import.py     | 33 +++++++++++
 tests/test_workflows.py           | 94 +++++++++++++++++++++++++++++++
 wcs/formdata.py                   |  2 +
 wcs/sql.py                        |  2 +
 wcs/wf/register_comment.py        | 23 +++++++-
 7 files changed, 241 insertions(+), 5 deletions(-)
tests/form_pages/test_formdata.py
1499 1499
    formdef.data_class().wipe()
1500 1500

  
1501 1501
    resp = login(get_app(pub), username='foo', password='foo').get('/test/')
1502 1502
    assert '>1st page<' in resp.text
1503 1503
    assert '>2nd page<' in resp.text
1504 1504
    assert '>3rd page<' not in resp.text
1505 1505
    assert '>4th page<' in resp.text
1506 1506
    assert len(http_requests.requests) == 1
1507

  
1508

  
1509
def test_formdata_evolution_registercommenter_to(pub):
1510
    user = create_user(pub)
1511

  
1512
    Role.wipe()
1513
    role1 = Role(name='role the user does not have')
1514
    role1.store()
1515
    role2 = Role(name='role the user does have')
1516
    role2.store()
1517
    user.roles = [role2.id]
1518
    user.store()
1519

  
1520
    wf = Workflow(name='status')
1521
    st1 = wf.add_status('Status1', 'st1')
1522
    comment = RegisterCommenterWorkflowStatusItem()
1523
    comment.id = '_comment'
1524
    comment.comment = 'Hello World'
1525
    comment.to = None
1526
    st1.items.append(comment)
1527
    comment.parent = st1
1528

  
1529
    wf.store()
1530

  
1531
    FormDef.wipe()
1532
    formdef = FormDef()
1533
    formdef.name = 'test'
1534
    formdef.workflow_id = wf.id
1535
    formdef.fields = []
1536
    formdef.store()
1537
    formdef.data_class().wipe()
1538

  
1539
    # register comment to all users
1540
    app = login(get_app(pub), username='foo', password='foo')
1541
    resp = app.get('/test/')
1542
    resp = resp.forms[0].submit('submit')
1543
    assert 'Check values then click submit.' in resp.text
1544
    resp = resp.forms[0].submit('submit')
1545
    assert resp.status_int == 302
1546
    resp = resp.follow()
1547
    assert 'The form has been recorded' in resp.text
1548

  
1549
    formdata = formdef.data_class().select()[0]
1550
    assert formdata.evolution[0].parts[0].content == 'Hello World'
1551
    assert formdata.evolution[0].parts[0].to is None
1552
    resp = app.get('/test/%s/' % formdata.id)
1553
    resp.status_int = 200
1554
    assert resp.html.find('div', {'id': 'evolution-log'}).find('p').text == 'Hello World'
1555

  
1556
    # register comment to other users
1557
    formdef.data_class().wipe()
1558
    comment.to = [role1.id]
1559
    wf.store()
1560

  
1561
    resp = app.get('/test/')
1562
    resp = resp.forms[0].submit('submit')
1563
    assert 'Check values then click submit.' in resp.text
1564
    resp = resp.forms[0].submit('submit')
1565
    assert resp.status_int == 302
1566
    resp = resp.follow()
1567
    assert 'The form has been recorded' in resp.text
1568

  
1569
    formdata = formdef.data_class().select()[0]
1570
    assert formdata.evolution[0].parts[0].content == 'Hello World'
1571
    assert formdata.evolution[0].parts[0].to == [role1.id]
1572
    resp = app.get('/test/%s/' % formdata.id)
1573
    resp.status_int = 200
1574
    assert not resp.html.find('div', {'id': 'evolution-log'}).find('p')
1575

  
1576
    # register comment to this user
1577
    formdef.data_class().wipe()
1578
    comment.to = [role2.id]
1579
    wf.store()
1580

  
1581
    resp = app.get('/test/')
1582
    resp = resp.forms[0].submit('submit')
1583
    assert 'Check values then click submit.' in resp.text
1584
    resp = resp.forms[0].submit('submit')
1585
    assert resp.status_int == 302
1586
    resp = resp.follow()
1587
    assert 'The form has been recorded' in resp.text
1588

  
1589
    formdata = formdef.data_class().select()[0]
1590
    assert formdata.evolution[0].parts[0].content == 'Hello World'
1591
    assert formdata.evolution[0].parts[0].to == [role2.id]
1592
    resp = app.get('/test/%s/' % formdata.id)
1593
    resp.status_int = 200
1594
    assert resp.html.find('div', {'id': 'evolution-log'}).find('p').text == 'Hello World'
tests/test_formdata.py
425 425
    d.user_id = local_user.id
426 426
    d.receipt_time = time.localtime()
427 427
    evo = Evolution()
428 428
    evo.time = time.localtime()
429 429
    evo.status = 'wf-%s' % st_new.id
430 430
    evo.who = '_submitter'
431 431
    d.evolution = [evo]
432 432
    d.store()
433
    evo.add_part(JournalEvolutionPart(d, "ok"))
433
    evo.add_part(JournalEvolutionPart(d, "ok", None))
434 434
    evo.add_part(JournalWsCallErrorPart("summary", "label", "data"))
435 435
    evo = Evolution()
436 436
    evo.time = time.localtime()
437 437
    evo.status = 'wf-%s' % st_finished.id
438 438
    evo.who = '_submitter'
439 439
    d.evolution.append(evo)
440 440
    d.store()
441 441

  
......
465 465
    export = d.get_json_export_dict(anonymise=True)
466 466
    assert 'evolution' in export
467 467
    assert len(export['evolution']) == 2
468 468
    assert export['evolution'][0]['status'] == st_new.id
469 469
    assert 'time' in export['evolution'][0]
470 470
    assert 'who' not in export['evolution'][0]
471 471
    assert 'parts' in export['evolution'][0]
472 472
    assert len(export['evolution'][0]['parts']) == 2
473
    assert len(export['evolution'][0]['parts'][0]) == 1
473
    assert len(export['evolution'][0]['parts'][0]) == 2
474 474
    assert export['evolution'][0]['parts'][0]['type'] == 'workflow-comment'
475 475
    assert len(export['evolution'][0]['parts'][1]) == 1
476 476
    assert export['evolution'][0]['parts'][1]['type'] == 'wscall-error'
477 477
    assert export['evolution'][1]['status'] == st_finished.id
478 478
    assert 'time' in export['evolution'][1]
479 479
    assert 'who' not in export['evolution'][0]
480 480
    assert 'parts' not in export['evolution'][1]
481 481

  
tests/test_workflow_import.py
476 476
    trigger.roles = [role.id]
477 477

  
478 478
    wf2 = assert_import_export_works(wf)
479 479
    assert wf2.global_actions[0].triggers[0].roles == [role.id]
480 480

  
481 481
    wf2 = assert_import_export_works(wf, True)
482 482

  
483 483

  
484
def test_register_comment_to(pub):
485
    role = Role()
486
    role.id = '5'
487
    role.name = 'Test Role'
488
    role.store()
489

  
490
    wf = Workflow(name='global actions')
491
    st1 = wf.add_status('Status1', 'st1')
492

  
493
    add_to_journal1 = RegisterCommenterWorkflowStatusItem()
494
    add_to_journal1.id = '_add_to_journal1'
495
    add_to_journal1.comment = 'HELLO WORLD'
496
    st1.items.append(add_to_journal1)
497
    add_to_journal1.parent = st1
498

  
499
    add_to_journal2 = RegisterCommenterWorkflowStatusItem()
500
    add_to_journal2.id = '_add_to_journal2'
501
    add_to_journal2.comment = 'OLA MUNDO'
502
    add_to_journal2.to = [role.id]
503
    st1.items.append(add_to_journal2)
504
    add_to_journal2.parent = st1
505
    assert wf.possible_status[0].items[0].to == None
506
    assert wf.possible_status[0].items[1].to == [role.id]
507

  
508
    xml_root = wf.export_to_xml()
509
    assert 'to' not in [x.tag for x in xml_root.findall('possible_status/status/items/item[1]/')]
510
    assert 'to' in [x.tag for x in xml_root.findall('possible_status/status/items/item[2]/')]
511

  
512
    wf2 = assert_import_export_works(wf)
513
    assert wf2.possible_status[0].items[0].to == []
514
    assert wf2.possible_status[0].items[1].to == [role.id]
515

  
516

  
484 517
def test_backoffice_fields(pub):
485 518
    wf = Workflow(name='bo fields')
486 519
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
487 520
    wf.backoffice_fields_formdef.fields = [
488 521
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
489 522
    ]
490 523
    wf2 = assert_import_export_works(wf, True)
491 524

  
tests/test_workflows.py
1148 1148
    assert formdata.evolution[-1].parts[0].orig_filename == 'hello.txt'
1149 1149

  
1150 1150
    assert isinstance(formdata.evolution[-1].parts[1], JournalEvolutionPart)
1151 1151
    assert len(formdata.evolution[-1].parts[1].content) > 0
1152 1152
    comment_view = str(formdata.evolution[-1].parts[1].view())
1153 1153
    assert comment_view == '<p>%s</p>' % comment_text
1154 1154

  
1155 1155

  
1156
def test_register_comment_to(pub):
1157
    workflow = Workflow(name='register comment to')
1158
    st1 = workflow.add_status('Status1', 'st1')
1159

  
1160
    role = Role(name='foorole')
1161
    role.store()
1162
    role2 = Role(name='no-one-role')
1163
    role2.store()
1164
    user = pub.user_class(name='baruser')
1165
    user.roles = []
1166
    user.store()
1167

  
1168
    FormDef.wipe()
1169
    formdef = FormDef()
1170
    formdef.url_name = 'foobar'
1171
    formdef._workflow = workflow
1172

  
1173
    formdata = formdef.data_class()()
1174
    formdata.just_created()
1175
    assert formdata.status == 'wf-st1'
1176
    formdata.store()
1177

  
1178
    register_commenter = RegisterCommenterWorkflowStatusItem()
1179
    register_commenter.parent = st1
1180
    st1.items.append(register_commenter)
1181

  
1182
    def display_parts():
1183
        formdata.evolution[-1]._display_parts = None  # invalidate cache
1184
        return [str(x) for x in formdata.evolution[-1].display_parts()]
1185

  
1186
    register_commenter.comment = 'all'
1187
    register_commenter.to = None
1188
    register_commenter.perform(formdata)
1189
    assert len(formdata.evolution[-1].parts) == 1
1190
    assert display_parts() == ['<p>all</p>']
1191

  
1192
    register_commenter.comment = 'to-role'
1193
    register_commenter.to = [role.id]
1194
    register_commenter.perform(formdata)
1195
    assert len(formdata.evolution[-1].parts) == 2
1196
    assert len(display_parts()) == 1
1197
    pub._request._user = user
1198
    assert display_parts() == ['<p>all</p>']
1199
    user.roles = [role.id]
1200
    assert display_parts() == ['<p>all</p>', '<p>to-role</p>']
1201

  
1202
    user.roles = []
1203
    register_commenter.comment = 'to-submitter'
1204
    register_commenter.to = ['_submitter']
1205
    register_commenter.perform(formdata)
1206
    assert len(formdata.evolution[-1].parts) == 3
1207
    assert display_parts() == ['<p>all</p>']
1208
    formdata.user_id = user.id
1209
    assert display_parts() == ['<p>all</p>', '<p>to-submitter</p>']
1210

  
1211
    register_commenter.comment = 'to-role-or-submitter'
1212
    register_commenter.to = [role.id, '_submitter']
1213
    register_commenter.perform(formdata)
1214
    assert len(formdata.evolution[-1].parts) == 4
1215
    assert display_parts() == ['<p>all</p>', '<p>to-submitter</p>', '<p>to-role-or-submitter</p>']
1216
    formdata.user_id = None
1217
    assert display_parts() == ['<p>all</p>']
1218
    user.roles = [role.id]
1219
    assert display_parts() == ['<p>all</p>', '<p>to-role</p>', '<p>to-role-or-submitter</p>']
1220
    formdata.user_id = user.id
1221
    assert display_parts() == [
1222
        '<p>all</p>',
1223
        '<p>to-role</p>',
1224
        '<p>to-submitter</p>',
1225
        '<p>to-role-or-submitter</p>',
1226
    ]
1227

  
1228
    register_commenter.comment = 'd1'
1229
    register_commenter.to = [role2.id]
1230
    register_commenter.perform(formdata)
1231
    assert len(formdata.evolution[-1].parts) == 5
1232
    assert display_parts() == [
1233
        '<p>all</p>',
1234
        '<p>to-role</p>',
1235
        '<p>to-submitter</p>',
1236
        '<p>to-role-or-submitter</p>',
1237
    ]
1238
    register_commenter2 = RegisterCommenterWorkflowStatusItem()
1239
    register_commenter2.parent = st1
1240
    st1.items.append(register_commenter2)
1241
    register_commenter2.comment = 'd2'
1242
    register_commenter2.to = [role.id, '_submitter']
1243
    user.roles = [role.id, role2.id]
1244
    register_commenter2.perform(formdata)
1245
    assert len(formdata.evolution[-1].parts) == 6
1246
    assert '<p>d1</p>' in [str(x) for x in display_parts()]
1247
    assert '<p>d2</p>' in [str(x) for x in display_parts()]
1248

  
1249

  
1156 1250
def test_email(pub, emails):
1157 1251
    pub.substitutions.feed(MockSubstitutionVariables())
1158 1252

  
1159 1253
    formdef = FormDef()
1160 1254
    formdef.name = 'baz'
1161 1255
    formdef.fields = []
1162 1256
    formdef.store()
1163 1257

  
wcs/formdata.py
152 152

  
153 153
        if not self.parts:
154 154
            return []
155 155

  
156 156
        l = []
157 157
        for p in self.parts:
158 158
            if not hasattr(p, 'view'):
159 159
                continue
160
            if hasattr(p, 'to') and not self.formdata.is_for_current_user(p.to):
161
                continue
160 162
            text = p.view()
161 163
            if text:
162 164
                l.append(text)
163 165
        self._display_parts = l
164 166
        return self._display_parts
165 167

  
166 168
    def get_json_export_dict(self, user, anonymise=False):
167 169
        data = {
wcs/sql.py
2017 2017
                elif type(value) in (tuple, list):
2018 2018
                    fts_strings.extend(value)
2019 2019
        if self._evolution:
2020 2020
            for evo in self._evolution:
2021 2021
                if evo.comment:
2022 2022
                    fts_strings.append(evo.comment)
2023 2023
                for part in evo.parts or []:
2024 2024
                    if hasattr(part, 'view'):
2025
                        if hasattr(part, 'to') and not self.is_for_current_user(part.to):
2026
                            continue
2025 2027
                        html_part = part.view()
2026 2028
                        if html_part:
2027 2029
                            fts_strings.append(qommon.misc.html2text(html_part))
2028 2030
        user = self.get_user()
2029 2031
        if user:
2030 2032
            fts_strings.append(user.get_display_name())
2031 2033

  
2032 2034
        sql_statement = (
wcs/wf/register_comment.py
26 26
    AttachmentEvolutionPart,
27 27
)
28 28

  
29 29
import sys
30 30

  
31 31

  
32 32
class JournalEvolutionPart:  # pylint: disable=C1001
33 33
    content = None
34
    to = None
34 35

  
35
    def __init__(self, formdata, message):
36
    def __init__(self, formdata, message, to):
36 37
        if not message:
37 38
            return
39
        self.to = to
38 40
        if '{{' in message or '{%' in message:
39 41
            # django template
40 42
            content = template_on_formdata(formdata, message)
41 43
            if content and not content.startswith('<'):
42 44
                # add <div> to mark the string as processed as HTML
43 45
                content = '<div>%s</div>' % content
44 46
            self.content = content
45 47
            return
......
63 65
                htmltext('<p>')
64 66
                + htmltext('\n').join([(x or htmltext('</p><p>')) for x in self.content.splitlines()])
65 67
                + htmltext('</p>')
66 68
            )
67 69

  
68 70
    def get_json_export_dict(self, anonymise=False):
69 71
        d = {
70 72
            'type': 'workflow-comment',
73
            'to': self.to,
71 74
        }
72 75
        if not anonymise:
73 76
            d['content'] = self.content
74 77
        return d
75 78

  
76 79

  
77 80
class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem):
78 81
    description = N_('History Message')
79 82
    key = 'register-comment'
80 83
    category = 'interaction'
81 84

  
82 85
    comment = None
86
    to = None
83 87
    attachments = None
84 88

  
85 89
    def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
86 90
        super(RegisterCommenterWorkflowStatusItem, self).add_parameters_widgets(
87 91
            form, parameters, prefix=prefix, formdef=formdef
88 92
        )
89 93
        if 'comment' in parameters:
90 94
            form.add(
91 95
                TextWidget, '%scomment' % prefix, title=_('Message'), value=self.comment, cols=80, rows=10
92 96
            )
97
        if 'to' in parameters:
98
            form.add(
99
                WidgetList,
100
                '%sto' % prefix,
101
                title=_('To'),
102
                element_type=SingleSelectWidget,
103
                value=self.to or [],
104
                add_element_label=self.get_add_role_label(),
105
                element_kwargs={
106
                    'render_br': False,
107
                    'options': [(None, '---', None)] + self.get_list_of_roles(include_logged_in_users=False),
108
                },
109
            )
93 110

  
94 111
    def get_parameters(self):
95
        return ('comment', 'attachments', 'condition')
112
        return ('comment', 'to', 'attachments', 'condition')
96 113

  
97 114
    def attach_uploads_to_formdata(self, formdata, uploads):
98 115
        if not formdata.evolution[-1].parts:
99 116
            formdata.evolution[-1].parts = []
100 117
        for upload in uploads:
101 118
            try:
102 119
                # useless but required to restore upload.fp from serialized state,
103 120
                # needed by AttachmentEvolutionPart.from_upload()
......
115 132
        # (with substitution vars)
116 133
        if self.attachments:
117 134
            uploads = self.convert_attachments_to_uploads()
118 135
            self.attach_uploads_to_formdata(formdata, uploads)
119 136
            formdata.store()  # store and invalidate cache, so references can be used in the comment message.
120 137

  
121 138
        # the comment can use attachments done above
122 139
        try:
123
            formdata.evolution[-1].add_part(JournalEvolutionPart(formdata, self.comment))
140
            formdata.evolution[-1].add_part(JournalEvolutionPart(formdata, self.comment, self.to))
124 141
            formdata.store()
125 142
        except TemplateError as e:
126 143
            url = formdata.get_url()
127 144
            get_logger().error(
128 145
                'error in template for comment [%s], ' 'comment could not be generated: %s' % (url, str(e))
129 146
            )
130 147

  
131 148

  
132
-