workflow: allow to send generated docs in backoffice field (#19188)

This commit is contained in:
Thomas NOËL 2017-10-04 11:40:47 +02:00
parent eb586a7cfa
commit 2b193960e9
3 changed files with 163 additions and 3 deletions

View File

@ -19,7 +19,8 @@ from quixote.http_request import Upload as QuixoteUpload
from wcs.qommon.form import UploadedFile
from wcs.qommon.ident.password_accounts import PasswordAccount
from wcs.formdef import FormDef
from wcs.workflows import Workflow, EditableWorkflowStatusItem, DisplayMessageWorkflowStatusItem
from wcs.workflows import (Workflow, EditableWorkflowStatusItem,
DisplayMessageWorkflowStatusItem, WorkflowBackofficeFieldsFormDef)
from wcs.wf.export_to_model import ExportToModel, transform_to_pdf
from wcs.wf.jump import JumpWorkflowStatusItem
from wcs.wf.attachment import AddAttachmentWorkflowStatusItem
@ -2551,6 +2552,70 @@ def test_formdata_generated_document_non_interactive(pub):
assert formdef.data_class().count() == 1
assert formdef.data_class().select()[0].status == 'wf-st2'
def test_formdata_generated_document_to_backoffice_field(pub):
create_user_and_admin(pub)
wf = Workflow(name='status')
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
wf.backoffice_fields_formdef.fields = [
fields.FileField(id='bo1', label='bo field 1', type='file'),
fields.StringField(id='bo2', label='bo field 2', type='string'),
]
st1 = wf.add_status('Status1', 'st1')
export_to = ExportToModel()
export_to.method = 'non-interactive'
template_filename = os.path.join(os.path.dirname(__file__), 'template.odt')
template = open(template_filename).read()
upload = QuixoteUpload('/foo/template.odt', content_type='application/octet-stream')
upload.fp = StringIO.StringIO()
upload.fp.write(template)
upload.fp.seek(0)
export_to.model_file = UploadedFile(pub.app_dir, None, upload)
export_to.id = '_export_to'
export_to.attach_to_history = True
export_to.backoffice_filefield_id = 'bo1'
st1.items.append(export_to)
export_to.parent = st1
assert export_to.get_backoffice_filefield_options() == [('bo1', 'bo field 1', 'bo1')]
jump = JumpWorkflowStatusItem()
jump.status = 'st2'
st1.items.append(jump)
jump.parent = st1
wf.add_status('Status2', 'st2')
wf.store()
formdef = create_formdef()
formdef.workflow_id = wf.id
formdef.fields = [fields.TextField(id='0', label='comment', type='text', varname='comment')]
formdef.store()
formdef.data_class().wipe()
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
resp.form['f0'] = 'Hello\n\nWorld.'
resp = resp.forms[0].submit('submit')
assert 'Check values then click submit.' in resp.body
resp = resp.forms[0].submit('submit')
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.body
# get the two generated files from backoffice: in backoffice fields
# (export_to.backoffice_filefield_id), and in history (export_to.attach_to_history)
for index in (0, 1):
resp = login(get_app(pub), username='admin', password='admin').get(
'/backoffice/management/test/1/')
resp = resp.click('template.odt', index=index)
assert resp.location.endswith('/template.odt')
resp = resp.follow()
assert resp.content_type == 'application/octet-stream'
with open(os.path.join(os.path.dirname(__file__), 'template-out.odt')) as f:
assert_equal_zip(StringIO.StringIO(resp.body), f)
assert formdef.data_class().count() == 1
assert formdef.data_class().select()[0].status == 'wf-st2'
def test_formdata_form_file_download(pub):
create_user(pub)
wf = Workflow(name='status')

View File

@ -2131,6 +2131,70 @@ def test_export_to_model_image(pub):
# check the original image has been left
assert zinfo.file_size == 580
def test_export_to_model_backoffice_field(pub):
wf = Workflow(name='email with attachments')
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
wf.backoffice_fields_formdef.fields = [
FileField(id='bo1', label='bo field 1', type='file', varname='backoffice_file1'),
]
st1 = wf.add_status('Status1')
wf.store()
formdef = FormDef()
formdef.name = 'foo-export-to-bofile'
formdef.fields = [
StringField(id='1', label='String', type='string', varname='string'),
]
formdef.workflow_id = wf.id
formdef.store()
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
formdata.store()
pub.substitutions.feed(formdata)
item = ExportToModel()
item.method = 'non-interactive'
template_filename = os.path.join(os.path.dirname(__file__), 'template.odt')
template = open(template_filename).read()
upload = QuixoteUpload('/foo/template.odt', content_type='application/octet-stream')
upload.fp = StringIO.StringIO()
upload.fp.write(template)
upload.fp.seek(0)
item.model_file = UploadedFile(pub.app_dir, None, upload)
item.parent = st1
item.backoffice_filefield_id = 'bo1'
item.perform(formdata)
assert 'bo1' in formdata.data
fbo1 = formdata.data['bo1']
assert fbo1.base_filename == 'template.odt'
assert fbo1.content_type == 'application/octet-stream'
zfile = zipfile.ZipFile(fbo1.get_file())
assert 'foo-export-to-bofile' in zfile.read('content.xml')
# no more 'bo1' backoffice field: do nothing
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
formdata.store()
pub.substitutions.feed(formdata)
# id is not bo1:
wf.backoffice_fields_formdef.fields = [
FileField(id='bo2', label='bo field 2', type='file'),
]
item.perform(formdata)
assert formdata.data == {}
# field is not a field file:
wf.backoffice_fields_formdef.fields = [
StringField(id='bo1', label='bo field 1', type='string'),
]
item.perform(formdata)
assert formdata.data == {}
# no field at all:
wf.backoffice_fields_formdef.fields = []
item.perform(formdata)
assert formdata.data == {}
def test_global_timeouts(pub):
FormDef.wipe()
Workflow.wipe()

View File

@ -34,7 +34,7 @@ from qommon import ezt
from qommon.form import (SingleSelectWidget, WidgetList, CheckboxWidget,
StringWidget, UploadWidget, WysiwygTextWidget, Upload,
UploadedFile, UploadValidationError, VarnameWidget,
RadiobuttonsWidget)
RadiobuttonsWidget, PicklableUpload)
from qommon.errors import PublishError
import qommon
@ -212,6 +212,7 @@ class ExportToModel(WorkflowStatusItem):
convert_to_pdf = False
push_to_portfolio = False
method = 'interactive'
backoffice_filefield_id = None
def render_as_line(self):
if self.model_file:
@ -276,13 +277,20 @@ class ExportToModel(WorkflowStatusItem):
def get_parameters(self):
parameters = ('method', 'by', 'label', 'model_file', 'attach_to_history',
'backoffice_info_text', 'varname')
'backoffice_info_text', 'varname', 'backoffice_filefield_id')
if transform_to_pdf is not None:
parameters += ('convert_to_pdf',)
if has_portfolio():
parameters += ('push_to_portfolio',)
return parameters
def get_backoffice_filefield_options(self):
options = []
for field in self.parent.parent.get_backoffice_fields():
if field.key == 'file':
options.append((field.id, field.label, field.id))
return options
def add_parameters_widgets(self, form, parameters, prefix='',
formdef=None):
methods = collections.OrderedDict(
@ -322,6 +330,13 @@ class ExportToModel(WorkflowStatusItem):
form.add(CheckboxWidget, '%sconvert_to_pdf' % prefix,
title=_('Convert generated file to PDF'),
value=self.convert_to_pdf)
if 'backoffice_filefield_id' in parameters:
options = self.get_backoffice_filefield_options()
if options:
form.add(SingleSelectWidget, '%sbackoffice_filefield_id' % prefix,
title=_('Store in a backoffice file field'),
value=self.backoffice_filefield_id,
options=[(None, '---', None)] + options)
if 'attach_to_history' in parameters:
form.add(CheckboxWidget, '%sattach_to_history' % prefix,
title=_('Attach generated file to the form history'),
@ -516,6 +531,15 @@ class ExportToModel(WorkflowStatusItem):
return
self.perform_real(formdata, formdata.evolution[-1])
def store_in_backoffice_filefield(self, formdata, filename, content_type, content):
filefield = [x for x in self.parent.parent.get_backoffice_fields()
if x.id == self.backoffice_filefield_id and x.key == 'file']
if filefield:
upload = PicklableUpload(filename, content_type)
upload.receive([content])
formdata.data[self.backoffice_filefield_id] = upload
formdata.store()
def perform_real(self, formdata, evo):
outstream = self.apply_template_to_formdata(formdata)
filename = self.model_file.base_filename
@ -532,5 +556,12 @@ class ExportToModel(WorkflowStatusItem):
content_type=content_type,
varname=self.varname))
formdata.store()
if self.backoffice_filefield_id:
outstream.seek(0)
self.store_in_backoffice_filefield(
formdata,
filename,
content_type,
outstream.read())
register_item_class(ExportToModel)