-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#2598] Refactor notifications for expiring actions/plans, messages, …
…cases - replace cron jobs with celery tasks - explicitly mark internal utility functions for case notifications
- Loading branch information
Showing
25 changed files
with
661 additions
and
478 deletions.
There are no files selected for viewing
48 changes: 0 additions & 48 deletions
48
src/open_inwoner/accounts/management/commands/actions_expire.py
This file was deleted.
Oops, something went wrong.
59 changes: 0 additions & 59 deletions
59
src/open_inwoner/accounts/management/commands/notify_about_messages.py
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from .notify_expiring_actions import notify_about_expiring_actions | ||
from .notify_expiring_plans import notify_about_expiring_plans | ||
from .notify_messages import notify_about_messages | ||
|
||
__all__ = [ | ||
"notify_about_expiring_actions", | ||
"notify_about_expiring_plans", | ||
"notify_about_messages", | ||
] |
39 changes: 39 additions & 0 deletions
39
src/open_inwoner/accounts/notifications/notify_expiring_actions.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import logging | ||
|
||
from django.db.models.query import QuerySet | ||
from django.urls import reverse | ||
|
||
from mail_editor.helpers import find_template | ||
|
||
from open_inwoner.accounts.models import Action, User | ||
from open_inwoner.utils.url import build_absolute_url | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def notify_about_expiring_actions( | ||
receiver: User, objects: QuerySet[Action], channel: str | ||
): | ||
send = _channels[channel] | ||
|
||
send(receiver=receiver, actions=objects) | ||
|
||
|
||
def _send_email(receiver: User, actions: QuerySet[Action]): | ||
actions_link = build_absolute_url(reverse("profile:action_list")) | ||
template = find_template("expiring_action") | ||
context = { | ||
"actions": actions, | ||
"actions_link": actions_link, | ||
} | ||
|
||
template.send_email([receiver.email], context) | ||
|
||
logger.info( | ||
f"The email was sent to the user {receiver} about {actions.count()} expiring actions" | ||
) | ||
|
||
|
||
_channels = { | ||
"email": _send_email, | ||
} |
42 changes: 42 additions & 0 deletions
42
src/open_inwoner/accounts/notifications/notify_expiring_plans.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import logging | ||
|
||
from django.db.models.query import QuerySet | ||
from django.urls import reverse | ||
|
||
from mail_editor.helpers import find_template | ||
|
||
from open_inwoner.accounts.models import User | ||
from open_inwoner.plans.models import Plan | ||
from open_inwoner.userfeed import hooks as userfeed_hooks | ||
from open_inwoner.utils.url import build_absolute_url | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def notify_about_expiring_plans(receiver: User, objects: QuerySet[Plan], channel: str): | ||
for plan in objects: | ||
userfeed_hooks.plan_expiring(receiver, plan) | ||
|
||
send = _channels[channel] | ||
|
||
send(receiver=receiver, plans=objects) | ||
|
||
|
||
def _send_email(receiver: User, plans: QuerySet[Plan]): | ||
plan_list_link = build_absolute_url(reverse("collaborate:plan_list")) | ||
template = find_template("expiring_plan") | ||
context = { | ||
"plans": plans, | ||
"plan_list_link": plan_list_link, | ||
} | ||
|
||
template.send_email([receiver.email], context) | ||
|
||
logger.info( | ||
f"The email was sent to the user {receiver} about {plans.count()} expiring plans" | ||
) | ||
|
||
|
||
_channels = { | ||
"email": _send_email, | ||
} |
47 changes: 47 additions & 0 deletions
47
src/open_inwoner/accounts/notifications/notify_messages.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import logging | ||
|
||
from django.db.models import Count | ||
from django.db.models.query import QuerySet | ||
from django.urls import reverse | ||
|
||
from mail_editor.helpers import find_template | ||
|
||
from open_inwoner.accounts.models import Message, User | ||
from open_inwoner.utils.url import build_absolute_url | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def notify_about_messages(receiver: User, objects: QuerySet[Message], channel: str): | ||
send = _channels[channel] | ||
|
||
send(receiver=receiver, messages=objects) | ||
|
||
|
||
def _send_email(receiver: User, messages: QuerySet[Message]): | ||
inbox_url = build_absolute_url(reverse("inbox:index")) | ||
template = find_template("new_messages") | ||
|
||
total_messages = messages.count() | ||
total_senders = messages.aggregate(total_senders=Count("sender", distinct=True))[ | ||
"total_senders" | ||
] | ||
|
||
context = { | ||
"total_messages": total_messages, | ||
"total_senders": total_senders, | ||
"inbox_link": inbox_url, | ||
} | ||
|
||
template.send_email([receiver.email], context) | ||
|
||
messages.update(sent=True) | ||
|
||
logger.info( | ||
f"The email was sent to the user {receiver} about {total_messages} new messages" | ||
) | ||
|
||
|
||
_channels = { | ||
"email": _send_email, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
from datetime import date | ||
from typing import Callable | ||
|
||
from django.db.models import Q | ||
from django.db.models.query import QuerySet | ||
from django.utils.translation import gettext as _ | ||
|
||
from celery import group | ||
from celery.result import allow_join_result | ||
|
||
from open_inwoner.accounts.models import Action, Message, User | ||
from open_inwoner.celery import app | ||
from open_inwoner.plans.models import Plan | ||
from open_inwoner.utils.constants import NotificationChannel | ||
|
||
from .notifications import ( | ||
notify_about_expiring_actions, | ||
notify_about_expiring_plans, | ||
notify_about_messages, | ||
) | ||
|
||
|
||
@app.task | ||
def send_email(receiver: User, objects: QuerySet, notify: Callable): | ||
""" | ||
Send email to `receiver` about `objects` using `notify` | ||
""" | ||
notify( | ||
receiver=receiver, | ||
objects=objects, | ||
channel=NotificationChannel.email, | ||
) | ||
|
||
|
||
@app.task(name=_("Send emails about expiring actions")) | ||
def send_emails_about_expiring_actions(): | ||
today = date.today() | ||
user_ids = Action.objects.expiring_actions_user_ids(end_date=today) | ||
receivers = User.objects.filter( | ||
is_active=True, plans_notifications=True, pk__in=user_ids | ||
).distinct() | ||
|
||
task_group = group( | ||
send_email.s( | ||
receiver=receiver, | ||
objects=Action.objects.filter(is_for=receiver, end_date=today), | ||
notify=notify_about_expiring_actions, | ||
) | ||
for receiver in receivers | ||
) | ||
|
||
promise = task_group.apply_async() | ||
with allow_join_result(): | ||
return promise.get() | ||
|
||
|
||
@app.task(name=_("Send emails about expiring plans")) | ||
def send_emails_about_expiring_plans(): | ||
today = date.today() | ||
user_ids = Plan.objects.expiring_plans_user_ids(end_date=today) | ||
receivers = User.objects.filter( | ||
is_active=True, plans_notifications=True, pk__in=user_ids | ||
).distinct() | ||
|
||
task_group = group( | ||
send_email.s( | ||
receiver=receiver, | ||
objects=Plan.objects.filter(end_date=today).filter( | ||
Q(created_by=receiver) | Q(plan_contacts=receiver) | ||
), | ||
notify=notify_about_expiring_plans, | ||
) | ||
for receiver in receivers | ||
) | ||
|
||
promise = task_group.apply_async() | ||
with allow_join_result(): | ||
return promise.get() | ||
|
||
|
||
@app.task(name=_("Send emails about messages")) | ||
def send_emails_about_messages(): | ||
receivers = User.objects.filter( | ||
received_messages__seen=False, | ||
received_messages__sent=False, | ||
is_active=True, | ||
messages_notifications=True, | ||
).distinct() | ||
|
||
email_data = [] | ||
|
||
for receiver in receivers: | ||
messages_to_update = Message.objects.filter( | ||
receiver=receiver, | ||
seen=False, | ||
sent=False, | ||
) | ||
email_data.append( | ||
{ | ||
"receiver": receiver, | ||
"messages_to_update": messages_to_update, | ||
} | ||
) | ||
|
||
task_group = group( | ||
send_email.s( | ||
receiver=data["receiver"], | ||
objects=data["messages_to_update"], | ||
notify=notify_about_messages, | ||
) | ||
for data in email_data | ||
) | ||
|
||
promise = task_group.apply_async() | ||
with allow_join_result(): | ||
return promise.get() |
Oops, something went wrong.