cards: extend "update cards" checkbox to CSV imports (#88294)
gitea/wcs/pipeline/head Build queued...
Details
gitea/wcs/pipeline/head Build queued...
Details
This commit is contained in:
parent
69249df789
commit
520e52d1a7
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue