Skip to content

Commit

Permalink
Adding notifications to dedicated channel cases (#4916)
Browse files Browse the repository at this point in the history
Co-authored-by: Will Sheldon <[email protected]>
  • Loading branch information
whitdog47 and wssheldon authored Jul 8, 2024
1 parent f93e43b commit cb60cd4
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 8 deletions.
12 changes: 12 additions & 0 deletions src/dispatch/case/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
from dispatch.storage.enums import StorageAction
from dispatch.ticket import flows as ticket_flows

from .messaging import (
send_case_created_notifications,
send_case_update_notifications,
)

from .models import Case, CaseStatus
from .service import get

Expand Down Expand Up @@ -216,6 +221,9 @@ def case_new_create_flow(
db_session.add(case)
db_session.commit()

if case.dedicated_channel:
send_case_created_notifications(case, db_session)

if case.case_priority.page_assignee:
if not service_id:
if case.case_type.oncall_service:
Expand Down Expand Up @@ -386,6 +394,10 @@ def case_update_flow(
if case_details_changed(case, previous_case):
conversation_flows.set_conversation_topic(case, db_session)

# we send the case update notifications
if case.dedicated_channel:
send_case_update_notifications(case, previous_case, db_session)


def case_delete_flow(case: Case, db_session: SessionLocal):
"""Runs the case delete flow."""
Expand Down
217 changes: 213 additions & 4 deletions src/dispatch/case/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,36 @@
"""
import logging

from dispatch.database.core import SessionLocal
from dispatch.case.models import Case
from sqlalchemy.orm import Session

from dispatch.database.core import resolve_attr
from dispatch.case.models import Case, CaseRead
from dispatch.messaging.strings import (
CASE_CLOSE_REMINDER,
CASE_TRIAGE_REMINDER,
CASE_NOTIFICATION,
CASE_NOTIFICATION_COMMON,
CASE_NAME_WITH_ENGAGEMENT,
CASE_NAME_WITH_ENGAGEMENT_NO_SELF_JOIN,
CASE_NAME,
CASE_ASSIGNEE,
CASE_STATUS_CHANGE,
CASE_TYPE_CHANGE,
CASE_SEVERITY_CHANGE,
CASE_PRIORITY_CHANGE,
MessageType,
)
from dispatch.config import DISPATCH_UI_URL
from dispatch.plugin import service as plugin_service
from dispatch.event import service as event_service
from dispatch.notification import service as notification_service

from .enums import CaseStatus

log = logging.getLogger(__name__)


def send_case_close_reminder(case: Case, db_session: SessionLocal) -> None:
def send_case_close_reminder(case: Case, db_session: Session) -> None:
"""
Sends a direct message to the assignee reminding them to close the case if possible.
"""
Expand Down Expand Up @@ -57,7 +72,7 @@ def send_case_close_reminder(case: Case, db_session: SessionLocal) -> None:
log.debug(f"Case close reminder sent to {case.assignee.individual.email}.")


def send_case_triage_reminder(case: Case, db_session: SessionLocal) -> None:
def send_case_triage_reminder(case: Case, db_session: Session) -> None:
"""
Sends a direct message to the assignee reminding them to triage the case if possible.
"""
Expand Down Expand Up @@ -93,3 +108,197 @@ def send_case_triage_reminder(case: Case, db_session: SessionLocal) -> None:
)

log.debug(f"Case triage reminder sent to {case.assignee.individual.email}.")


def send_case_created_notifications(case: Case, db_session: Session):
"""Sends case created notifications."""
notification_template = CASE_NOTIFICATION.copy()

if case.status != CaseStatus.closed:
if case.project.allow_self_join:
notification_template.insert(0, CASE_NAME_WITH_ENGAGEMENT)
else:
notification_template.insert(0, CASE_NAME_WITH_ENGAGEMENT_NO_SELF_JOIN)
else:
notification_template.insert(0, CASE_NAME)

case_description = (
case.description
if len(case.description) <= 500
else f"{case.description[:500]}..."
)

notification_kwargs = {
"name": case.name,
"title": case.title,
"description": case_description,
"visibility": case.visibility,
"status": case.status,
"type": case.case_type.name,
"type_description": case.case_type.description,
"severity": case.case_severity.name,
"severity_description": case.case_severity.description,
"priority": case.case_priority.name,
"priority_description": case.case_priority.description,
"reporter_fullname": case.reporter.individual.name,
"reporter_team": case.reporter.team,
"reporter_weblink": case.reporter.individual.weblink,
"assignee_fullname": case.assignee.individual.name,
"assignee_team": case.assignee.team,
"assignee_weblink": case.assignee.individual.weblink,
"document_weblink": resolve_attr(case, "case_document.weblink"),
"storage_weblink": resolve_attr(case, "storage.weblink"),
"ticket_weblink": resolve_attr(case, "ticket.weblink"),
"contact_fullname": case.assignee.individual.name,
"contact_weblink": case.assignee.individual.weblink,
"case_id": case.id,
"organization_slug": case.project.organization.slug,
}

notification_params = {
"text": "Case Notification",
"type": MessageType.case_notification,
"template": notification_template,
"kwargs": notification_kwargs,
}

notification_service.filter_and_send(
db_session=db_session,
project_id=case.project.id,
class_instance=case,
notification_params=notification_params,
)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Case notifications sent",
case_id=case.id,
)

log.debug("Case created notifications sent.")


def send_case_update_notifications(
case: Case, previous_case: CaseRead, db_session: Session
):
"""Sends notifications about case changes."""
notification_text = "Case Notification"
notification_type = MessageType.case_notification
notification_template = CASE_NOTIFICATION_COMMON.copy()

change = False
if previous_case.status != case.status:
change = True
notification_template.append(CASE_STATUS_CHANGE)
if previous_case.case_type.name != case.case_type.name:
notification_template.append(CASE_TYPE_CHANGE)

if previous_case.case_severity.name != case.case_severity.name:
notification_template.append(CASE_SEVERITY_CHANGE)

if previous_case.case_priority.name != case.case_priority.name:
notification_template.append(CASE_PRIORITY_CHANGE)
else:
if case.status != CaseStatus.closed:
if previous_case.case_type.name != case.case_type.name:
change = True
notification_template.append(CASE_TYPE_CHANGE)

if previous_case.case_severity.name != case.case_severity.name:
change = True
notification_template.append(CASE_SEVERITY_CHANGE)

if previous_case.case_priority.name != case.case_priority.name:
change = True
notification_template.append(CASE_PRIORITY_CHANGE)

if not change:
# we don't need to send notifications
log.debug("Case updated notifications not sent. No changes were made.")
return

notification_template.append(CASE_ASSIGNEE)

# we send an update to the case conversation if the case is active or stable
if case.status != CaseStatus.closed:
case_conversation_notification_template = notification_template.copy()
case_conversation_notification_template.insert(0, CASE_NAME)

convo_plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
if convo_plugin:
convo_plugin.instance.send(
case.conversation.channel_id,
notification_text,
case_conversation_notification_template,
notification_type,
assignee_fullname=case.assignee.individual.name,
assignee_team=case.assignee.team,
assignee_weblink=case.assignee.individual.weblink,
case_priority_new=case.case_priority.name,
case_priority_old=previous_case.case_priority.name,
case_severity_new=case.case_severity.name,
case_severity_old=previous_case.case_severity.name,
case_status_new=case.status,
case_status_old=previous_case.status,
case_type_new=case.case_type.name,
case_type_old=previous_case.case_type.name,
name=case.name,
ticket_weblink=case.ticket.weblink,
title=case.title,
escalated_to_incident=case.incidents[0] if case.incidents else None,
)
else:
log.debug(
"Case updated notification not sent to case conversation. No conversation plugin enabled." # noqa
)

# we send a notification to the notification conversations and emails
fyi_notification_template = notification_template.copy()
if case.status != CaseStatus.closed:
if case.project.allow_self_join:
fyi_notification_template.insert(0, CASE_NAME_WITH_ENGAGEMENT)
else:
fyi_notification_template.insert(0, CASE_NAME_WITH_ENGAGEMENT_NO_SELF_JOIN)
else:
fyi_notification_template.insert(0, CASE_NAME)

notification_kwargs = {
"assignee_fullname": case.assignee.individual.name,
"assignee_team": case.assignee.team,
"assignee_weblink": case.assignee.individual.weblink,
"contact_fullname": case.assignee.individual.name,
"contact_weblink": case.assignee.individual.weblink,
"case_id": case.id,
"case_priority_new": case.case_priority.name,
"case_priority_old": previous_case.case_priority.name,
"case_severity_new": case.case_severity.name,
"case_severity_old": previous_case.case_severity.name,
"case_status_new": case.status,
"case_status_old": previous_case.status,
"case_type_new": case.case_type.name,
"case_type_old": previous_case.case_type.name,
"name": case.name,
"organization_slug": case.project.organization.slug,
"ticket_weblink": resolve_attr(case, "ticket.weblink"),
"title": case.title,
"escalated_to_incident": case.incidents[0] if case.incidents else None,
}

notification_params = {
"text": notification_text,
"type": notification_type,
"template": fyi_notification_template,
"kwargs": notification_kwargs,
}

notification_service.filter_and_send(
db_session=db_session,
project_id=case.project.id,
class_instance=case,
notification_params=notification_params,
)

log.debug("Case updated notifications sent.")
1 change: 1 addition & 0 deletions src/dispatch/messaging/email/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def get_template(message_type: MessageType, project_id: int):
MessageType.incident_completed_form_notification: ("notification.mjml", None),
MessageType.incident_executive_report: ("executive_report.mjml", None),
MessageType.incident_notification: ("notification.mjml", None),
MessageType.case_notification: ("notification.mjml", None),
MessageType.incident_participant_welcome: ("notification.mjml", None),
MessageType.incident_tactical_report: ("tactical_report.mjml", None),
MessageType.incident_task_reminder: (
Expand Down
Loading

0 comments on commit cb60cd4

Please sign in to comment.