Skip to content

Commit

Permalink
Update notifications data for belga specfic templates [SDBELGA-781] (#…
Browse files Browse the repository at this point in the history
…1957)

* Update notifications data for belga specfic templates '

* reformat code via black

* fix mypy

* handle none case

* update utils functions based on comments

* refactore datetime func and add tests

* add TypedDict definition

* fix mypy

* address comment

* udpate docstring and minor changes

* minor change

* remove unused imports
  • Loading branch information
devketanpro authored Apr 10, 2024
1 parent 11441cc commit 9a7ce5d
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 1 deletion.
32 changes: 32 additions & 0 deletions server/planning/assignments/assignments.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
from planning.common import format_address, get_assginment_name
from apps.content import push_content_notification
from .assignments_history import ASSIGNMENT_HISTORY_ACTIONS
from planning.utils import get_event_formatted_dates, get_formatted_contacts

logger = logging.getLogger(__name__)
planning_type = deepcopy(superdesk.Resource.rel("planning", type="string"))
Expand Down Expand Up @@ -453,6 +454,10 @@ def send_assignment_notification(self, updates, original=None, force=False):
# Add the ICS object to the assignment
assignment["planning"]["ics_data"] = ical.to_ical()

# get formatted contacts and event date time for email templates
formatted_contacts = get_formatted_contacts(event_item) if event_item else []
fomatted_event_date = get_event_formatted_dates(event_item) if event_item else ""

# The assignment is to an external contact or a user
if assigned_to.get("contact") or assigned_to.get("user"):
# If it is a reassignment
Expand All @@ -473,6 +478,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
event=event_item,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
# notify the desk
if assigned_to.get("desk"):
Expand All @@ -489,6 +497,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
event=event_item,
omit_user=True,
is_link=True,
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)

else:
Expand Down Expand Up @@ -525,6 +536,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
omit_user=True,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
else:
# it is being reassigned by someone else so notify both the new assignee and the old
Expand All @@ -547,6 +561,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
omit_user=True,
is_link=True,
contact_id=original.get("assigned_to").get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
# notify the assignee
assigned_from = original.get("assigned_to")
Expand All @@ -570,6 +587,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
omit_user=True,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
else: # A new assignment
# Notify the user the assignment has been made to unless assigning to your self
Expand All @@ -592,6 +612,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
omit_user=True,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
else: # Assigned/Reassigned to a desk, notify all desk members
# if it was assigned to a desk before, test if there has been a change of desk
Expand Down Expand Up @@ -620,6 +643,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
omit_user=True,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
else:
PlanningNotifications().notify_assignment(
Expand All @@ -637,6 +663,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
event=event_item,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)
else:
assign_type = "reassigned" if original.get("assigned_to") else "assigned"
Expand All @@ -656,6 +685,9 @@ def send_assignment_notification(self, updates, original=None, force=False):
omit_user=True,
is_link=True,
contact_id=assigned_to.get("contact"),
contacts=formatted_contacts,
location=event.get("LOCATION", ""),
event_date_time=fomatted_event_date,
)

def send_assignment_cancellation_notification(
Expand Down
33 changes: 33 additions & 0 deletions server/planning/tests/utils_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from planning.tests import TestCase
from datetime import datetime
from planning.utils import get_event_formatted_dates


class TestGetEventFormattedDates(TestCase):
def test_multi_day_event(self):
start = datetime(2024, 5, 28, 5, 00, 00)
end = datetime(2024, 5, 29, 6, 00, 00)
event = {"dates": {"start": start, "end": end}}
result = get_event_formatted_dates(event)
self.assertEqual(result, "05:00 28/05/2024 - 06:00 29/05/2024")

def test_all_day_event(self):
start = datetime(2024, 4, 27, 22, 00, 00)
end = datetime(2024, 4, 28, 21, 59, 59)
event = {"dates": {"start": start, "end": end}}
result = get_event_formatted_dates(event)
self.assertEqual(result, "ALL DAY 27/04/2024")

def test_same_start_end(self):
start = datetime(2024, 4, 1, 14, 45)
end = datetime(2024, 4, 1, 14, 45)
event = {"dates": {"start": start, "end": end}}
result = get_event_formatted_dates(event)
self.assertEqual(result, "14:45 01/04/2024")

def test_dates_same_and_different_time(self):
start = datetime(2024, 5, 28, 6, 00, 00)
end = datetime(2024, 5, 28, 5, 00, 00)
event = {"dates": {"start": start, "end": end}}
result = get_event_formatted_dates(event)
self.assertEqual(result, "06:00 - 05:00, 28/05/2024")
89 changes: 88 additions & 1 deletion server/planning/utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,97 @@
from typing import Union
from typing import Union, List, Dict, Any, TypedDict
from bson.objectid import ObjectId
from bson.errors import InvalidId
from datetime import datetime
from flask_babel import format_time, format_datetime, lazy_gettext
from eve.utils import str_to_date
import arrow
from flask import current_app as app


class FormattedContact(TypedDict):
name: str
organisation: str
email: List[str]
phone: List[str]
mobile: List[str]
website: str


MULTI_DAY_SECONDS = 24 * 60 * 60 # Number of seconds for an multi-day event
ALL_DAY_SECONDS = MULTI_DAY_SECONDS - 1 # Number of seconds for an all-day event


def try_cast_object_id(value: str) -> Union[ObjectId, str]:
try:
return ObjectId(value)
except InvalidId:
return value


def get_formatted_contacts(event: Dict[str, Any]) -> List[FormattedContact]:
contacts = event.get("event_contact_info", [])
formatted_contacts: List[FormattedContact] = []

for contact in contacts:
if contact.get("public", False):
formatted_contact: FormattedContact = {
"name": " ".join(
[
c
for c in [
contact.get("first_name", ""),
contact.get("last_name", ""),
]
if c
]
),
"organisation": contact.get("organisation", ""),
"email": contact.get("contact_email", []),
"phone": [c.get("number", "") for c in contact.get("contact_phone", []) if c.get("public")],
"mobile": [c.get("number", "") for c in contact.get("mobile", []) if c.get("public")],
"website": contact.get("website", ""),
}
formatted_contacts.append(formatted_contact)

return formatted_contacts


def parse_date(datetime: Union[str, datetime]) -> datetime:
"""Return datetime instance for datetime."""
if isinstance(datetime, str):
try:
return str_to_date(datetime)
except ValueError:
return arrow.get(datetime).datetime
return datetime


def time_short(datetime: datetime):
if datetime:
return format_time(parse_date(datetime), app.config.get("TIME_FORMAT_SHORT", "HH:mm"))


def date_short(datetime: datetime):
if datetime:
return format_datetime(parse_date(datetime), app.config.get("DATE_FORMAT_SHORT", "dd/MM/yyyy"))


def get_event_formatted_dates(event: Dict[str, Any]) -> str:
start = event.get("dates", {}).get("start")
end = event.get("dates", {}).get("end")

duration_seconds = int((end - start).total_seconds())

if duration_seconds == ALL_DAY_SECONDS:
# All day event
return "{} {}".format(lazy_gettext("ALL DAY"), date_short(start))

if duration_seconds >= MULTI_DAY_SECONDS:
# Multi day event
return "{} {} - {} {}".format(time_short(start), date_short(start), time_short(end), date_short(end))

if start == end:
# start and end are the same
return "{} {}".format(time_short(start), date_short(start))

return "{} - {}, {}".format(time_short(start), time_short(end), date_short(start))

0 comments on commit 9a7ce5d

Please sign in to comment.