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 | ||
---|---|---|
1084 | 1084 |
if workflow_id is None: |
1085 | 1085 |
workflow_id = self.formdef_default_workflow |
1086 | 1086 |
return redirect('workflow-status-remapping?new=%s' % workflow_id) |
1087 |
self.formdef.workflow_id = workflow_id |
|
1088 |
self.formdef.store(comment=_('Workflow change')) |
|
1087 |
self.formdef.change_workflow(workflow_id) |
|
1089 | 1088 |
return redirect('.') |
1090 | 1089 | |
1091 | 1090 |
def workflow_status_remapping(self): |
... | ... | |
1124 | 1123 |
r += form.render() |
1125 | 1124 |
return r.getvalue() |
1126 | 1125 |
else: |
1127 |
get_logger().info( |
|
1128 |
'admin - form "%s", workflow is now "%s" (was "%s")' |
|
1129 |
% (self.formdef.name, new_workflow.name, self.formdef.workflow.name) |
|
1130 |
) |
|
1131 |
self.workflow_status_remapping_submit(form) |
|
1132 |
if new_workflow.id == self.formdef_default_workflow: |
|
1133 |
self.formdef.workflow_id = None |
|
1134 |
else: |
|
1135 |
self.formdef.workflow_id = new_workflow.id |
|
1136 |
self.formdef.store(comment=_('Workflow change')) |
|
1137 |
# instruct formdef to update its security rules |
|
1138 |
self.formdef.data_class().rebuild_security() |
|
1139 |
return redirect('.') |
|
1126 |
return self.workflow_status_remapping_submit(form, new_workflow) |
|
1127 | ||
1128 |
def workflow_status_remapping_submit(self, form, new_workflow): |
|
1129 |
get_logger().info( |
|
1130 |
'admin - form "%s", workflow is now "%s" (was "%s")' |
|
1131 |
% (self.formdef.name, new_workflow.name, self.formdef.workflow.name) |
|
1132 |
) |
|
1140 | 1133 | |
1141 |
def workflow_status_remapping_submit(self, form): |
|
1142 | 1134 |
status_mapping = {} |
1143 | 1135 |
for status in self.formdef.workflow.possible_status: |
1144 |
status_mapping['wf-%s' % status.id] = 'wf-%s' % form.get_widget('mapping-%s' % status.id).parse() |
|
1145 |
if any(x[0] != x[1] for x in status_mapping.items()): |
|
1146 |
# if there are status changes, update all formdatas (except drafts) |
|
1147 |
status_mapping.update({'draft': 'draft'}) |
|
1148 |
for item in self.formdef.data_class().select([NotEqual('status', 'draft')]): |
|
1149 |
item.status = status_mapping.get(item.status) |
|
1150 |
if item.evolution: |
|
1151 |
for evo in item.evolution: |
|
1152 |
evo.status = status_mapping.get(evo.status) |
|
1153 |
item.store() |
|
1136 |
status_mapping[status.id] = form.get_widget('mapping-%s' % status.id).parse() |
|
1137 | ||
1138 |
if new_workflow.id == self.formdef_default_workflow: |
|
1139 |
new_workflow_id = None |
|
1140 |
else: |
|
1141 |
new_workflow_id = new_workflow.id |
|
1142 |
self.formdef.change_workflow(new_workflow_id, status_mapping) |
|
1143 |
return redirect('.') |
|
1154 | 1144 | |
1155 | 1145 |
def get_preview(self): |
1156 | 1146 |
form = Form(action='#', use_tokens=False) |
wcs/formdef.py | ||
---|---|---|
54 | 54 |
from .qommon.misc import xml_node_text |
55 | 55 |
from .qommon.publisher import get_publisher_class |
56 | 56 |
from .qommon.storage import Equal |
57 |
from .qommon.storage import NotEqual |
|
57 | 58 |
from .qommon.storage import StorableObject |
58 | 59 |
from .qommon.storage import fix_key |
59 | 60 |
from .qommon.substitution import Substitutions |
... | ... | |
1582 | 1583 |
# chunk contains the fields. |
1583 | 1584 |
return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2) |
1584 | 1585 | |
1586 |
def change_workflow(self, new_workflow_id, status_mapping=None): |
|
1587 |
old_workflow = self.get_workflow() |
|
1588 | ||
1589 |
formdata_count = self.data_class().count() |
|
1590 |
if formdata_count: |
|
1591 |
assert status_mapping, 'status mapping is required if there are formdatas' |
|
1592 |
assert all( |
|
1593 |
status.id in status_mapping for status in old_workflow.possible_status |
|
1594 |
), 'a status was not mapped' |
|
1595 | ||
1596 |
mapping = {} |
|
1597 |
for old_status, new_status in status_mapping.items(): |
|
1598 |
mapping['wf-%s' % old_status] = 'wf-%s' % new_status |
|
1599 |
mapping['draft'] = 'draft' |
|
1600 | ||
1601 |
if any([x[0] != x[1] for x in mapping.items()]): |
|
1602 |
# if there are status changes, update all formdatas (except drafts) |
|
1603 |
if get_publisher().is_using_postgresql(): |
|
1604 |
from . import sql |
|
1605 | ||
1606 |
sql.formdef_remap_statuses(self, mapping) |
|
1607 |
else: |
|
1608 | ||
1609 |
def map_status(status): |
|
1610 |
if status is None: |
|
1611 |
return None |
|
1612 |
elif status in mapping: |
|
1613 |
return mapping[status] |
|
1614 |
elif '-invalid-' in status: |
|
1615 |
return status |
|
1616 |
else: |
|
1617 |
return '%s-invalid-%s' % (status, old_workflow.id) |
|
1618 | ||
1619 |
for formdata in self.data_class().select([NotEqual('status', 'draft')]): |
|
1620 |
formdata.status = map_status(formdata.status) |
|
1621 |
if formdata.evolution: |
|
1622 |
for evo in formdata.evolution: |
|
1623 |
evo.status = map_status(evo.status) |
|
1624 |
formdata.store() |
|
1625 | ||
1626 |
self.workflow_id = new_workflow_id |
|
1627 |
self.store(comment=_('Workflow change')) |
|
1628 |
if formdata_count: |
|
1629 |
# instruct formdef to update its security rules |
|
1630 |
self.data_class().rebuild_security() |
|
1631 | ||
1585 | 1632 | |
1586 | 1633 |
EmailsDirectory.register( |
1587 | 1634 |
'new_user', |
wcs/sql.py | ||
---|---|---|
3508 | 3508 | |
3509 | 3509 |
conn.commit() |
3510 | 3510 |
cur.close() |
3511 | ||
3512 | ||
3513 |
@guard_postgres |
|
3514 |
def formdef_remap_statuses(formdef, mapping): |
|
3515 |
conn, cur = get_connection_and_cursor() |
|
3516 |
table_name = get_formdef_table_name(formdef) |
|
3517 |
evolutions_table_name = table_name + '_evolutions' |
|
3518 |
old_workflow_id = formdef.workflow_id or '_default' |
|
3519 |
args = [] |
|
3520 |
case_expression = '(CASE ' |
|
3521 |
case_expression += 'WHEN status IS NULL THEN NULL ' |
|
3522 |
for old_id, new_id in mapping.items(): |
|
3523 |
case_expression += "WHEN status = %s THEN %s " |
|
3524 |
args.extend([old_id, new_id]) |
|
3525 |
case_expression += " WHEN status LIKE '%%-invalid-%%' THEN status " |
|
3526 |
case_expression += " ELSE (status || '-invalid-' || %s) END)" |
|
3527 |
args.append(old_workflow_id) |
|
3528 | ||
3529 |
cur.execute('BEGIN') |
|
3530 |
cur.execute('UPDATE %s SET status = %s WHERE status <> \'draft\'' % (table_name, case_expression), args) |
|
3531 |
cur.execute('UPDATE %s SET status = %s' % (evolutions_table_name, case_expression), args) |
|
3532 |
cur.execute('COMMIT') |
|
3511 |
- |