diff --git a/tests/backoffice_pages/test_carddata.py b/tests/backoffice_pages/test_carddata.py index e46b50b47..5a5a9940e 100644 --- a/tests/backoffice_pages/test_carddata.py +++ b/tests/backoffice_pages/test_carddata.py @@ -681,6 +681,58 @@ def test_backoffice_cards_import_data_csv_no_backoffice_fields(pub): assert carddef.data_class().count() == 2 +def test_backoffice_cards_import_data_csv_custom_id_no_update(pub): + user = create_user(pub) + user.name_identifiers = [str(uuid.uuid4())] + user.store() + + Workflow.wipe() + workflow = Workflow(name='form-title') + workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow) + workflow.backoffice_fields_formdef.fields = [ + fields.StringField(id='bo0', varname='foo_bovar', label='bo variable'), + ] + workflow.add_status('st0') + workflow.store() + + CardDef.wipe() + carddef = CardDef() + carddef.name = 'test' + carddef.fields = [ + fields.StringField(id='1', label='String', varname='custom_id'), + fields.ItemField(id='2', label='List', items=['item1', 'item2']), + ] + carddef.backoffice_submission_roles = user.roles + carddef.id_template = '{{form_var_custom_id}}' + carddef.workflow = workflow + carddef.store() + carddef.data_class().wipe() + + card = carddef.data_class()() + card.data = {'1': 'plop', '2': 'test', '2_display': 'test', 'bo0': 'xxx'} + card.just_created() + card.store() + + app = login(get_app(pub)) + data = b'''\ +"String","List" +"plop","item1" +"test","item2" +''' + resp = app.get('/backoffice/data/test/import-file') + resp.forms[0]['file'] = Upload('test.csv', data, 'text/csv') + resp.form['update_existing_cards'].checked = False + resp = resp.forms[0].submit().follow() + assert carddef.data_class().count() == 2 + + card.refresh_from_storage() + assert card.data == {'1': 'plop', '2': 'test', '2_display': 'test', 'bo0': 'xxx'} # no change + + other_card = carddef.data_class().select(order_by='-receipt_time')[0] + assert other_card.data == {'1': 'test', '2': 'item2', '2_display': 'item2', 'bo0': None} + assert other_card.id_display == 'test' + + def test_backoffice_cards_import_data_csv_custom_id_update(pub): user = create_user(pub) user.name_identifiers = [str(uuid.uuid4())] @@ -721,6 +773,7 @@ def test_backoffice_cards_import_data_csv_custom_id_update(pub): ''' resp = app.get('/backoffice/data/test/import-file') resp.forms[0]['file'] = Upload('test.csv', data, 'text/csv') + resp.form['update_existing_cards'].checked = True resp = resp.forms[0].submit().follow() assert carddef.data_class().count() == 2 diff --git a/wcs/backoffice/data_management.py b/wcs/backoffice/data_management.py index cf1dd439e..013ff0428 100644 --- a/wcs/backoffice/data_management.py +++ b/wcs/backoffice/data_management.py @@ -228,10 +228,16 @@ class CardPage(FormPage): form.add( CheckboxWidget, 'update_existing_cards', - title=_('Update existing cards (only for JSON imports)'), + title=_('Update existing cards (only for JSON imports)') + if not self.formdef.id_template + else _('Update existing cards'), hint=_('Cards will be matched using their unique identifier ("uuid" property).') if not self.formdef.id_template - else _('Cards will be matched using their custom identifier ("id" property).'), + else _( + 'Cards will be matched using their custom identifier ("id" property). ' + 'If this option is enabled cards with the same identifiers will be updated, ' + 'otherwise they will be skipped.' + ), value=False, ) form.add_submit('submit', _('Submit')) @@ -241,19 +247,22 @@ class CardPage(FormPage): if form.is_submitted() and not form.has_errors(): file_content = form.get_widget('file').parse().fp.read() + update_existing_cards = form.get_widget('update_existing_cards').parse() try: json_content = json.loads(file_content) except ValueError: # not json -> CSV try: - return self.import_csv_submit(file_content, submission_agent_id=get_request().user.id) + return self.import_csv_submit( + file_content, + update_existing_cards=update_existing_cards, + submission_agent_id=get_request().user.id, + ) except ValueError as e: form.set_error('file', e) else: try: - return self.import_json_submit( - json_content, update_existing_cards=form.get_widget('update_existing_cards').parse() - ) + return self.import_json_submit(json_content, update_existing_cards=update_existing_cards) except ValueError as e: form.set_error('file', e) @@ -275,7 +284,9 @@ class CardPage(FormPage): impossible_fields.append(field.label) return impossible_fields - def import_csv_submit(self, content, afterjob=True, api=False, submission_agent_id=None): + def import_csv_submit( + self, content, afterjob=True, api=False, update_existing_cards=False, submission_agent_id=None + ): if b'\0' in content: raise ValueError(_('Invalid file format.')) @@ -328,7 +339,10 @@ class CardPage(FormPage): raise ValueError(error_message) job = ImportFromCsvAfterJob( - carddef=self.formdef, data_lines=data_lines, submission_agent_id=submission_agent_id + carddef=self.formdef, + data_lines=data_lines, + update_existing_cards=update_existing_cards, + submission_agent_id=submission_agent_id, ) if afterjob: get_response().add_after_job(job) @@ -432,12 +446,13 @@ class CardBackOfficeStatusPage(FormBackOfficeStatusPage): class ImportFromCsvAfterJob(AfterJob): - def __init__(self, carddef, data_lines, submission_agent_id): + def __init__(self, carddef, data_lines, update_existing_cards, submission_agent_id): super().__init__( label=_('Importing data into cards'), carddef_class=carddef.__class__, carddef_id=carddef.id, data_lines=data_lines, + update_existing_cards=update_existing_cards, submission_agent_id=submission_agent_id, ) @@ -448,6 +463,7 @@ class ImportFromCsvAfterJob(AfterJob): def execute(self): self.carddef = self.kwargs['carddef_class'].get(self.kwargs['carddef_id']) + update_existing_cards = self.kwargs['update_existing_cards'] carddata_class = self.carddef.data_class() self.submission_agent_id = self.kwargs['submission_agent_id'] self.total_count = len(self.kwargs['data_lines']) @@ -507,6 +523,9 @@ class ImportFromCsvAfterJob(AfterJob): except KeyError: pass # unique id, fine else: + if not update_existing_cards: + self.increment_count() + continue # overwrite (only fields from CSV columns, not unsupported or backoffice fields) new_card = False orig_data = copy.copy(carddata_with_same_id.data)