Projet

Général

Profil

0001-workflows-report-labels-of-deleted-fields-in-create-.patch

Frédéric Péters, 16 janvier 2022 11:55

Télécharger (7,69 ko)

Voir les différences:

Subject: [PATCH] workflows: report labels of deleted fields in create
 form/card action (#60696)

 tests/admin_pages/test_workflow.py | 49 ++++++++++++++++++++++++++++++
 tests/workflow/test_formdata.py    | 17 ++++++++++-
 wcs/wf/create_formdata.py          | 26 ++++++++++++++--
 3 files changed, 88 insertions(+), 4 deletions(-)
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
-