workflows: don't crash on removed create formdata action target formdef (#54390)

This commit is contained in:
Frédéric Péters 2021-05-28 23:53:30 +02:00
parent 2675eefcfd
commit 009b64315e
2 changed files with 79 additions and 5 deletions

View File

@ -5854,6 +5854,67 @@ def test_create_formdata_tracking_code(two_pubs, emails):
assert tracking_code in emails.get('Foobar')['payload']
def test_create_formdata_attach_to_history(two_pubs):
FormDef.wipe()
if two_pubs.is_using_postgresql():
two_pubs.loggederror_class.wipe()
two_pubs.tracking_code_class.wipe()
target_formdef = FormDef()
target_formdef.name = 'target form'
target_formdef.fields = [
StringField(id='0', label='string', varname='foo_string'),
]
target_formdef.store()
target_formdef.data_class().wipe()
wf = Workflow(name='create-formdata')
wf.possible_status = Workflow.get_default_workflow().possible_status[:]
create = CreateFormdataWorkflowStatusItem()
create.label = 'create a new linked form'
create.varname = 'resubmitted'
create.id = '_create'
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 = wf.possible_status[1]
wf.possible_status[1].items.insert(0, create)
wf.store()
source_formdef = FormDef()
source_formdef.name = 'source form'
source_formdef.fields = []
source_formdef.workflow_id = wf.id
source_formdef.store()
formdata = source_formdef.data_class()()
formdata.data = {}
formdata.just_created()
create.formdef_slug = target_formdef.url_name
create.attach_to_history = True
wf.store()
del source_formdef._workflow
formdata.perform_workflow()
assert target_formdef.data_class().count() == 1
assert formdata.evolution[-1].parts[0].attach_to_history is True
assert 'Created new form' in str(formdata.evolution[-1].parts[0].view())
assert target_formdef.get_url() in str(formdata.evolution[-1].parts[0].view())
# don't crash in case target formdata is removed
formdata.refresh_from_storage()
target_formdef.data_class().wipe()
assert 'deleted' in str(formdata.evolution[-1].parts[0].view())
# don't crash in case target formdef is removed
target_formdef.remove_self()
formdata.refresh_from_storage()
assert 'deleted' in str(formdata.evolution[-1].parts[0].view())
def test_create_carddata(two_pubs):
CardDef.wipe()
FormDef.wipe()

View File

@ -159,7 +159,12 @@ class LinkedFormdataEvolutionPart(EvolutionPart):
return {k: v for k, v in self.__dict__.items() if not k.startswith('_')}
def __repr__(self):
return '<Linked %s "%s-%s">' % (self.formdef_class.__name__, self.formdef_id, self.formdata_id)
return '<%s %s "%s-%s">' % (
self.__class__.__name__,
self.formdef_class.__name__,
self.formdef_id,
self.formdata_id,
)
@classmethod
def get_substitution_variables(cls, formdata):
@ -173,12 +178,20 @@ class LinkedFormdataEvolutionPart(EvolutionPart):
def view(self):
if self.attach_to_history:
try:
formdata = self.formdata
if formdata is None:
raise KeyError
except KeyError:
return htmltext('<p class="wf-links">%s (%s, %s-%s)</p>') % (
_('Created new form'),
_('deleted'),
self.formdef_id,
self.formdata_id,
)
return htmltext('<p class="wf-links">%s <a href="%s">%s %s</a>') % (
_('Created new form'),
self.formdata
and self.formdata.get_url(
backoffice=bool(get_request() and get_request().is_in_backoffice())
),
formdata.get_url(backoffice=bool(get_request() and get_request().is_in_backoffice())),
self.formdef.name if self.formdef else _('Deleted'),
self.formdata_id,
)