0001-misc-remap-statuses-in-a-transaction-38579.patch
tests/admin_pages/test_form.py | ||
---|---|---|
566 | 566 |
formdata2.status = 'draft' |
567 | 567 |
formdata2.store() |
568 | 568 | |
569 |
formdata3 = data_class() |
|
570 |
formdata3.status = 'wf-1' |
|
571 |
formdata3.store() |
|
572 | ||
569 | 573 |
Workflow.wipe() |
570 | 574 |
workflow = Workflow(name='Workflow One') |
571 | 575 |
workflow.store() |
... | ... | |
587 | 591 |
assert len(resp.forms[0]['mapping-%s' % status.id].options) == 1 |
588 | 592 |
assert data_class.get(formdata1.id).status == 'wf-new' |
589 | 593 |
assert data_class.get(formdata2.id).status == 'draft' |
594 |
assert data_class.get(formdata3.id).status == 'wf-1' |
|
590 | 595 |
resp = resp.forms[0].submit() |
591 | 596 |
assert data_class.get(formdata1.id).status == 'wf-finished' |
592 | 597 |
assert data_class.get(formdata2.id).status == 'draft' |
598 |
assert data_class.get(formdata3.id).status == 'wf-1-invalid-_default' |
|
593 | 599 | |
594 | 600 |
# change to another workflow, with no mapping change |
595 | 601 |
workflow2 = workflow |
... | ... | |
610 | 616 |
resp = resp.forms[0].submit() |
611 | 617 |
assert data_class.get(formdata1.id).status == 'wf-finished' |
612 | 618 |
assert data_class.get(formdata2.id).status == 'draft' |
619 |
assert data_class.get(formdata3.id).status == 'wf-1-invalid-_default' |
|
613 | 620 | |
614 | 621 | |
615 | 622 |
def test_form_submitter_roles(pub): |
wcs/admin/forms.py | ||
---|---|---|
1099 | 1099 |
if workflow_id is None: |
1100 | 1100 |
workflow_id = self.formdef_default_workflow |
1101 | 1101 |
return redirect('workflow-status-remapping?new=%s' % workflow_id) |
1102 |
self.formdef.workflow_id = workflow_id |
|
1103 |
self.formdef.store(comment=_('Workflow change')) |
|
1102 |
self.formdef.change_workflow(workflow_id) |
|
1104 | 1103 |
return redirect('.') |
1105 | 1104 | |
1106 | 1105 |
def workflow_status_remapping(self): |
... | ... | |
1139 | 1138 |
r += form.render() |
1140 | 1139 |
return r.getvalue() |
1141 | 1140 |
else: |
1142 |
get_logger().info( |
|
1143 |
'admin - form "%s", workflow is now "%s" (was "%s")' |
|
1144 |
% (self.formdef.name, new_workflow.name, self.formdef.workflow.name) |
|
1145 |
) |
|
1146 |
self.workflow_status_remapping_submit(form) |
|
1147 |
if new_workflow.id == self.formdef_default_workflow: |
|
1148 |
self.formdef.workflow_id = None |
|
1149 |
else: |
|
1150 |
self.formdef.workflow_id = new_workflow.id |
|
1151 |
self.formdef.store(comment=_('Workflow change')) |
|
1152 |
# instruct formdef to update its security rules |
|
1153 |
self.formdef.data_class().rebuild_security() |
|
1154 |
return redirect('.') |
|
1141 |
return self.workflow_status_remapping_submit(form, new_workflow) |
|
1142 | ||
1143 |
def workflow_status_remapping_submit(self, form, new_workflow): |
|
1144 |
get_logger().info( |
|
1145 |
'admin - form "%s", workflow is now "%s" (was "%s")' |
|
1146 |
% (self.formdef.name, new_workflow.name, self.formdef.workflow.name) |
|
1147 |
) |
|
1155 | 1148 | |
1156 |
def workflow_status_remapping_submit(self, form): |
|
1157 | 1149 |
status_mapping = {} |
1158 | 1150 |
for status in self.formdef.workflow.possible_status: |
1159 |
status_mapping['wf-%s' % status.id] = 'wf-%s' % form.get_widget('mapping-%s' % status.id).parse() |
|
1160 |
if any(x[0] != x[1] for x in status_mapping.items()): |
|
1161 |
# if there are status changes, update all formdatas (except drafts) |
|
1162 |
status_mapping.update({'draft': 'draft'}) |
|
1163 |
for item in self.formdef.data_class().select([NotEqual('status', 'draft')]): |
|
1164 |
item.status = status_mapping.get(item.status) |
|
1165 |
if item.evolution: |
|
1166 |
for evo in item.evolution: |
|
1167 |
evo.status = status_mapping.get(evo.status) |
|
1168 |
item.store() |
|
1151 |
status_mapping[status.id] = form.get_widget('mapping-%s' % status.id).parse() |
|
1152 | ||
1153 |
if new_workflow.id == self.formdef_default_workflow: |
|
1154 |
new_workflow_id = None |
|
1155 |
else: |
|
1156 |
new_workflow_id = new_workflow.id |
|
1157 |
self.formdef.change_workflow(new_workflow_id, status_mapping) |
|
1158 |
return redirect('.') |
|
1169 | 1159 | |
1170 | 1160 |
def get_preview(self): |
1171 | 1161 |
form = Form(action='#', use_tokens=False) |
wcs/formdef.py | ||
---|---|---|
41 | 41 |
from .qommon.form import Form, HtmlWidget, UploadedFile |
42 | 42 |
from .qommon.misc import JSONEncoder, get_as_datetime, simplify, xml_node_text |
43 | 43 |
from .qommon.publisher import get_publisher_class |
44 |
from .qommon.storage import Equal, StorableObject, fix_key |
|
44 |
from .qommon.storage import Equal, NotEqual, StorableObject, fix_key
|
|
45 | 45 |
from .qommon.substitution import Substitutions |
46 | 46 |
from .qommon.template import Template |
47 | 47 |
from .roles import logged_users_role |
... | ... | |
1664 | 1664 |
# chunk contains the fields. |
1665 | 1665 |
return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2) |
1666 | 1666 | |
1667 |
def change_workflow(self, new_workflow_id, status_mapping=None): |
|
1668 |
old_workflow = self.get_workflow() |
|
1669 | ||
1670 |
formdata_count = self.data_class().count() |
|
1671 |
if formdata_count: |
|
1672 |
assert status_mapping, 'status mapping is required if there are formdatas' |
|
1673 |
assert all( |
|
1674 |
status.id in status_mapping for status in old_workflow.possible_status |
|
1675 |
), 'a status was not mapped' |
|
1676 | ||
1677 |
mapping = {} |
|
1678 |
for old_status, new_status in status_mapping.items(): |
|
1679 |
mapping['wf-%s' % old_status] = 'wf-%s' % new_status |
|
1680 |
mapping['draft'] = 'draft' |
|
1681 | ||
1682 |
if any([x[0] != x[1] for x in mapping.items()]): |
|
1683 |
# if there are status changes, update all formdatas (except drafts) |
|
1684 |
if get_publisher().is_using_postgresql(): |
|
1685 |
from . import sql |
|
1686 | ||
1687 |
sql.formdef_remap_statuses(self, mapping) |
|
1688 |
else: |
|
1689 | ||
1690 |
def map_status(status): |
|
1691 |
if status is None: |
|
1692 |
return None |
|
1693 |
elif status in mapping: |
|
1694 |
return mapping[status] |
|
1695 |
elif '-invalid-' in status: |
|
1696 |
return status |
|
1697 |
else: |
|
1698 |
return '%s-invalid-%s' % (status, old_workflow.id) |
|
1699 | ||
1700 |
for formdata in self.data_class().select([NotEqual('status', 'draft')]): |
|
1701 |
formdata.status = map_status(formdata.status) |
|
1702 |
if formdata.evolution: |
|
1703 |
for evo in formdata.evolution: |
|
1704 |
evo.status = map_status(evo.status) |
|
1705 |
formdata.store() |
|
1706 | ||
1707 |
self.workflow_id = new_workflow_id |
|
1708 |
self.store(comment=_('Workflow change')) |
|
1709 |
if formdata_count: |
|
1710 |
# instruct formdef to update its security rules |
|
1711 |
self.data_class().rebuild_security() |
|
1712 | ||
1667 | 1713 | |
1668 | 1714 |
EmailsDirectory.register( |
1669 | 1715 |
'new_user', |
wcs/sql.py | ||
---|---|---|
3651 | 3651 | |
3652 | 3652 |
conn.commit() |
3653 | 3653 |
cur.close() |
3654 | ||
3655 | ||
3656 |
@guard_postgres |
|
3657 |
def formdef_remap_statuses(formdef, mapping): |
|
3658 |
conn, cur = get_connection_and_cursor() |
|
3659 |
table_name = get_formdef_table_name(formdef) |
|
3660 |
evolutions_table_name = table_name + '_evolutions' |
|
3661 |
old_workflow_id = formdef.workflow_id or '_default' |
|
3662 |
args = [] |
|
3663 |
case_expression = '(CASE ' |
|
3664 |
case_expression += 'WHEN status IS NULL THEN NULL ' |
|
3665 |
for old_id, new_id in mapping.items(): |
|
3666 |
case_expression += "WHEN status = %s THEN %s " |
|
3667 |
args.extend([old_id, new_id]) |
|
3668 |
case_expression += " WHEN status LIKE '%%-invalid-%%' THEN status " |
|
3669 |
case_expression += " ELSE (status || '-invalid-' || %s) END)" |
|
3670 |
args.append(old_workflow_id) |
|
3671 | ||
3672 |
cur.execute('BEGIN') |
|
3673 |
cur.execute('UPDATE %s SET status = %s WHERE status <> \'draft\'' % (table_name, case_expression), args) |
|
3674 |
cur.execute('UPDATE %s SET status = %s' % (evolutions_table_name, case_expression), args) |
|
3675 |
cur.execute('COMMIT') |
|
3654 |
- |