0001-misc-remap-statuses-in-a-transaction-38579.patch
tests/admin_pages/test_form.py | ||
---|---|---|
517 | 517 |
formdata2.status = 'draft' |
518 | 518 |
formdata2.store() |
519 | 519 | |
520 |
formdata3 = data_class() |
|
521 |
formdata3.status = 'wf-1' |
|
522 |
formdata3.store() |
|
523 | ||
520 | 524 |
Workflow.wipe() |
521 | 525 |
workflow = Workflow(name='Workflow One') |
522 | 526 |
workflow.store() |
... | ... | |
538 | 542 |
assert len(resp.forms[0]['mapping-%s' % status.id].options) == 1 |
539 | 543 |
assert data_class.get(formdata1.id).status == 'wf-new' |
540 | 544 |
assert data_class.get(formdata2.id).status == 'draft' |
545 |
assert data_class.get(formdata3.id).status == 'wf-1' |
|
541 | 546 |
resp = resp.forms[0].submit() |
542 | 547 |
assert data_class.get(formdata1.id).status == 'wf-finished' |
543 | 548 |
assert data_class.get(formdata2.id).status == 'draft' |
549 |
assert data_class.get(formdata3.id).status == 'wf-1-invalid-_default' |
|
544 | 550 | |
545 | 551 |
# change to another workflow, with no mapping change |
546 | 552 |
workflow2 = workflow |
... | ... | |
561 | 567 |
resp = resp.forms[0].submit() |
562 | 568 |
assert data_class.get(formdata1.id).status == 'wf-finished' |
563 | 569 |
assert data_class.get(formdata2.id).status == 'draft' |
570 |
assert data_class.get(formdata3.id).status == 'wf-1-invalid-_default' |
|
564 | 571 | |
565 | 572 | |
566 | 573 |
def test_form_submitter_roles(pub): |
wcs/admin/forms.py | ||
---|---|---|
1069 | 1069 |
if workflow_id is None: |
1070 | 1070 |
workflow_id = self.formdef_default_workflow |
1071 | 1071 |
return redirect('workflow-status-remapping?new=%s' % workflow_id) |
1072 |
self.formdef.workflow_id = workflow_id |
|
1073 |
self.formdef.store(comment=_('Workflow change')) |
|
1072 |
self.formdef.change_workflow(workflow_id) |
|
1074 | 1073 |
return redirect('.') |
1075 | 1074 | |
1076 | 1075 |
def workflow_status_remapping(self): |
... | ... | |
1109 | 1108 |
r += form.render() |
1110 | 1109 |
return r.getvalue() |
1111 | 1110 |
else: |
1112 |
get_logger().info( |
|
1113 |
'admin - form "%s", workflow is now "%s" (was "%s")' |
|
1114 |
% (self.formdef.name, new_workflow.name, self.formdef.workflow.name) |
|
1115 |
) |
|
1116 |
self.workflow_status_remapping_submit(form) |
|
1117 |
if new_workflow.id == self.formdef_default_workflow: |
|
1118 |
self.formdef.workflow_id = None |
|
1119 |
else: |
|
1120 |
self.formdef.workflow_id = new_workflow.id |
|
1121 |
self.formdef.store(comment=_('Workflow change')) |
|
1122 |
# instruct formdef to update its security rules |
|
1123 |
self.formdef.data_class().rebuild_security() |
|
1124 |
return redirect('.') |
|
1111 |
return self.workflow_status_remapping_submit(form, new_workflow) |
|
1112 | ||
1113 |
def workflow_status_remapping_submit(self, form, new_workflow): |
|
1114 |
get_logger().info( |
|
1115 |
'admin - form "%s", workflow is now "%s" (was "%s")' |
|
1116 |
% (self.formdef.name, new_workflow.name, self.formdef.workflow.name) |
|
1117 |
) |
|
1125 | 1118 | |
1126 |
def workflow_status_remapping_submit(self, form): |
|
1127 | 1119 |
status_mapping = {} |
1128 | 1120 |
for status in self.formdef.workflow.possible_status: |
1129 |
status_mapping['wf-%s' % status.id] = 'wf-%s' % form.get_widget('mapping-%s' % status.id).parse() |
|
1130 |
if any([x[0] != x[1] for x in status_mapping.items()]): |
|
1131 |
# if there are status changes, update all formdatas (except drafts) |
|
1132 |
status_mapping.update({'draft': 'draft'}) |
|
1133 |
for item in self.formdef.data_class().select([NotEqual('status', 'draft')]): |
|
1134 |
item.status = status_mapping.get(item.status) |
|
1135 |
if item.evolution: |
|
1136 |
for evo in item.evolution: |
|
1137 |
evo.status = status_mapping.get(evo.status) |
|
1138 |
item.store() |
|
1121 |
status_mapping[status.id] = form.get_widget('mapping-%s' % status.id).parse() |
|
1122 | ||
1123 |
if new_workflow.id == self.formdef_default_workflow: |
|
1124 |
new_workflow_id = None |
|
1125 |
else: |
|
1126 |
new_workflow_id = new_workflow.id |
|
1127 |
self.formdef.change_workflow(new_workflow_id, status_mapping) |
|
1128 |
return redirect('.') |
|
1139 | 1129 | |
1140 | 1130 |
def get_preview(self): |
1141 | 1131 |
form = Form(action='#', use_tokens=False) |
wcs/formdef.py | ||
---|---|---|
50 | 50 |
from .qommon.storage import Equal |
51 | 51 |
from .qommon.storage import StorableObject |
52 | 52 |
from .qommon.storage import fix_key |
53 |
from .qommon.storage import NotEqual |
|
53 | 54 |
from .qommon.substitution import Substitutions |
54 | 55 |
from .roles import logged_users_role |
55 | 56 | |
... | ... | |
1580 | 1581 |
# chunk contains the fields. |
1581 | 1582 |
return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2) |
1582 | 1583 | |
1584 |
def change_workflow(self, new_workflow_id, status_mapping=None): |
|
1585 |
old_workflow = self.get_workflow() |
|
1586 | ||
1587 |
formdata_count = self.data_class().count() |
|
1588 |
if formdata_count: |
|
1589 |
assert status_mapping, 'status mapping is required if there are formdatas' |
|
1590 |
assert all( |
|
1591 |
status.id in status_mapping for status in old_workflow.possible_status |
|
1592 |
), 'a status was not mapped' |
|
1593 | ||
1594 |
mapping = {} |
|
1595 |
for old_status, new_status in status_mapping.items(): |
|
1596 |
mapping['wf-%s' % old_status] = 'wf-%s' % new_status |
|
1597 |
mapping['draft'] = 'draft' |
|
1598 | ||
1599 |
if any([x[0] != x[1] for x in mapping.items()]): |
|
1600 |
# if there are status changes, update all formdatas (except drafts) |
|
1601 |
if get_publisher().is_using_postgresql(): |
|
1602 |
from . import sql |
|
1603 | ||
1604 |
sql.formdef_remap_statuses(self, mapping) |
|
1605 |
else: |
|
1606 | ||
1607 |
def map_status(status): |
|
1608 |
if status is None: |
|
1609 |
return None |
|
1610 |
elif status in mapping: |
|
1611 |
return mapping[status] |
|
1612 |
elif '-invalid-' in status: |
|
1613 |
return status |
|
1614 |
else: |
|
1615 |
return '%s-invalid-%s' % (status, old_workflow.id) |
|
1616 | ||
1617 |
for formdata in self.data_class().select([NotEqual('status', 'draft')]): |
|
1618 |
formdata.status = map_status(formdata.status) |
|
1619 |
if formdata.evolution: |
|
1620 |
for evo in formdata.evolution: |
|
1621 |
evo.status = map_status(evo.status) |
|
1622 |
formdata.store() |
|
1623 | ||
1624 |
self.workflow_id = new_workflow_id |
|
1625 |
self.store(comment=_('Workflow change')) |
|
1626 |
if formdata_count: |
|
1627 |
# instruct formdef to update its security rules |
|
1628 |
self.data_class().rebuild_security() |
|
1629 | ||
1583 | 1630 | |
1584 | 1631 |
from .qommon.admin.emails import EmailsDirectory |
1585 | 1632 |
wcs/sql.py | ||
---|---|---|
3511 | 3511 | |
3512 | 3512 |
conn.commit() |
3513 | 3513 |
cur.close() |
3514 | ||
3515 | ||
3516 |
@guard_postgres |
|
3517 |
def formdef_remap_statuses(formdef, mapping): |
|
3518 |
conn, cur = get_connection_and_cursor() |
|
3519 |
table_name = get_formdef_table_name(formdef) |
|
3520 |
evolutions_table_name = table_name + '_evolutions' |
|
3521 |
old_workflow_id = formdef.workflow_id or '_default' |
|
3522 |
args = [] |
|
3523 |
case_expression = '(CASE ' |
|
3524 |
case_expression += 'WHEN status IS NULL THEN NULL ' |
|
3525 |
for old_id, new_id in mapping.items(): |
|
3526 |
case_expression += "WHEN status = %s THEN %s " |
|
3527 |
args.extend([old_id, new_id]) |
|
3528 |
case_expression += " WHEN status LIKE '%%-invalid-%%' THEN status " |
|
3529 |
case_expression += " ELSE (status || '-invalid-' || %s) END)" |
|
3530 |
args.append(old_workflow_id) |
|
3531 | ||
3532 |
cur.execute('BEGIN') |
|
3533 |
cur.execute('UPDATE %s SET status = %s WHERE status <> \'draft\'' % (table_name, case_expression), args) |
|
3534 |
cur.execute('UPDATE %s SET status = %s' % (evolutions_table_name, case_expression), args) |
|
3535 |
cur.execute('COMMIT') |
|
3514 |
- |