0001-wf-add-action-to-add-card-39997.patch
tests/test_backoffice_pages.py | ||
---|---|---|
47 | 47 |
from wcs.wf.register_comment import RegisterCommenterWorkflowStatusItem |
48 | 48 |
from wcs.wf.resubmit import ResubmitWorkflowStatusItem |
49 | 49 |
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping |
50 |
from wcs.wf.cards import CardAddWorkflowStatusItem |
|
50 | 51 |
from wcs.carddef import CardDef |
51 | 52 |
from wcs.categories import Category |
52 | 53 |
from wcs.formdef import FormDef |
... | ... | |
5919 | 5920 |
pq = resp.pyquery.remove_namespaces() |
5920 | 5921 |
assert pq('.field-type-string .value').text() == 'coucou' |
5921 | 5922 |
assert pq('.field-type-file .value').text() == 'bar' |
5923 | ||
5924 | ||
5925 |
def test_backoffice_create_carddata_from_formdata(pub, studio): |
|
5926 |
CardDef.wipe() |
|
5927 |
FormDef.wipe() |
|
5928 | ||
5929 |
user = create_user(pub, is_admin=True) |
|
5930 |
user.name = 'Foo Bar' |
|
5931 |
user.email = 'foo@example.com' |
|
5932 |
user.store() |
|
5933 | ||
5934 |
carddef = CardDef() |
|
5935 |
carddef.name = 'My card' |
|
5936 |
carddef.fields = [ |
|
5937 |
fields.StringField(id='1', label='string'), |
|
5938 |
fields.ItemField(id='2', label='List', items=['item1', 'item2']), |
|
5939 |
fields.DateField(id='3', label='Date') |
|
5940 |
] |
|
5941 |
carddef.store() |
|
5942 | ||
5943 |
wf = Workflow(name='create-carddata') |
|
5944 |
st1 = wf.add_status('New') |
|
5945 |
st2 = wf.add_status('Create card') |
|
5946 | ||
5947 |
jump = ChoiceWorkflowStatusItem() |
|
5948 |
jump.id = '_createcard' |
|
5949 |
jump.label = 'Create card' |
|
5950 |
jump.by = ['_receiver'] |
|
5951 |
jump.status = st2.id |
|
5952 |
jump.parent = st1 |
|
5953 |
st1.items.append(jump) |
|
5954 | ||
5955 |
create_card = CardAddWorkflowStatusItem() |
|
5956 |
create_card.label = 'Create Card Data' |
|
5957 |
create_card.varname = 'mycard' |
|
5958 |
create_card.id = '_create' |
|
5959 |
create_card.formdef_slug = carddef.url_name |
|
5960 |
create_card.mappings = [ |
|
5961 |
Mapping(field_id='1', expression='Simple String'), |
|
5962 |
Mapping(field_id='2', expression='=form_var_list_raw'), |
|
5963 |
Mapping(field_id='3', expression='=form_var_date'), |
|
5964 |
] |
|
5965 |
create_card.parent = st2 |
|
5966 |
st2.items.append(create_card) |
|
5967 | ||
5968 |
display_message = DisplayMessageWorkflowStatusItem() |
|
5969 |
display_message.message = 'Card nr. {{ form_cards_mycard_form_number }} created' |
|
5970 |
display_message.parent = st2 |
|
5971 |
st2.items.append(display_message) |
|
5972 |
wf.store() |
|
5973 | ||
5974 |
formdef = FormDef() |
|
5975 |
formdef.name = 'Source form' |
|
5976 |
formdef.workflow_roles = {'_receiver': 1} |
|
5977 |
formdef.fields = [ |
|
5978 |
fields.ItemField(id='1', label='List', items=['item1', 'item2'], |
|
5979 |
varname='list'), |
|
5980 |
fields.DateField(id='2', label='Date', varname='date') |
|
5981 |
] |
|
5982 |
formdef.workflow_id = wf.id |
|
5983 |
formdef.store() |
|
5984 | ||
5985 |
formdata = formdef.data_class()() |
|
5986 |
today = time.strptime('2020-01-01', '%Y-%m-%d') |
|
5987 |
formdata.data = { |
|
5988 |
'1': 'item2', |
|
5989 |
'2': today |
|
5990 |
} |
|
5991 | ||
5992 |
formdata.user = user |
|
5993 |
formdata.just_created() |
|
5994 |
formdata.store() |
|
5995 |
formdata.perform_workflow() |
|
5996 | ||
5997 |
app = login(get_app(pub)) |
|
5998 |
resp = app.get(formdata.get_url(backoffice=True)) |
|
5999 |
resp = resp.form.submit(name='button_createcard').follow() |
|
6000 |
assert 'Card nr. 1-1 created' in resp |
tests/test_workflows.py | ||
---|---|---|
21 | 21 |
from wcs.qommon.form import * |
22 | 22 | |
23 | 23 |
from wcs.formdef import FormDef |
24 |
from wcs.carddef import CardDef |
|
24 | 25 |
from wcs import sessions |
25 | 26 |
from wcs.fields import (StringField, DateField, MapField, FileField, ItemField, |
26 | 27 |
ItemsField, CommentField) |
... | ... | |
52 | 53 |
from wcs.wf.redirect_to_url import RedirectToUrlWorkflowStatusItem |
53 | 54 |
from wcs.wf.notification import SendNotificationWorkflowStatusItem |
54 | 55 |
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping |
56 |
from wcs.wf.cards import CardAddWorkflowStatusItem |
|
55 | 57 | |
56 | 58 | |
57 | 59 |
from utilities import (create_temporary_pub, MockSubstitutionVariables, |
... | ... | |
4405 | 4407 |
assert len(errors) == 2 |
4406 | 4408 |
assert any('form_var_toto_string' in (error.exception_message or '') for error in errors) |
4407 | 4409 |
assert any('Missing field' in error.summary for error in errors) |
4410 | ||
4411 | ||
4412 |
def test_create_carddata(pub): |
|
4413 |
CardDef.wipe() |
|
4414 |
FormDef.wipe() |
|
4415 |
LoggedError.wipe() |
|
4416 | ||
4417 | ||
4418 |
carddef = CardDef() |
|
4419 |
carddef.name = 'My card' |
|
4420 |
carddef.fields = [ |
|
4421 |
StringField(id='1', label='string'), |
|
4422 |
ItemField(id='2', label='List', items=['item1', 'item2'], |
|
4423 |
varname='clist'), |
|
4424 |
DateField(id='3', label='Date', varname='cdate') |
|
4425 |
] |
|
4426 |
carddef.store() |
|
4427 | ||
4428 |
wf = Workflow(name='create-carddata') |
|
4429 |
wf.possible_status = Workflow.get_default_workflow().possible_status[:] |
|
4430 |
create = CardAddWorkflowStatusItem() |
|
4431 |
create.label = 'Create CardDef' |
|
4432 |
create.varname = 'mycard' |
|
4433 |
create.id = '_create' |
|
4434 |
create.formdef_slug = carddef.url_name |
|
4435 |
create.mappings = [ |
|
4436 |
Mapping(field_id='1', expression='=form_var_undefined'), |
|
4437 |
Mapping(field_id='2', expression='=form_var_list_raw'), |
|
4438 |
Mapping(field_id='3', expression='=form_var_date'), |
|
4439 |
] |
|
4440 |
create.parent = wf.possible_status[1] |
|
4441 |
wf.possible_status[1].items.insert(0, create) |
|
4442 |
wf.store() |
|
4443 | ||
4444 |
formdef = FormDef() |
|
4445 |
formdef.name = 'source form' |
|
4446 |
formdef.fields = [ |
|
4447 |
ItemField(id='1', label='List', items=['item1', 'item2'], |
|
4448 |
varname='list'), |
|
4449 |
DateField(id='2', label='Date', varname='date') |
|
4450 |
] |
|
4451 |
formdef.workflow_id = wf.id |
|
4452 |
formdef.store() |
|
4453 | ||
4454 |
formdata = formdef.data_class()() |
|
4455 |
formdata.data = {} |
|
4456 |
formdata.just_created() |
|
4457 | ||
4458 |
assert carddef.data_class().count() == 0 |
|
4459 | ||
4460 |
formdata = formdef.data_class()() |
|
4461 |
formdata.data = {} |
|
4462 | ||
4463 |
formdata.just_created() |
|
4464 |
formdata.perform_workflow() |
|
4465 | ||
4466 |
assert carddef.data_class().count() == 1 |
|
4467 | ||
4468 |
errors = LoggedError.select() |
|
4469 |
assert len(errors) == 1 |
|
4470 |
assert any('form_var_undefined' in (error.exception_message or '') for error in errors) |
|
4471 | ||
4472 |
formdata = formdef.data_class()() |
|
4473 |
today = datetime.date.today() |
|
4474 | ||
4475 |
formdata.data = {'1': 'item1', '2': today} |
|
4476 |
formdata.just_created() |
|
4477 |
formdata.perform_workflow() |
|
4478 | ||
4479 |
assert formdata.get_substitution_variables()['form_cards_mycard_form_number'] == '1-2' |
|
4480 |
carddata = carddef.data_class().get(id=2) |
|
4481 |
assert carddata.get_substitution_variables()['form_var_clist'] == 'item1' |
|
4482 |
assert carddata.get_substitution_variables()['form_var_cdate'] == today |
wcs/variables.py | ||
---|---|---|
421 | 421 | |
422 | 422 |
return LazyFormDataLinks(self._formdata) |
423 | 423 | |
424 |
@property |
|
425 |
def cards(self): |
|
426 |
from .wf.cards import LazyCardDataLinks |
|
427 |
return LazyCardDataLinks(self._formdata) |
|
428 | ||
424 | 429 |
def export_to_json(self, include_files=True): |
425 | 430 |
# this gets used to generate an email attachment :/ |
426 | 431 |
return self._formdata.export_to_json(include_files=include_files) |
wcs/wf/cards.py | ||
---|---|---|
1 |
# w.c.s. - web application for online forms |
|
2 |
# Copyright (C) 2005-2020 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software; you can redistribute it and/or modify |
|
5 |
# it under the terms of the GNU General Public License as published by |
|
6 |
# the Free Software Foundation; either version 2 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU General Public License |
|
15 |
# along with this program; if not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
from quixote import get_publisher |
|
18 | ||
19 |
from ..qommon import _ |
|
20 |
from wcs.workflows import register_item_class |
|
21 |
from wcs.carddef import CardDef |
|
22 | ||
23 |
from wcs.wf.create_formdata import (CreateFormdataWorkflowStatusItem, |
|
24 |
LinkedFormdataEvolutionPart, |
|
25 |
LazyFormDataLinks) |
|
26 | ||
27 | ||
28 |
class LinkedCardDataEvolutionPart(LinkedFormdataEvolutionPart): |
|
29 |
formdef_class = CardDef |
|
30 |
repr_prefix = 'Card' |
|
31 |
form_property_name = 'cards' |
|
32 | ||
33 | ||
34 |
class LazyCardDataLinks(LazyFormDataLinks): |
|
35 |
evolution_part_class = LinkedCardDataEvolutionPart |
|
36 | ||
37 | ||
38 |
class CardManagement(object): |
|
39 | ||
40 |
@classmethod |
|
41 |
def is_available(cls, workflow=None): |
|
42 |
return get_publisher().has_site_option('studio') |
|
43 | ||
44 | ||
45 |
class CardAddWorkflowStatusItem(CardManagement, CreateFormdataWorkflowStatusItem): |
|
46 |
description = N_('Add Card') |
|
47 |
key = 'add-card' |
|
48 |
category = 'formdata-action' |
|
49 |
ok_in_global_action = True |
|
50 | ||
51 |
formdef_class = CardDef |
|
52 |
evolution_part_class = LinkedCardDataEvolutionPart |
|
53 | ||
54 |
formdef_label = N_('Card') |
|
55 |
mappings_label = N_('Mappings to card fields') |
|
56 |
varname_hint = N_('Used to get linked card in expressions.') |
|
57 | ||
58 |
def get_parameters(self): |
|
59 |
return ('formdef_slug', 'mappings', 'keep_user', 'varname') |
|
60 | ||
61 | ||
62 |
register_item_class(CardAddWorkflowStatusItem) |
wcs/wf/create_formdata.py | ||
---|---|---|
111 | 111 | |
112 | 112 |
class LinkedFormdataEvolutionPart(object): |
113 | 113 |
formdef_class = FormDef |
114 |
repr_prefix = 'Link' |
|
115 |
form_property_name = 'links' |
|
114 | 116 | |
115 | 117 |
def __init__(self, formdata, varname=None): |
116 | 118 |
self._formdef = formdata.formdef |
... | ... | |
136 | 138 |
return {k: v for k, v in self.__dict__.items() if not k.startswith('_')} |
137 | 139 | |
138 | 140 |
def __repr__(self): |
139 |
return '<Link "%s-%s">' % (self.formdef_id, self.formdata_id)
|
|
141 |
return '<%s "%s-%s">' % (self.repr_prefix, self.formdef_id, self.formdata_id)
|
|
140 | 142 | |
141 | 143 |
@classmethod |
142 | 144 |
def get_substitution_variables(cls, formdata): |
143 | 145 |
d = {} |
144 | 146 |
for part in formdata.iter_evolution_parts(): |
145 |
if not isinstance(part, LinkedFormdataEvolutionPart):
|
|
147 |
if not isinstance(part, cls):
|
|
146 | 148 |
continue |
147 | 149 |
if part.formdata: |
148 |
d['form_links_%s' % (part.varname or '*')] = part
|
|
150 |
d['form_%s_%s' % (cls.form_property_name, part.varname or '*')] = part
|
|
149 | 151 |
return d |
150 | 152 | |
151 | 153 | |
152 | 154 |
class LazyFormDataLinks(object): |
155 |
evolution_part_class = LinkedFormdataEvolutionPart |
|
156 | ||
153 | 157 |
def __init__(self, formdata): |
154 | 158 |
self._formdata = formdata |
155 | 159 | |
156 | 160 |
def __getattr__(self, varname): |
157 | 161 |
for part in self._formdata.iter_evolution_parts(): |
158 |
if not isinstance(part, LinkedFormdataEvolutionPart):
|
|
162 |
if not isinstance(part, self.evolution_part_class):
|
|
159 | 163 |
continue |
160 | 164 |
if part.varname == varname and part.formdata: |
161 | 165 |
return part.formdata.get_substitution_variables() |
... | ... | |
172 | 176 |
evolution_part_class = LinkedFormdataEvolutionPart |
173 | 177 | |
174 | 178 |
formdef_slug = None |
179 |
formdef_label = _('Form') |
|
180 |
mappings_label = _('Mappings to new form fields') |
|
181 |
varname_hint = _('This is used to get linked forms in expressions.') |
|
182 | ||
175 | 183 |
draft = False |
176 | 184 |
backoffice_submission = False |
177 | 185 |
keep_user = True |
... | ... | |
202 | 210 |
list_forms = [(None, '---', '')] |
203 | 211 |
list_forms += [(x.url_name, x.name, x.url_name) for x in self.formdef_class.select(order_by='name')] |
204 | 212 |
form.add(SingleSelectWidget, 'formdef_slug', |
205 |
title=_('Form'),
|
|
213 |
title=self.formdef_label,
|
|
206 | 214 |
value=self.formdef_slug, |
207 | 215 |
options=list_forms) |
208 | 216 |
if 'draft' in parameters: |
... | ... | |
228 | 236 |
formdef = self._resolve_formdef_slug(form.get('formdef_slug')) |
229 | 237 |
if 'mappings' in parameters and formdef: |
230 | 238 |
form.add(MappingsWidget, '%smappings' % prefix, |
231 |
title=_('Mappings to new form fields'),
|
|
239 |
title=self.mappings_label,
|
|
232 | 240 |
to_formdef=formdef, |
233 | 241 |
value=self.mappings) |
234 | 242 |
if 'varname' in parameters: |
235 | 243 |
form.add(VarnameWidget, '%svarname' % prefix, |
236 | 244 |
title=_('Identifier'), value=self.varname, |
237 |
hint=_('This is used to get linked forms in expressions.'),
|
|
245 |
hint=self.varname_hint,
|
|
238 | 246 |
advanced=not(bool(self.varname))) |
239 | 247 | |
240 | 248 |
def submit_admin_form(self, form): |
wcs/workflows.py | ||
---|---|---|
2912 | 2912 |
from .wf import redirect_to_url |
2913 | 2913 |
from .wf import notification |
2914 | 2914 |
from .wf import create_formdata |
2915 |
from .wf import cards |
|
2915 | 2916 | |
2916 | 2917 |
from .wf.export_to_model import ExportToModel |
2917 |
- |