workflows: extend create carddata/formdata user association options (#51593)
This commit is contained in:
parent
5415020101
commit
e886daee6f
|
@ -5519,7 +5519,7 @@ def test_workflow_inspect_page(pub):
|
|||
create_formdata.varname = 'resubmitted'
|
||||
create_formdata.draft = True
|
||||
create_formdata.formdef_slug = target_formdef.url_name
|
||||
create_formdata.keep_user = True
|
||||
create_formdata.user_association_mode = 'keep-user'
|
||||
create_formdata.backoffice_submission = True
|
||||
create_formdata.mappings = [
|
||||
Mapping(field_id='0', expression='=form_var_toto_string'),
|
||||
|
@ -5752,7 +5752,7 @@ def create_formdata(request, pub):
|
|||
create_formdata.varname = 'resubmitted'
|
||||
create_formdata.draft = True
|
||||
create_formdata.formdef_slug = target_formdef.url_name
|
||||
create_formdata.keep_user = True
|
||||
create_formdata.user_association_mode = 'keep-user'
|
||||
create_formdata.backoffice_submission = True
|
||||
create_formdata.attach_to_history = request.param.get('attach_to_history', False)
|
||||
create_formdata.mappings = [
|
||||
|
|
|
@ -5633,6 +5633,29 @@ def test_create_formdata(two_pubs):
|
|||
assert target_formdef.data_class().count() == 0
|
||||
|
||||
|
||||
def test_create_formdata_migration(pub):
|
||||
wf = Workflow(name='create-formdata')
|
||||
st1 = wf.add_status('Status1', 'st1')
|
||||
|
||||
create = CreateFormdataWorkflowStatusItem()
|
||||
create.id = '_create'
|
||||
create.label = 'create a new linked form'
|
||||
create.varname = 'resubmitted'
|
||||
create.mappings = [
|
||||
Mapping(field_id='0', expression='=form_var_toto_string'),
|
||||
Mapping(field_id='1', expression='=form_var_toto_file_raw'),
|
||||
Mapping(field_id='2', expression='=form_var_toto_item_raw'),
|
||||
]
|
||||
create.parent = st1
|
||||
create.keep_user = True
|
||||
st1.items.append(create)
|
||||
wf.store()
|
||||
|
||||
wf = Workflow.get(wf.id)
|
||||
assert wf.possible_status[0].items[0].user_association_mode == 'keep-user'
|
||||
assert not hasattr(wf.possible_status[0].items[0], 'keep_user')
|
||||
|
||||
|
||||
def test_create_formdata_tracking_code(two_pubs, emails):
|
||||
FormDef.wipe()
|
||||
if two_pubs.is_using_postgresql():
|
||||
|
@ -5782,6 +5805,139 @@ def test_create_carddata(two_pubs):
|
|||
assert carddef.data_class().count() == 0
|
||||
|
||||
|
||||
def test_create_carddata_user_association(two_pubs):
|
||||
CardDef.wipe()
|
||||
FormDef.wipe()
|
||||
two_pubs.user_class.wipe()
|
||||
|
||||
user = two_pubs.user_class()
|
||||
user.email = 'test@example.net'
|
||||
user.name_identifiers = ['xyz']
|
||||
user.store()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'My card'
|
||||
carddef.fields = []
|
||||
carddef.user_support = 'optional'
|
||||
carddef.store()
|
||||
|
||||
wf = Workflow(name='create-carddata')
|
||||
wf.possible_status = Workflow.get_default_workflow().possible_status[:]
|
||||
create = CreateCarddataWorkflowStatusItem()
|
||||
create.label = 'Create CardDef'
|
||||
create.varname = 'mycard'
|
||||
create.id = '_create'
|
||||
create.formdef_slug = carddef.url_name
|
||||
create.map_fields_by_varname = True
|
||||
create.parent = wf.possible_status[1]
|
||||
wf.possible_status[1].items.insert(0, create)
|
||||
wf.store()
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'source form'
|
||||
formdef.fields = []
|
||||
formdef.workflow_id = wf.id
|
||||
formdef.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user is None
|
||||
|
||||
# keep user
|
||||
carddef.data_class().wipe()
|
||||
create.user_association_mode = 'keep-user'
|
||||
wf.store()
|
||||
|
||||
formdata = FormDef.get(formdef.id).data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user.id == user.id
|
||||
|
||||
# user association on direct user
|
||||
carddef.data_class().wipe()
|
||||
create.user_association_mode = 'custom'
|
||||
create.user_association_template = '{{ form_user }}'
|
||||
wf.store()
|
||||
|
||||
formdata = FormDef.get(formdef.id).data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user.id == user.id
|
||||
|
||||
# user association on user email
|
||||
carddef.data_class().wipe()
|
||||
create.user_association_mode = 'custom'
|
||||
create.user_association_template = 'test@example.net'
|
||||
wf.store()
|
||||
|
||||
formdata = FormDef.get(formdef.id).data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user.id == user.id
|
||||
|
||||
# user association on name id
|
||||
carddef.data_class().wipe()
|
||||
create.user_association_mode = 'custom'
|
||||
create.user_association_template = 'xyz'
|
||||
wf.store()
|
||||
|
||||
formdata = FormDef.get(formdef.id).data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user.id == user.id
|
||||
|
||||
# user association on invalid user
|
||||
carddef.data_class().wipe()
|
||||
create.user_association_mode = 'custom'
|
||||
create.user_association_template = 'zzz'
|
||||
wf.store()
|
||||
|
||||
formdata = FormDef.get(formdef.id).data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user is None
|
||||
|
||||
# user association on invalid template
|
||||
carddef.data_class().wipe()
|
||||
create.user_association_mode = 'custom'
|
||||
create.user_association_template = '{% %}'
|
||||
wf.store()
|
||||
|
||||
formdata = FormDef.get(formdef.id).data_class()()
|
||||
formdata.data = {}
|
||||
formdata.user_id = user.id
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert carddef.data_class().count() == 1
|
||||
assert carddef.data_class().select()[0].user is None
|
||||
|
||||
|
||||
def test_call_external_workflow_with_evolution_linked_object(two_pubs):
|
||||
FormDef.wipe()
|
||||
CardDef.wipe()
|
||||
|
|
|
@ -349,17 +349,8 @@ class ImportFromCsvAfterJob(AfterJob):
|
|||
|
||||
def user_lookup(self, user_value):
|
||||
if self.carddef.user_support != 'optional':
|
||||
return
|
||||
if not user_value:
|
||||
return
|
||||
users = []
|
||||
if '@' in user_value:
|
||||
users = get_publisher().user_class.get_users_with_email(user_value)
|
||||
else:
|
||||
users = get_publisher().user_class.get_users_with_name_identifier(user_value)
|
||||
if not users:
|
||||
return
|
||||
return users[0]
|
||||
return None
|
||||
return get_publisher().user_class.lookup_by_string(user_value)
|
||||
|
||||
def execute(self):
|
||||
self.carddef = self.kwargs['carddef_class'].get(self.kwargs['carddef_id'])
|
||||
|
|
17
wcs/users.py
17
wcs/users.py
|
@ -209,6 +209,23 @@ class User(StorableObject):
|
|||
d[prefix + 'user_name_identifier_%d' % i] = name_identifier
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def lookup_by_string(cls, user_value):
|
||||
# lookup a single user using some string identifier, it can either be
|
||||
# an email address or a uuid (name id).
|
||||
if not user_value:
|
||||
return None
|
||||
if '@' in user_value:
|
||||
users = cls.get_users_with_email(user_value)
|
||||
else:
|
||||
users = cls.get_users_with_name_identifier(user_value)
|
||||
if not users:
|
||||
return None
|
||||
# hopefully the list has a single item but sort it on id to get a
|
||||
# stable value in case there are multiple items.
|
||||
users.sort(key=lambda x: x.id)
|
||||
return users[0]
|
||||
|
||||
@classmethod
|
||||
def get_substitution_variables_list(cls, prefix='session_'):
|
||||
formdef = cls.get_formdef()
|
||||
|
|
|
@ -39,13 +39,21 @@ class CreateCarddataWorkflowStatusItem(CreateFormdataWorkflowStatusItem):
|
|||
formdef_label = N_('Card')
|
||||
mappings_label = N_('Mappings to new card fields')
|
||||
varname_hint = N_('This is used to get linked card in expressions.')
|
||||
user_association_option_label = N_('User to associate to card')
|
||||
|
||||
@classmethod
|
||||
def is_available(cls, workflow=None):
|
||||
return get_publisher().has_site_option('studio')
|
||||
|
||||
def get_parameters(self):
|
||||
return ('formdef_slug', 'mappings', 'keep_user', 'varname', 'condition')
|
||||
return (
|
||||
'formdef_slug',
|
||||
'mappings',
|
||||
'user_association_mode',
|
||||
'user_association_template',
|
||||
'varname',
|
||||
'condition',
|
||||
)
|
||||
|
||||
|
||||
register_item_class(CreateCarddataWorkflowStatusItem)
|
||||
|
|
|
@ -29,6 +29,7 @@ from wcs.qommon.form import (
|
|||
CompositeWidget,
|
||||
SingleSelectWidget,
|
||||
ComputedExpressionWidget,
|
||||
RadiobuttonsWidget,
|
||||
CheckboxWidget,
|
||||
VarnameWidget,
|
||||
HtmlWidget,
|
||||
|
@ -218,16 +219,26 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
mappings_label = N_('Mappings to new form fields')
|
||||
accept_empty_value = False
|
||||
varname_hint = N_('This is used to get linked forms in expressions.')
|
||||
user_association_option_label = N_('User to associate to form')
|
||||
|
||||
draft = False
|
||||
backoffice_submission = False
|
||||
keep_user = True
|
||||
user_association_mode = None
|
||||
user_association_template = None
|
||||
keep_submission_context = False
|
||||
mappings = None
|
||||
varname = None
|
||||
map_fields_by_varname = False
|
||||
attach_to_history = False
|
||||
|
||||
def migrate(self):
|
||||
changed = super().migrate()
|
||||
if getattr(self, 'keep_user', False) is True:
|
||||
self.user_association_mode = 'keep-user'
|
||||
delattr(self, 'keep_user')
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
def _resolve_formdef_slug(self, formdef_slug):
|
||||
if formdef_slug:
|
||||
try:
|
||||
|
@ -268,15 +279,33 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
self.backoffice_submission == CreateFormdataWorkflowStatusItem.backoffice_submission
|
||||
),
|
||||
)
|
||||
if 'keep_user' in parameters:
|
||||
if 'user_association_mode' in parameters:
|
||||
form.add(
|
||||
CheckboxWidget,
|
||||
'%skeep_user' % prefix,
|
||||
title=_('Keep user'),
|
||||
value=self.keep_user,
|
||||
advanced=(self.keep_user == CreateFormdataWorkflowStatusItem.keep_user),
|
||||
RadiobuttonsWidget,
|
||||
'%suser_association_mode' % prefix,
|
||||
title=_(self.user_association_option_label),
|
||||
options=[
|
||||
(None, _('None'), 'none'),
|
||||
('keep-user', _('Keep Current User'), 'keep-user'),
|
||||
('custom', _('Custom (user will come from template value)'), 'custom'),
|
||||
],
|
||||
value=self.user_association_mode,
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
advanced=bool(self.user_association_mode),
|
||||
)
|
||||
if 'keep_submission_context' in parameters and self.keep_user:
|
||||
if 'user_association_template' in parameters:
|
||||
form.add(
|
||||
ComputedExpressionWidget,
|
||||
'%suser_association_template' % prefix,
|
||||
title=_('Template for user association (via email or NameID)'),
|
||||
value=self.user_association_template,
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%suser_association_mode' % prefix,
|
||||
'data-dynamic-display-value': 'custom',
|
||||
},
|
||||
advanced=bool(self.user_association_mode),
|
||||
)
|
||||
if 'keep_submission_context' in parameters:
|
||||
form.add(
|
||||
CheckboxWidget,
|
||||
'%skeep_submission_context' % prefix,
|
||||
|
@ -377,7 +406,8 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
'map_fields_by_varname',
|
||||
'mappings',
|
||||
'backoffice_submission',
|
||||
'keep_user',
|
||||
'user_association_mode',
|
||||
'user_association_template',
|
||||
'keep_submission_context',
|
||||
'varname',
|
||||
'attach_to_history',
|
||||
|
@ -397,10 +427,34 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
new_formdata = formdef.data_class()()
|
||||
new_formdata.receipt_time = time.localtime()
|
||||
|
||||
if self.keep_user:
|
||||
if self.user_association_mode == 'keep-user':
|
||||
new_formdata.user_id = formdata.user_id
|
||||
elif self.user_association_mode == 'custom' and self.user_association_template:
|
||||
with get_publisher().complex_data():
|
||||
try:
|
||||
value = self.compute(
|
||||
self.user_association_template,
|
||||
formdata=formdata,
|
||||
raises=True,
|
||||
allow_complex=True,
|
||||
status_item=self,
|
||||
)
|
||||
except Exception:
|
||||
# already logged by self.compute
|
||||
value = None
|
||||
else:
|
||||
value = get_publisher().get_cached_complex_data(value)
|
||||
|
||||
if self.keep_submission_context and self.keep_user:
|
||||
from wcs.variables import LazyUser
|
||||
|
||||
if isinstance(value, LazyUser):
|
||||
value = value._user
|
||||
if isinstance(value, get_publisher().user_class):
|
||||
new_formdata.user = value
|
||||
else:
|
||||
new_formdata.user = get_publisher().user_class.lookup_by_string(value)
|
||||
|
||||
if self.keep_submission_context:
|
||||
new_formdata.submission_context = formdata.submission_context or {}
|
||||
new_formdata.submission_channel = formdata.submission_channel
|
||||
new_formdata.submission_agent_id = formdata.submission_agent_id
|
||||
|
|
Loading…
Reference in New Issue