Source code for ploneintranet.todo.handlers
# -*- coding: utf-8 -*-
from .behaviors import IMustRead
from .behaviors import ITodo
from .interfaces import ITodoUtility
from .interfaces import MUST_READ
from plone import api
from ploneintranet.notifications.interfaces import IMessageFactory
from Products.DCWorkflow.interfaces import IAfterTransitionEvent
from zope.component import getUtility
from zope.lifecycleevent.interfaces import IObjectAddedEvent
import logging
log = logging.getLogger(__name__)
[docs]def mark(obj, evt):
"""The event handler that marks this object as mustread.
"""
todos = getUtility(ITodoUtility)
obj_uuid = api.content.get_uuid(obj)
behavior = IMustRead(obj)
# Verify if it has been booked in the utility
present = todos.query(content_uids=[obj_uuid], verbs=[MUST_READ])
if not behavior.mustread and len(present) > 0:
# Ok, so it was present but somehow we don't want it to be "must read"
# anymore, so we complete the actions (ugh)
todos.complete_action(content_uid=obj_uuid, verb=MUST_READ)
if behavior.mustread and len(present) == 0:
todos.add_action(content_uid=obj_uuid, verb=MUST_READ)
[docs]def on_delete(obj, evt):
"""Complete actions for objects marked as must read that have been deleted
"""
todos = getUtility(ITodoUtility)
obj_uuid = api.content.get_uuid(obj)
todos.complete_action(content_uid=obj_uuid, verb=MUST_READ)
[docs]def todo_set_role(obj, evt):
""" update role for assignees
"""
todo = ITodo(obj)
assignee = todo.assignee
if not assignee and IObjectAddedEvent.providedBy(evt):
assignee = obj.REQUEST.get("assignee")
if assignee:
obj.manage_addLocalRoles(assignee, ["Assignee"])
[docs]def _is_change_reported(event, field):
for change in event.descriptions:
if field in change.attributes:
return True
return False
[docs]def trigger_user_notifications(obj, recipient, mail_template=""):
""" Send out notifications to all channels the user wants
"""
# XXX check the user prefs
# If user wants inline notes
# send notification
message = IMessageFactory(obj)()
tool = api.portal.get_tool("ploneintranet_notifications")
try:
tool.append_to_user_queue(recipient, message.clone())
except ValueError as ve:
log.error("Error adding a notification for task: %s" % str(ve))
# if the user wants email
# send an email
try:
R = obj.REQUEST
R.set("recipient", recipient)
view = api.content.get_view(mail_template, obj, R)
view.send_email()
except Exception as e:
log.error("Error sending notification mail for task: %s" % str(e))
[docs]def task_update_handler(obj, event):
"""
* when a task is created the assignee gets a notification
* when a task is edited assignee and initiator get notifications
* when a task is state changed assignee and initiator get notifications
always - the one who did the changes does not get a notification
"""
# After creation, another event handler may update the workflow state of a
# task which will trigger additional messages.
# The request is marked to show that the item has just been created.
if getattr(obj.REQUEST, "newly_created", False):
return
# Don't send notifications for planned tasks
wft = api.portal.get_tool("portal_workflow")
state_id = wft.getInfoFor(obj, "review_state")
if state_id == "planned":
return
creator = obj.initiator
assignee = obj.assignee
current_user = api.user.get_current()
current_user_id = current_user.getId()
recipients = set()
if creator and creator != current_user.getId():
recipients.add(creator)
# Determine the nature of the change
change = "modification"
if IAfterTransitionEvent.providedBy(event):
# In a case, a task is transitioned from 'planned' to 'open' when
# the case reaches the milestone of the task.
# The assignee may only be first aware of the task when it is set to
# 'open', since they may not have permission to view it earlier. So we
# send a notification that they have been assigned.
old_state = event.old_state.getId()
if state_id == "open":
change = "assignment"
elif old_state == "open" and state_id == "done":
change = "modification"
else:
return
elif IObjectAddedEvent.providedBy(event):
# When triggered by IObjectAddedEvent the obj.assignee hasn't been set
# yet, but we can get it from the request
assignee = obj.REQUEST.form.get("assignee", None)
if assignee:
obj.REQUEST.newly_created = True
change = "assignment"
elif _is_change_reported(event, "assignee"):
# The task has been changed and one of the changes was the assignee.
change = "assignment"
# Special Case:
# An assignee has been set and it is not the current user, so we
# need to inform the assignee.
if assignee and assignee != current_user_id:
recipients.add(assignee)
# Trigger the notifications (inline, emails, etc)
if change == "assignment":
mail_template = "todo-assigned-notification-email"
elif change == "modification":
mail_template = "todo-changed-notification-email"
else:
# undefined situation. Should not happen. Abort.
log.warning("Change type unknown. Not sending any notification.")
for recipient in recipients:
trigger_user_notifications(obj, recipient, mail_template=mail_template)