0001-workflows-report-labels-of-deleted-fields-in-create-.patch
tests/admin_pages/test_workflow.py | ||
---|---|---|
2508 | 2508 |
assert "syntax error: Could not parse the remainder: '{{' from '{{'" in resp |
2509 | 2509 | |
2510 | 2510 | |
2511 |
def test_workflows_create_formdata_deleted_field(pub): |
|
2512 |
create_superuser(pub) |
|
2513 | ||
2514 |
FormDef.wipe() |
|
2515 |
target_formdef = FormDef() |
|
2516 |
target_formdef.name = 'target form' |
|
2517 |
target_formdef.enable_tracking_codes = True |
|
2518 |
target_formdef.fields = [ |
|
2519 |
fields.StringField(id='0', label='string1', varname='foo'), |
|
2520 |
fields.StringField(id='1', label='string2', varname='bar'), |
|
2521 |
] |
|
2522 |
target_formdef.store() |
|
2523 | ||
2524 |
Workflow.wipe() |
|
2525 |
wf = Workflow(name='create-formdata') |
|
2526 | ||
2527 |
st2 = wf.add_status('Resubmit') |
|
2528 | ||
2529 |
create_formdata = CreateFormdataWorkflowStatusItem() |
|
2530 |
create_formdata.id = '_create_formdata' |
|
2531 |
create_formdata.formdef_slug = target_formdef.url_name |
|
2532 |
create_formdata.mappings = [ |
|
2533 |
Mapping(field_id='0', expression='{{ "a" }}'), |
|
2534 |
Mapping(field_id='1', expression='{{ "b" }}'), |
|
2535 |
] |
|
2536 |
create_formdata.parent = st2 |
|
2537 |
st2.items.append(create_formdata) |
|
2538 | ||
2539 |
wf.store() |
|
2540 | ||
2541 |
app = login(get_app(pub)) |
|
2542 |
# edit/submit to get field labels into cache |
|
2543 |
resp = app.get('/backoffice/workflows/%s/status/%s/items/_create_formdata/' % (wf.id, st2.id)) |
|
2544 |
resp = resp.form.submit(name='submit') |
|
2545 | ||
2546 |
# remove field |
|
2547 |
target_formdef.fields = [ |
|
2548 |
fields.StringField(id='1', label='string2', varname='bar'), |
|
2549 |
] |
|
2550 |
target_formdef.store() |
|
2551 | ||
2552 |
resp = app.get('/backoffice/workflows/%s/status/%s/items/_create_formdata/' % (wf.id, st2.id)) |
|
2553 |
assert resp.form['mappings$element1$field_id'].options == [ |
|
2554 |
('', False, '---'), |
|
2555 |
('1', False, 'string2'), |
|
2556 |
('0', True, '❗ string1 (deleted field)'), |
|
2557 |
] |
|
2558 | ||
2559 | ||
2511 | 2560 |
def test_workflows_create_carddata_action_config(pub): |
2512 | 2561 |
create_superuser(pub) |
2513 | 2562 |
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 |
) |
... | ... | |
107 | 111 |
element_kwargs={ |
108 | 112 |
'to_formdef': to_formdef, |
109 | 113 |
'accept_empty_value': accept_empty_value, |
114 |
'cached_field_labels': kwargs.pop('cached_field_labels', None), |
|
110 | 115 |
}, |
111 | 116 |
**kwargs, |
112 | 117 |
) |
... | ... | |
304 | 309 |
varname = None |
305 | 310 |
map_fields_by_varname = False |
306 | 311 |
attach_to_history = False |
312 |
cached_field_labels = None |
|
307 | 313 | |
308 | 314 |
def migrate(self): |
309 | 315 |
changed = super().migrate() |
... | ... | |
402 | 408 |
accept_empty_value=self.accept_empty_value, |
403 | 409 |
to_formdef=formdef, |
404 | 410 |
value=self.mappings, |
411 |
cached_field_labels=self.cached_field_labels, |
|
405 | 412 |
) |
406 | 413 |
if form.is_submitted() and get_request().form.get('map_fields_by_varname') != 'yes': |
407 | 414 |
# do not validate form if formdef is changed and there is no mappings |
... | ... | |
452 | 459 |
else: |
453 | 460 |
form.ERROR_NOTICE = Form.ERROR_NOTICE |
454 | 461 | |
462 |
def submit_admin_form(self, form): |
|
463 |
super().submit_admin_form(form) |
|
464 |
# keep a cache of field labels, to be used in case of errors if fields are removed |
|
465 |
mapped_field_ids = [x.field_id for x in self.mappings or []] |
|
466 |
if self.formdef: |
|
467 |
self.cached_field_labels = { |
|
468 |
x.id: x.label for x in self.formdef.get_widget_fields() if x.id in mapped_field_ids |
|
469 |
} |
|
470 | ||
455 | 471 |
def get_mappings_parameter_view_value(self): |
456 | 472 |
to_id_fields = {str(field.id): field for field in self.formdef.get_widget_fields()} |
457 | 473 |
result = [] |
... | ... | |
654 | 670 |
) |
655 | 671 | |
656 | 672 |
if missing_fields: |
657 |
summary = _('Missing field %r') % missing_fields |
|
673 |
labels = [(self.cached_field_labels or {}).get(x, 'unknown (%s)' % x) for x in missing_fields] |
|
674 |
summary = '%s %s' % ( |
|
675 |
ngettext('Missing field:', 'Missing fields:', len(labels)), |
|
676 |
', '.join(sorted(labels)), |
|
677 |
) |
|
658 | 678 |
get_publisher().record_error(summary, formdata=src, status_item=self) |
659 | 679 | |
660 | 680 |
def _set_value(self, formdata, field, value): |
661 |
- |