0002-create_formdata-add-automatic-mapping-by-varnames-39.patch
tests/test_backoffice_pages.py | ||
---|---|---|
5737 | 5737 |
wf.store() |
5738 | 5738 |
source_formdef.workflow_id = wf.id |
5739 | 5739 |
source_formdef.store() |
5740 |
source_formdef.data_class().wipe() |
|
5741 |
target_formdef.data_class().wipe() |
|
5742 |
LoggedError.wipe() |
|
5740 | 5743 |
return locals() |
5741 | 5744 | |
5742 | 5745 | |
5743 | 5746 |
def test_backoffice_create_formdata_backoffice_submission(create_formdata): |
5744 |
create_formdata['source_formdef'].data_class().wipe() |
|
5745 |
create_formdata['target_formdef'].data_class().wipe() |
|
5747 |
# create submitting user |
|
5748 |
user = create_formdata['pub'].user_class() |
|
5749 |
user.name = 'Jean Darmette' |
|
5750 |
user.email = 'jean.darmette@triffouilis.fr' |
|
5751 |
user.store() |
|
5752 | ||
5753 |
# create source formdata |
|
5754 |
formdata = create_formdata['source_formdef'].data_class()() |
|
5755 |
upload = PicklableUpload('/foo/bar', content_type='text/plain') |
|
5756 |
upload.receive([b'hello world']) |
|
5757 |
formdata.data = { |
|
5758 |
'0': 'coucou', |
|
5759 |
'1': upload, |
|
5760 |
} |
|
5761 |
formdata.user = user |
|
5762 |
formdata.just_created() |
|
5763 |
formdata.store() |
|
5764 |
formdata.perform_workflow() |
|
5765 | ||
5766 |
# agent login and go to backoffice management pages |
|
5767 |
app = get_app(create_formdata['pub']) |
|
5768 |
app = login(app) |
|
5769 |
resp = app.get(create_formdata['source_formdef'].get_url(backoffice=True)) |
|
5770 | ||
5771 |
# click on first available formdata |
|
5772 |
resp = resp.click(href='%s/' % formdata.id) |
|
5773 |
target_data_class = create_formdata['target_formdef'].data_class() |
|
5774 |
assert target_data_class.count() == 0 |
|
5775 |
# resubmit it through backoffice submission |
|
5776 |
resp = resp.form.submit(name='button_resubmit') |
|
5777 |
assert LoggedError.count() == 0 |
|
5778 |
assert target_data_class.count() == 1 |
|
5779 |
target_formdata = target_data_class.select()[0] |
|
5780 | ||
5781 |
assert target_formdata.submission_context == { |
|
5782 |
'agent_id': str(create_formdata['admin'].id), |
|
5783 |
'orig_formdata_id': '1', |
|
5784 |
'orig_formdef_id': '1' |
|
5785 |
} |
|
5786 |
assert target_formdata.user.id == user.id |
|
5787 |
assert target_formdata.status == 'draft' |
|
5788 |
assert resp.location == 'http://example.net/backoffice/management/target-form/%s/' % target_formdata.id |
|
5789 |
resp = resp.follow() |
|
5790 |
assert resp.location == 'http://example.net/backoffice/submission/target-form/%s/' % target_formdata.id |
|
5791 |
resp = resp.follow() |
|
5792 |
# second redirect with magic-token |
|
5793 |
resp = resp.follow() |
|
5794 |
resp = resp.form.submit(name='submit') # -> validation |
|
5795 |
resp = resp.form.submit(name='submit') # -> submission |
|
5796 |
target_formdata = target_data_class.get(id=target_formdata.id) |
|
5797 |
assert target_formdata.user.id == user.id |
|
5798 |
assert target_formdata.status == 'wf-new' |
|
5799 |
resp = resp.follow() |
|
5800 |
pq = resp.pyquery.remove_namespaces() |
|
5801 |
assert pq('.field-type-string .value').text() == 'coucou' |
|
5802 |
assert pq('.field-type-file .value').text() == 'bar' |
|
5803 | ||
5804 | ||
5805 |
def test_backoffice_create_formdata_map_fields_by_varname(create_formdata): |
|
5806 |
create_formdata['create_formdata'].map_fields_by_varname = True |
|
5807 |
create_formdata['create_formdata'].mappings = [] |
|
5808 |
create_formdata['wf'].store() |
|
5809 |
create_formdata['source_formdef'].fields = [ |
|
5810 |
fields.StringField(id='0', label='string', varname='string0'), |
|
5811 |
fields.FileField(id='1', label='file', type='file', varname='file1'), |
|
5812 |
fields.StringField(id='2', label='string', varname='string2', required=False), |
|
5813 |
fields.FileField(id='3', label='file', type='file', varname='file3', required=False), |
|
5814 |
] |
|
5815 |
create_formdata['source_formdef'].store() |
|
5816 |
create_formdata['target_formdef'].fields = [ |
|
5817 |
fields.StringField(id='0', label='string', varname='string0'), |
|
5818 |
fields.FileField(id='1', label='file', type='file', varname='file1'), |
|
5819 |
fields.StringField(id='2', label='string', varname='string2', required=False), |
|
5820 |
fields.FileField(id='3', label='file', type='file', varname='file3', required=False), |
|
5821 |
] |
|
5822 |
create_formdata['target_formdef'].store() |
|
5746 | 5823 | |
5747 | 5824 |
# create submitting user |
5748 | 5825 |
user = create_formdata['pub'].user_class() |
... | ... | |
5774 | 5851 |
assert target_data_class.count() == 0 |
5775 | 5852 |
# resubmit it through backoffice submission |
5776 | 5853 |
resp = resp.form.submit(name='button_resubmit') |
5854 |
assert LoggedError.count() == 0 |
|
5777 | 5855 |
assert target_data_class.count() == 1 |
5778 | 5856 |
target_formdata = target_data_class.select()[0] |
5779 | 5857 |
wcs/wf/create_formdata.py | ||
---|---|---|
18 | 18 |
import xml.etree.ElementTree as ET |
19 | 19 | |
20 | 20 |
from quixote import get_request, get_session, get_publisher |
21 |
from quixote.html import htmltext |
|
21 | 22 | |
22 | 23 |
from django.utils.functional import cached_property |
23 | 24 | |
24 | 25 |
from wcs.qommon import _ |
25 | 26 |
from wcs.qommon.form import (WidgetListAsTable, CompositeWidget, |
26 | 27 |
SingleSelectWidget, ComputedExpressionWidget, |
27 |
CheckboxWidget, StringWidget, VarnameWidget)
|
|
28 |
CheckboxWidget, VarnameWidget, HtmlWidget)
|
|
28 | 29 | |
29 | 30 |
from wcs.logged_errors import LoggedError |
30 | 31 |
from wcs.workflows import WorkflowStatusItem, register_item_class |
... | ... | |
32 | 33 | |
33 | 34 | |
34 | 35 |
class Mapping(object): |
36 |
field_id = None |
|
37 |
expression = None |
|
38 | ||
35 | 39 |
def __init__(self, field_id, expression): |
36 | 40 |
self.field_id = field_id |
37 | 41 |
self.expression = expression |
... | ... | |
178 | 182 |
keep_submission_context = False |
179 | 183 |
mappings = None |
180 | 184 |
varname = None |
185 |
map_fields_by_varname = False |
|
181 | 186 | |
182 | 187 |
@classmethod |
183 | 188 |
def is_available(cls, workflow=None): |
... | ... | |
237 | 242 |
title=_('Identifier'), value=self.varname, |
238 | 243 |
hint=_('This is used to get linked forms in expressions.'), |
239 | 244 |
advanced=not(bool(self.varname))) |
245 |
if 'map_fields_by_varname' in parameters and self.formdef: |
|
246 |
form.add(CheckboxWidget, '%smap_fields_by_varname' % prefix, |
|
247 |
title=_('Map fields by varname'), |
|
248 |
value=self.map_fields_by_varname, |
|
249 |
advanced=( |
|
250 |
self.map_fields_by_varname == CreateFormdataWorkflowStatusItem.map_fields_by_varname)) |
|
251 |
if self.map_fields_by_varname: |
|
252 |
common_varnames = [htmltext('<tt>%s</tt>') % varname for varname in self._common_varnames()] |
|
253 |
common_varnames = htmltext(', ').join(common_varnames) |
|
254 |
form.widgets.append( |
|
255 |
HtmlWidget( |
|
256 |
htmltext( |
|
257 |
'<div class="infonotice">%s %s</div>') % (_('Common varnames:'), common_varnames))) |
|
258 | ||
259 |
def _common_varnames(self): |
|
260 |
'''Compute common varnames between the targeted formdef and all formdefs related to the parent workflow.''' |
|
261 |
assert self.formdef |
|
262 |
varnames = set(field.varname |
|
263 |
for formdef in self.parent.parent.formdefs() |
|
264 |
for field in formdef.get_widget_fields() if field.varname) |
|
265 |
return sorted(varnames & set(field.varname for field in self.formdef.get_widget_fields() if field.varname)) |
|
240 | 266 | |
241 | 267 |
def submit_admin_form(self, form): |
242 | 268 |
self.mappings = [] |
243 | 269 |
super(CreateFormdataWorkflowStatusItem, self).submit_admin_form(form) |
244 | 270 | |
245 | 271 |
def get_parameters(self): |
246 |
return ('formdef_slug', 'mappings', 'draft', 'backoffice_submission', |
|
272 |
return ('formdef_slug', 'map_fields_by_varname', 'mappings', 'draft', 'backoffice_submission',
|
|
247 | 273 |
'keep_user', 'keep_submission_context', 'varname') |
248 | 274 | |
249 | 275 |
def perform(self, formdata): |
... | ... | |
292 | 318 |
formdata.store() |
293 | 319 | |
294 | 320 |
def apply_mappings(self, dest, src): |
295 |
if not self.mappings: |
|
296 |
return |
|
297 | ||
298 |
# field.id can be serialized to xml, so we must alwat convert them to str when matching |
|
321 |
if self.map_fields_by_varname: |
|
322 |
fields_by_varname = {field.varname: field for field in self.formdef.get_widget_fields() if field.varname} |
|
323 |
for field in src.formdef.get_widget_fields(): |
|
324 |
dest_field = fields_by_varname.get(field.varname) |
|
325 |
if dest_field is None: |
|
326 |
continue |
|
327 |
try: |
|
328 |
self._set_value( |
|
329 |
formdata=dest, |
|
330 |
field=dest_field, |
|
331 |
value=src.data.get(field.id)) |
|
332 |
except Exception as e: |
|
333 |
LoggedError.record('Could copy field by varname for %s' % field.varname, |
|
334 |
formdata=src, status_item=self, exception=e) |
|
335 | ||
336 |
# field.id can be serialized to xml, so we must always convert them to |
|
337 |
# str when matching |
|
299 | 338 |
to_id_fields = {str(field.id): field for field in self.formdef.get_widget_fields()} |
300 | ||
301 | 339 |
missing_fields = [] |
302 | 340 | |
303 | 341 |
for mapping in self.mappings: |
304 |
- |