0002-misc-remap-statuses-in-a-transaction-38579.patch
tests/admin_pages/test_form.py | ||
---|---|---|
513 | 513 |
formdata2.status = 'draft' |
514 | 514 |
formdata2.store() |
515 | 515 | |
516 |
formdata3 = data_class() |
|
517 |
formdata3.status = 'wf-1' |
|
518 |
formdata3.store() |
|
519 | ||
516 | 520 |
Workflow.wipe() |
517 | 521 |
workflow = Workflow(name='Workflow One') |
518 | 522 |
workflow.store() |
... | ... | |
534 | 538 |
assert len(resp.forms[0]['mapping-%s' % status.id].options) == 1 |
535 | 539 |
assert data_class.get(formdata1.id).status == 'wf-new' |
536 | 540 |
assert data_class.get(formdata2.id).status == 'draft' |
541 |
assert data_class.get(formdata3.id).status == 'wf-1' |
|
537 | 542 |
resp = resp.forms[0].submit() |
538 | 543 |
assert data_class.get(formdata1.id).status == 'wf-finished' |
539 | 544 |
assert data_class.get(formdata2.id).status == 'draft' |
545 |
assert data_class.get(formdata3.id).status == 'wf-1-invalid-_default' |
|
540 | 546 | |
541 | 547 |
# change to another workflow, with no mapping change |
542 | 548 |
workflow2 = workflow |
... | ... | |
557 | 563 |
resp = resp.forms[0].submit() |
558 | 564 |
assert data_class.get(formdata1.id).status == 'wf-finished' |
559 | 565 |
assert data_class.get(formdata2.id).status == 'draft' |
566 |
assert data_class.get(formdata3.id).status == 'wf-1-invalid-_default' |
|
560 | 567 | |
561 | 568 | |
562 | 569 |
def test_form_submitter_roles(pub): |
wcs/admin/forms.py | ||
---|---|---|
864 | 864 |
if workflow_id is None: |
865 | 865 |
workflow_id = self.formdef_default_workflow |
866 | 866 |
return redirect('workflow-status-remapping?new=%s' % workflow_id) |
867 |
self.formdef.workflow_id = workflow_id |
|
868 |
self.formdef.store(comment=_('Workflow change')) |
|
867 |
self.formdef.change_workflow(workflow_id) |
|
869 | 868 |
return redirect('.') |
870 | 869 | |
871 | 870 |
def workflow_status_remapping(self): |
... | ... | |
898 | 897 |
r += form.render() |
899 | 898 |
return r.getvalue() |
900 | 899 |
else: |
901 |
get_logger().info('admin - form "%s", workflow is now "%s" (was "%s")' % ( |
|
902 |
self.formdef.name, new_workflow.name, self.formdef.workflow.name)) |
|
903 |
self.workflow_status_remapping_submit(form) |
|
904 |
if new_workflow.id == self.formdef_default_workflow: |
|
905 |
self.formdef.workflow_id = None |
|
906 |
else: |
|
907 |
self.formdef.workflow_id = new_workflow.id |
|
908 |
self.formdef.store(comment=_('Workflow change')) |
|
909 |
# instruct formdef to update its security rules |
|
910 |
self.formdef.data_class().rebuild_security() |
|
911 |
return redirect('.') |
|
900 |
return self.workflow_status_remapping_submit(form, new_workflow) |
|
901 | ||
902 |
def workflow_status_remapping_submit(self, form, new_workflow): |
|
903 |
get_logger().info('admin - form "%s", workflow is now "%s" (was "%s")' % ( |
|
904 |
self.formdef.name, new_workflow.name, self.formdef.workflow.name)) |
|
912 | 905 | |
913 |
def workflow_status_remapping_submit(self, form): |
|
914 | 906 |
status_mapping = {} |
915 | 907 |
for status in self.formdef.workflow.possible_status: |
916 |
status_mapping['wf-%s' % status.id] = 'wf-%s' % \ |
|
917 |
form.get_widget('mapping-%s' % status.id).parse() |
|
918 |
if any([x[0] != x[1] for x in status_mapping.items()]): |
|
919 |
# if there are status changes, update all formdatas (except drafts) |
|
920 |
status_mapping.update({'draft': 'draft'}) |
|
921 |
for item in self.formdef.data_class().select([NotEqual('status', 'draft')]): |
|
922 |
item.status = status_mapping.get(item.status) |
|
923 |
if item.evolution: |
|
924 |
for evo in item.evolution: |
|
925 |
evo.status = status_mapping.get(evo.status) |
|
926 |
item.store() |
|
908 |
status_mapping[status.id] = form.get_widget('mapping-%s' % status.id).parse() |
|
909 | ||
910 |
if new_workflow.id == self.formdef_default_workflow: |
|
911 |
new_workflow_id = None |
|
912 |
else: |
|
913 |
new_workflow_id = new_workflow.id |
|
914 |
self.formdef.change_workflow(new_workflow_id, status_mapping) |
|
915 |
return redirect('.') |
|
927 | 916 | |
928 | 917 |
def get_preview(self): |
929 | 918 |
form = Form(action='#', use_tokens=False) |
wcs/formdef.py | ||
---|---|---|
33 | 33 |
from quixote.http_request import Upload |
34 | 34 | |
35 | 35 |
from .qommon import _, N_, force_str, PICKLE_KWARGS |
36 |
from .qommon.storage import StorableObject, fix_key, Equal |
|
36 |
from .qommon.storage import StorableObject, fix_key, Equal, NotEqual
|
|
37 | 37 |
from .qommon.cron import CronJob |
38 | 38 |
from .qommon.form import * |
39 | 39 |
from .qommon.misc import simplify, get_as_datetime, xml_node_text |
... | ... | |
1517 | 1517 |
# chunk contains the fields. |
1518 | 1518 |
return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2) |
1519 | 1519 | |
1520 |
def change_workflow(self, new_workflow_id, status_mapping=None): |
|
1521 |
old_workflow = self.get_workflow() |
|
1522 | ||
1523 |
formdata_count = self.data_class().count() |
|
1524 |
if formdata_count: |
|
1525 |
assert status_mapping, 'status mapping is required if there are formdatas' |
|
1526 |
assert all(status.id in status_mapping for status in old_workflow.possible_status), ( |
|
1527 |
'a status was not mapped' |
|
1528 |
) |
|
1529 | ||
1530 |
mapping = {} |
|
1531 |
for old_status, new_status in status_mapping.items(): |
|
1532 |
mapping['wf-%s' % old_status] = 'wf-%s' % new_status |
|
1533 |
mapping['draft'] = 'draft' |
|
1534 | ||
1535 |
if any([x[0] != x[1] for x in mapping.items()]): |
|
1536 |
# if there are status changes, update all formdatas (except drafts) |
|
1537 |
if get_publisher().is_using_postgresql(): |
|
1538 |
from . import sql |
|
1539 |
sql.formdef_remap_statuses(self, mapping) |
|
1540 |
else: |
|
1541 |
def map_status(status): |
|
1542 |
if status is None: |
|
1543 |
return None |
|
1544 |
elif status in mapping: |
|
1545 |
return mapping[status] |
|
1546 |
elif '-invalid-' in status: |
|
1547 |
return status |
|
1548 |
else: |
|
1549 |
return '%s-invalid-%s' % (status, old_workflow.id) |
|
1550 |
for formdata in self.data_class().select([NotEqual('status', 'draft')]): |
|
1551 |
formdata.status = map_status(formdata.status) |
|
1552 |
if formdata.evolution: |
|
1553 |
for evo in formdata.evolution: |
|
1554 |
evo.status = map_status(evo.status) |
|
1555 |
formdata.store() |
|
1556 | ||
1557 |
self.workflow_id = new_workflow_id |
|
1558 |
self.store(comment=_('Workflow change')) |
|
1559 |
if formdata_count: |
|
1560 |
# instruct formdef to update its security rules |
|
1561 |
self.data_class().rebuild_security() |
|
1562 | ||
1520 | 1563 | |
1521 | 1564 |
from .qommon.admin.emails import EmailsDirectory |
1522 | 1565 |
wcs/sql.py | ||
---|---|---|
2874 | 2874 | |
2875 | 2875 |
conn.commit() |
2876 | 2876 |
cur.close() |
2877 | ||
2878 | ||
2879 |
@guard_postgres |
|
2880 |
def formdef_remap_statuses(formdef, mapping): |
|
2881 |
conn, cur = get_connection_and_cursor() |
|
2882 |
table_name = get_formdef_table_name(formdef) |
|
2883 |
evolutions_table_name = table_name + '_evolutions' |
|
2884 |
old_workflow_id = formdef.workflow_id or '_default' |
|
2885 |
args = [] |
|
2886 |
case_expression = '(CASE ' |
|
2887 |
case_expression += 'WHEN status IS NULL THEN NULL ' |
|
2888 |
for old_id, new_id in mapping.items(): |
|
2889 |
case_expression += "WHEN status = %s THEN %s " |
|
2890 |
args.extend([old_id, new_id]) |
|
2891 |
case_expression += " WHEN status LIKE '%%-invalid-%%' THEN status " |
|
2892 |
case_expression += " ELSE (status || '-invalid-' || %s) END)" |
|
2893 |
args.append(old_workflow_id) |
|
2894 | ||
2895 |
cur.execute('BEGIN') |
|
2896 |
cur.execute('UPDATE %s SET status = %s WHERE status <> \'draft\'' % (table_name, case_expression), args) |
|
2897 |
cur.execute('UPDATE %s SET status = %s' % (evolutions_table_name, case_expression), args) |
|
2898 |
cur.execute('COMMIT') |
|
2877 |
- |