Allow cancelling of validation requests #22008

This commit is contained in:
Nicolas Demonte 2019-02-12 10:40:59 +01:00
parent f4c986b43a
commit 6a8f4e89dc
7 changed files with 112 additions and 0 deletions

View File

@ -39,6 +39,10 @@ msgstr "Un document précédemment validé est revenu en attente de validation"
msgid "A validation request has been refused"
msgstr "Une demande de validation a été refusée."
#: ../subscribers/document.py:638
msgid "A validation request previously sent to you has been deleted"
msgstr "Une demande de validation qui vous était adressée a été supprimée"
#: ../browser/comments.py:98
msgid "Accept refusal"
msgstr "Accepter la désattribution"
@ -106,6 +110,10 @@ msgstr "Annuler la validation et finalisation de la version ${version}"
msgid "Cancel validation of ${version}"
msgstr "Annuler la validation de la version ${version}"
#: ../menu.py:504
msgid "Cancel validation request"
msgstr "Annuler la demande de validation"
#: ../browser/refuse.py:33
#: ../browser/send_by_email.py:35
#: ../browser/to_process.py:25

View File

@ -57,6 +57,10 @@ msgstr "Retour à indicater"
msgid "Back to to process"
msgstr "Retour en à traiter"
#: ../profiles/default/workflows/versionnote_workflow/definition.xml
msgid "Back to validated"
msgstr "Retour à validé"
#: ../profiles/default/workflows/outgoingmail_workflow/definition.xml
msgid "Back to writing"
msgstr "Retour à la rédaction"

View File

@ -41,6 +41,10 @@ msgstr ""
msgid "A validation request has been refused"
msgstr ""
#: ../subscribers/document.py:638
msgid "A validation request previously sent to you has been deleted"
msgstr ""
#: ../browser/comments.py:98
msgid "Accept refusal"
msgstr ""
@ -108,6 +112,10 @@ msgstr ""
msgid "Cancel validation of ${version}"
msgstr ""
#: ../menu.py:504
msgid "Cancel validation request"
msgstr ""
#: ../browser/refuse.py:33
#: ../browser/send_by_email.py:35
#: ../browser/to_process.py:25

View File

@ -58,6 +58,10 @@ msgstr ""
msgid "Back to to process"
msgstr ""
#: ../profiles/default/workflows/versionnote_workflow/definition.xml
msgid "Back to validated"
msgstr ""
#: ../profiles/default/workflows/outgoingmail_workflow/definition.xml
msgid "Back to writing"
msgstr ""

View File

@ -235,6 +235,13 @@ class CustomMenu(menu.WorkflowMenu):
cssClass += ' version-action version-id-%s' % context.id
cssClass += ' version-action-%s' % action['id']
# special case to allow cancellation of validation requests:
# back_to_draft is available from state pending,
# but it must not be done directly by users.
if action['id'] == 'back_to_draft' and \
api.content.get_state(context) == 'pending':
continue
# limit cancelling actions to a version's rightful owner
# guards are bypassed for Managers, so call them at least once
action_guards = {
@ -484,6 +491,27 @@ class CustomMenu(menu.WorkflowMenu):
'submenu': None,
})
catalog = api.portal.get_tool('portal_catalog')
container_path = '/'.join(context.getPhysicalPath())
brains = catalog.searchResults({
'path': container_path,
'portal_type': 'validation',
'review_state': 'todo',
'Creator': api.user.get_current().id,
})
if IDmsDocument.providedBy(context) and brains:
results.append({
'title': _(u'Cancel validation request'),
'description': '',
'action': context.absolute_url() + '/@@cancel_validation',
'selected': False,
'icon': None,
'extra': {'id': 'plone-contentmenu-actions-cancel-validation',
'separator': None,
'class': 'no-icon overlay-form-reload link-overlay'},
'submenu': None,
})
return results
def getWorkflowActionsForType(self, context, request, portal_type):

View File

@ -85,6 +85,8 @@
<exit-transition transition_id="refuse"/>
<exit-transition transition_id="validate"/>
<exit-transition transition_id="obsolete"/>
<exit-transition transition_id="back_to_draft"/>
<exit-transition transition_id="back_to_validated"/>
<permission-map name="View" acquired="False">
<permission-role>Editor</permission-role>
<permission-role>Manager</permission-role>
@ -143,6 +145,15 @@
<guard>
<guard-role>Manager</guard-role>
<guard-role>Owner</guard-role>
<guard-role>Reviewer</guard-role>
</guard>
</transition>
<transition transition_id="back_to_validated" title="Back to validated" new_state="validated" trigger="USER" before_script="" after_script="" i18n:attributes="title">
<action url="" category="hidden" icon="" i18n:translate="">Back to draft</action>
<guard>
<guard-role>Manager</guard-role>
<guard-role>Owner</guard-role>
<guard-role>Reviewer</guard-role>
</guard>
</transition>
<transition transition_id="restore_from_trash" title="Restore" new_state="finished" trigger="USER" before_script="" after_script="" i18n:attributes="title">

View File

@ -604,6 +604,55 @@ def email_notification_of_canceled_information(context):
log = logging.getLogger('pfwbged.policy')
log.exception(e)
@grok.subscribe(IValidation, IObjectWillBeRemovedEvent)
def email_notification_of_canceled_validation(context, event):
document = None
for obj in aq_chain(context):
obj = aq_parent(obj)
if IDmsDocument.providedBy(obj):
document = obj
break
if not document:
return
absolute_url = document.absolute_url()
for enquirer in (context.enquirer or []):
member = context.portal_membership.getMemberById(enquirer)
if member:
email_from = member.getProperty('email', None)
if email_from:
break
else:
email_from = api.user.get_current().email or api.portal.get().getProperty('email_from_address') or 'admin@localhost'
responsible = context.responsible[0]
principal = api.user.get(responsible)
if not principal:
principal = api.group.get(responsible)
recipient_email = principal.getProperty('email') if principal else None
if not recipient_email:
return
subject = '%s - %s' % (context.title, document.title)
body = translate(_('A validation request previously sent to you has been deleted'), context=context.REQUEST) + \
'\n\n' + \
translate(_('Title: %s'), context=context.REQUEST) % context.title + \
'\n\n' + \
translate(_('Document: %s'), context=context.REQUEST) % document.title + \
'\n\n' + \
translate(_('Document Address: %s'), context=context.REQUEST) % document.absolute_url() + \
'\n\n\n\n-- \n' + \
translate(_('Sent by GED'))
body = body.encode('utf-8')
try:
context.MailHost.send(body, recipient_email, email_from, subject, charset='utf-8')
except Exception as e:
# do not abort transaction in case of email error
log = logging.getLogger('pfwbged.policy')
log.exception(e)
@grok.subscribe(IDmsDocument, IObjectModifiedEvent)
def log_some_history(context, event):