0003-workflows-add-target-roles-in-commenter-workflow-ite.patch
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 |
- |