Commit 9e6db4ee authored by Jérome Perrin's avatar Jérome Perrin

deferred_style: alarm to automate reports production

See merge request nexedi/erp5!1357
parents 2e60dde5 3b600793
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_generateReportDocumentList</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>configuration_form_id</string> </key>
<value> <string>Alarm_viewGenerateReportDocumentConfiguration</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_report_alarm</string> </value>
</item>
<item>
<key> <string>periodicity_day_frequency</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1609459200.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Report Alarm</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# type: (str, list[dict], str, str, str, str, str, DateTime.DateTime, Any)
portal = context.getPortalObject()
for attachment in attachment_list:
document = portal.portal_contributions.newContent(
data=attachment['content'],
filename=attachment['name'],
title=title,
reference=reference,
version=version,
publication_section=publication_section,
language=language,
effective_date=effective_date,
)
document.share()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>subject, attachment_list, title, reference, version=\'\', publication_section=\'\', language=None, effective_date=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_contributeAndShareReportDocument</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# coding: utf-8
"""
Alarm must define a script that returns a list of dictionnaries with the following keys:
- form_id str: id of an ERP5 Form or ERP5 Report. Required.
- context erp5.portal_type.Base: the context to render the report. Required.
- parameters dict: request parameters to render the report. Required.
Must be serializable for CMFActivity
- skin_name str: skin selection to use for this report ('ODS' | 'ODT'). Required.
- format Optional[str]: convert the document to this format. Note that in scenarios like
storing the result report in document module, it's better to keep the default format (None)
and convert on demand the stored document.
- language str: Localizer language to use. Required.
- callback_script_id str: id of a script to call at the end of report generation. Required
The script will be called on the context of the alarm, with the following arguments:
- subject str: the name of the report
- attachment_list dict: files produced by the report, dicts with following keys:
- name str: file name
- mime str: file mime type
- content bytes: file body
- **callback_script_kwargs
- callback_script_kwargs dict: of arguemnts that will be passed to callback script id.
- setup Callable[[dict], dict]: a function to call at setup before rendering the report.
This function receive this dict as argument and must return a dict of the same type.
"""
priority = 3
portal = context.getPortalObject()
report_configuration_script_id = context.getProperty('report_configuration_script_id')
assert report_configuration_script_id
for report_data in getattr(context, report_configuration_script_id)():
if report_data.get('setup'):
report_data = report_data['setup'](report_data)
notify_report_complete_kwargs = {
'alarm_relative_url': context.getRelativeUrl(),
'callback_script_id': report_data['callback_script_id'],
'callback_script_kwargs': report_data.get('callback_script_kwargs', {}),
}
report_context = report_data.get('context', context)
report_active_context = report_context.activate(
activity='SQLQueue',
node=portal.portal_preferences.getPreferredDeferredReportActivityFamily(),
tag=tag,
priority=priority,
)
if getattr(getattr(report_context, report_data['form_id']), 'pt', 'form_list') == 'report_view':
# erp5 report
report_active_context.Base_computeReportSection(
form=report_data['form_id'],
request_other=report_data['parameters'],
user_name=None,
tag=tag,
skin_name=report_data['skin_name'],
format=report_data.get('format', None),
priority=priority,
localizer_language=report_data['language'],
notify_report_complete_script_id='ERP5Site_finalizeAlarmReportDocumentGeneration',
notify_report_complete_kwargs=notify_report_complete_kwargs,
)
else:
# simple view
params = {}
if 'format' in report_data:
params['format'] = report_data['format']
report_active_context.Base_renderSimpleView(
localizer_language=report_data['language'],
skin_name=report_data['skin_name'],
request_form=report_data['parameters'],
deferred_style_dialog_method=report_data['form_id'],
user_name=None,
params=params,
notify_report_complete_script_id='ERP5Site_finalizeAlarmReportDocumentGeneration',
notify_report_complete_kwargs=notify_report_complete_kwargs,
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit=False, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_generateReportDocumentList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Base_edit</string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>my_report_configuration_script_id</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_viewGenerateReportDocumentConfiguration</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Alarm_viewGenerateReportDocumenConfiguration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>ERP5 Form</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Configuration</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>display_width</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_report_configuration_script_id</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>ID of a script returning the report configuration. See Alarm_generateReportDocumentList for the exact API</string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Report Configuration Script ID</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# pylint: disable=redefined-builtin
portal = context.getPortalObject()
if notify_report_complete_kwargs is None:
notify_report_complete_kwargs = {}
form = context.restrictedTraverse(form)
request = container.REQUEST
......@@ -58,5 +60,7 @@ activity_context.activate(
form_path=form.getPhysicalPath(),
user_name=user_name,
format=format,
report_section_count=len(report_section_list)
)
report_section_count=len(report_section_list),
notify_report_complete_script_id=notify_report_complete_script_id,
notify_report_complete_kwargs=notify_report_complete_kwargs,
)
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>form, request_other, user_name, tag, skin_name, format, priority, localizer_language, **kw</string> </value>
<value> <string>form, request_other, user_name, tag, skin_name, format, priority, localizer_language, notify_report_complete_script_id=\'ERP5Site_notifyReportComplete\', notify_report_complete_kwargs=None, **kw</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
# Render a "normal" form or an OOo template in an activity and send it by email
from Products.ERP5Type.Message import translateString
portal = context.getPortalObject()
if notify_report_complete_kwargs is None:
notify_report_complete_kwargs = {}
request = portal.REQUEST
report_format = request_form.get('format', '')
if portal.portal_preferences.getPreferredDeferredReportStoredAsDocument():
......@@ -31,9 +33,11 @@ with portal.Localizer.translationContext(localizer_language):
'content': '%s' % report_data,
'name': attachment_name},)
portal.ERP5Site_notifyReportComplete(
getattr(portal, notify_report_complete_script_id)(
user_name=user_name,
subject=str(translateString(attachment_name.rsplit('.', 1)[0])),
message='',
attachment_list=attachment_list,
format=report_format)
format=report_format,
**notify_report_complete_kwargs
)
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>localizer_language, skin_name, request_form, deferred_style_dialog_method, user_name, params</string> </value>
<value> <string>localizer_language, skin_name, request_form, deferred_style_dialog_method, user_name, params, notify_report_complete_script_id=\'ERP5Site_notifyReportComplete\', notify_report_complete_kwargs=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -51,9 +51,11 @@ with portal.Localizer.translationContext(localizer_language):
'content': '%s' % report_data,
'name': attachment_name},)
portal.ERP5Site_notifyReportComplete(
getattr(portal, notify_report_complete_script_id)(
user_name=user_name,
subject=title,
message='',
attachment_list=attachment_list,
format=format)
format=format,
**notify_report_complete_kwargs
)
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>active_process_url, skin_name, localizer_language, title, request_other, form_path, user_name, format, report_section_count</string> </value>
<value> <string>active_process_url, skin_name, localizer_language, title, request_other, form_path, user_name, format, report_section_count, notify_report_complete_script_id, notify_report_complete_kwargs</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
# pylint:disable=redefined-builtin
portal = context.getPortalObject()
assert alarm_relative_url
alarm = portal.restrictedTraverse(alarm_relative_url)
assert callback_script_id
callback = getattr(alarm, callback_script_id)
callback(
subject=subject,
attachment_list=attachment_list,
**callback_script_kwargs
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>user_name, subject, message, attachment_list, format, alarm_relative_url, callback_script_id, callback_script_kwargs</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_finalizeAlarmReportDocumentGeneration</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
2021-02-04 Jérome
* Alarm to automate report creation
2009-09-12 Jérome
* Allow rendering of any form / printout in deferred mode
\ No newline at end of file
portal_alarms/template_report_alarm
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment