0001-workflows-report-labels-of-deleted-fields-in-create-.patch
tests/admin_pages/test_workflow.py | ||
---|---|---|
2731 | 2731 |
assert "syntax error: Could not parse the remainder: '{{' from '{{'" in resp |
2732 | 2732 | |
2733 | 2733 | |
2734 |
def test_workflows_create_formdata_deleted_field(pub): |
|
2735 |
create_superuser(pub) |
|
2736 | ||
2737 |
FormDef.wipe() |
|
2738 |
target_formdef = FormDef() |
|
2739 |
target_formdef.name = 'target form' |
|
2740 |
target_formdef.enable_tracking_codes = True |
|
2741 |
target_formdef.fields = [ |
|
2742 |
fields.StringField(id='0', label='string1', varname='foo'), |
|
2743 |
fields.StringField(id='1', label='string2', varname='bar'), |
|
2744 |
] |
|
2745 |
target_formdef.store() |
|
2746 | ||
2747 |
Workflow.wipe() |
|
2748 |
wf = Workflow(name='create-formdata') |
|
2749 | ||
2750 |
st2 = wf.add_status('Resubmit') |
|
2751 | ||
2752 |
create_formdata = CreateFormdataWorkflowStatusItem() |
|
2753 |
create_formdata.id = '_create_formdata' |
|
2754 |
create_formdata.formdef_slug = target_formdef.url_name |
|
2755 |
create_formdata.mappings = [ |
|
2756 |
Mapping(field_id='0', expression='{{ "a" }}'), |
|
2757 |
Mapping(field_id='1', expression='{{ "b" }}'), |
|
2758 |
] |
|
2759 |
create_formdata.parent = st2 |
|
2760 |
st2.items.append(create_formdata) |
|
2761 | ||
2762 |
wf.store() |
|
2763 | ||
2764 |
app = login(get_app(pub)) |
|
2765 |
# edit/submit to get field labels into cache |
|
2766 |
resp = app.get('/backoffice/workflows/%s/status/%s/items/_create_formdata/' % (wf.id, st2.id)) |
|
2767 |
resp = resp.form.submit(name='submit') |
|
2768 | ||
2769 |
# remove field |
|
2770 |
target_formdef.fields = [ |
|
2771 |
fields.StringField(id='1', label='string2', varname='bar'), |
|
2772 |
] |
|
2773 |
target_formdef.store() |
|
2774 | ||
2775 |
resp = app.get('/backoffice/workflows/%s/status/%s/items/_create_formdata/' % (wf.id, st2.id)) |
|
2776 |
assert resp.form['mappings$element1$field_id'].options == [ |
|
2777 |
('', False, '---'), |
|
2778 |
('1', False, 'string2'), |
|
2779 |
('0', True, '❗ string1 (deleted field)'), |
|
2780 |
] |
|
2781 | ||
2782 | ||
2734 | 2783 |
def test_workflows_create_carddata_action_config(pub): |
2735 | 2784 |
create_superuser(pub) |
2736 | 2785 |
tests/workflow/test_formdata.py | ||
---|---|---|
106 | 106 |
errors = two_pubs.loggederror_class.select() |
107 | 107 |
assert len(errors) == 2 |
108 | 108 |
assert 'form_var_toto_string' in errors[0].exception_message |
109 |
assert 'Missing field' in errors[1].summary
|
|
109 |
assert errors[1].summary == 'Missing field: unknown (1), unknown (2)'
|
|
110 | 110 |
assert errors[0].formdata_id == str(target_formdef.data_class().select()[0].id) |
111 | 111 |
assert errors[1].formdata_id == str(target_formdef.data_class().select()[0].id) |
112 | 112 | |
113 |
if two_pubs.is_using_postgresql(): |
|
114 |
# add field labels cache |
|
115 |
two_pubs.loggederror_class.wipe() |
|
116 |
target_formdef.data_class().wipe() |
|
117 |
create.formdef_slug = target_formdef.url_name |
|
118 |
create.cached_field_labels = {'0': 'field0', '1': 'field1', '2': 'field2'} |
|
119 |
wf.store() |
|
120 |
del source_formdef._workflow |
|
121 |
formdata.perform_workflow() |
|
122 |
assert target_formdef.data_class().count() == 1 |
|
123 | ||
124 |
errors = two_pubs.loggederror_class.select() |
|
125 |
assert len(errors) == 2 |
|
126 |
assert errors[1].summary == 'Missing field: field1, field2' |
|
127 | ||
113 | 128 |
# no tracking code has been created |
114 | 129 |
created_formdata = target_formdef.data_class().select()[0] |
115 | 130 |
assert created_formdata.tracking_code is None |
wcs/wf/create_formdata.py | ||
---|---|---|
22 | 22 |
from quixote.html import htmltext |
23 | 23 | |
24 | 24 |
from wcs.formdef import FormDef |
25 |
from wcs.qommon import _ |
|
25 |
from wcs.qommon import _, ngettext
|
|
26 | 26 |
from wcs.qommon.form import ( |
27 | 27 |
CheckboxWidget, |
28 | 28 |
CompositeWidget, |
... | ... | |
48 | 48 | |
49 | 49 | |
50 | 50 |
class MappingWidget(CompositeWidget): |
51 |
def __init__(self, name, value=None, to_formdef=None, **kwargs): |
|
51 |
def __init__(self, name, value=None, to_formdef=None, cached_field_labels=None, **kwargs):
|
|
52 | 52 |
value = value or Mapping(None, '') |
53 | 53 |
self.accept_empty_value = kwargs.pop('accept_empty_value', False) |
54 | 54 |
super().__init__(name, value, **kwargs) |
55 | 55 | |
56 | 56 |
to_fields = self._fields_to_options(to_formdef) |
57 | 57 | |
58 |
if value and value.field_id not in [x[0] for x in to_fields]: |
|
59 |
old_label = (cached_field_labels or {}).get(value.field_id) or _('Unknown') |
|
60 |
error_option = '❗ %s (%s)' % (old_label, _('deleted field')) |
|
61 |
to_fields.append((value.field_id, error_option, value.field_id)) |
|
58 | 62 |
self.add( |
59 | 63 |
SingleSelectWidget, name='field_id', title=_('Field'), value=value.field_id, options=to_fields |
60 | 64 |
) |
... | ... | |
101 | 105 |
value.sort(key=lambda mapping: self.ranks.get(str(mapping.field_id), 9999)) |
102 | 106 | |
103 | 107 |
accept_empty_value = kwargs.pop('accept_empty_value', False) |
108 |
cached_field_labels = kwargs.pop('cached_field_labels', None) |
|
104 | 109 |
super().__init__( |
105 | 110 |
name, |
106 | 111 |
element_type=MappingWidget, |
107 | 112 |
element_kwargs={ |
108 | 113 |
'to_formdef': to_formdef, |
109 | 114 |
'accept_empty_value': accept_empty_value, |
115 |
'cached_field_labels': cached_field_labels, |
|
110 | 116 |
}, |
111 | 117 |
**kwargs, |
112 | 118 |
) |
... | ... | |
312 | 318 |
varname = None |
313 | 319 |
map_fields_by_varname = False |
314 | 320 |
attach_to_history = False |
321 |
cached_field_labels = None |
|
315 | 322 | |
316 | 323 |
def migrate(self): |
317 | 324 |
changed = super().migrate() |
... | ... | |
404 | 411 |
accept_empty_value=self.accept_empty_value, |
405 | 412 |
to_formdef=formdef, |
406 | 413 |
value=self.mappings, |
414 |
cached_field_labels=self.cached_field_labels, |
|
407 | 415 |
) |
408 | 416 |
if form.is_submitted() and get_request().form.get('map_fields_by_varname') != 'yes': |
409 | 417 |
# do not validate form if formdef is changed and there is no mappings |
... | ... | |
453 | 461 |
else: |
454 | 462 |
form.ERROR_NOTICE = Form.ERROR_NOTICE |
455 | 463 | |
464 |
def submit_admin_form(self, form): |
|
465 |
super().submit_admin_form(form) |
|
466 |
# keep a cache of field labels, to be used in case of errors if fields are removed |
|
467 |
mapped_field_ids = [x.field_id for x in self.mappings or []] |
|
468 |
if self.formdef: |
|
469 |
self.cached_field_labels = { |
|
470 |
x.id: x.label for x in self.formdef.get_widget_fields() if x.id in mapped_field_ids |
|
471 |
} |
|
472 | ||
456 | 473 |
def get_mappings_parameter_view_value(self): |
457 | 474 |
to_id_fields = {str(field.id): field for field in self.formdef.get_widget_fields()} |
458 | 475 |
result = [] |
... | ... | |
661 | 678 |
) |
662 | 679 | |
663 | 680 |
if missing_fields: |
664 |
summary = _('Missing field %r') % missing_fields |
|
681 |
labels = [(self.cached_field_labels or {}).get(x, 'unknown (%s)' % x) for x in missing_fields] |
|
682 |
summary = '%s %s' % ( |
|
683 |
ngettext('Missing field:', 'Missing fields:', len(labels)), |
|
684 |
', '.join(sorted(labels)), |
|
685 |
) |
|
665 | 686 |
get_publisher().record_error(summary, formdata=src, status_item=self) |
666 | 687 | |
667 | 688 |
def _set_value(self, formdata, field, value): |
668 |
- |