1
1
import logging
2
2
3
3
from django .contrib .auth import get_user_model
4
+ from django .contrib .auth .models import AbstractUser
4
5
from django .core .management .base import BaseCommand
5
6
6
7
from generic_notifications .channels import EmailChannel
8
+ from generic_notifications .frequencies import NotificationFrequency
7
9
from generic_notifications .models import Notification
8
10
from generic_notifications .registry import registry
11
+ from generic_notifications .types import NotificationType
9
12
10
13
User = get_user_model ()
11
14
@@ -48,23 +51,22 @@ def handle(self, *args, **options):
48
51
return
49
52
50
53
# Setup
51
- email_channel = EmailChannel ()
52
54
all_notification_types = registry .get_all_types ()
53
55
54
56
# Get the specific frequency (required argument)
55
57
try :
56
- frequency = registry .get_frequency (target_frequency )
58
+ frequency_cls = registry .get_frequency (target_frequency )
57
59
except KeyError :
58
60
logger .error (f"Frequency '{ target_frequency } ' not found" )
59
61
return
60
62
61
- if frequency .is_realtime :
63
+ if frequency_cls .is_realtime :
62
64
logger .error (f"Frequency '{ target_frequency } ' is realtime, not a digest frequency" )
63
65
return
64
66
65
67
total_emails_sent = 0
66
68
67
- logger .info (f"Processing { frequency .name } digests..." )
69
+ logger .info (f"Processing { frequency_cls .name } digests..." )
68
70
69
71
# Find all users who have unsent, unread notifications for email channel
70
72
users_with_notifications = User .objects .filter (
@@ -75,31 +77,29 @@ def handle(self, *args, **options):
75
77
76
78
for user in users_with_notifications :
77
79
# Determine which notification types should use this frequency for this user
78
- relevant_types = self .get_notification_types_for_frequency (
79
- user ,
80
- frequency .key ,
81
- all_notification_types ,
82
- email_channel ,
83
- )
80
+ relevant_types = self .get_notification_types_for_frequency (user , frequency_cls , all_notification_types )
84
81
85
82
if not relevant_types :
86
83
continue
87
84
88
85
# Get unsent notifications for these types
89
86
# Exclude read notifications - don't email what user already saw on website
87
+ relevant_type_keys = [nt .key for nt in relevant_types ]
90
88
notifications = Notification .objects .filter (
91
89
recipient = user ,
92
- notification_type__in = relevant_types ,
90
+ notification_type__in = relevant_type_keys ,
93
91
email_sent_at__isnull = True ,
94
92
read__isnull = True ,
95
93
channels__icontains = f'"{ EmailChannel .key } "' ,
96
94
).order_by ("-added" )
97
95
98
96
if notifications .exists ():
99
- logger .info (f" User { user .email } : { notifications .count ()} notifications for { frequency .name } digest" )
97
+ logger .info (
98
+ f" User { user .email } : { notifications .count ()} notifications for { frequency_cls .name } digest"
99
+ )
100
100
101
101
if not dry_run :
102
- EmailChannel .send_digest_emails (user , notifications , frequency )
102
+ EmailChannel .send_digest_emails (user , notifications , frequency_cls )
103
103
104
104
total_emails_sent += 1
105
105
@@ -117,18 +117,30 @@ def handle(self, *args, **options):
117
117
else :
118
118
logger .info (f"Successfully sent { total_emails_sent } digest emails" )
119
119
120
- def get_notification_types_for_frequency (self , user , frequency_key , all_notification_types , email_channel ):
120
+ def get_notification_types_for_frequency (
121
+ self ,
122
+ user : AbstractUser ,
123
+ wanted_frequency : type [NotificationFrequency ],
124
+ all_notification_types : list [type ["NotificationType" ]],
125
+ ) -> list [type ["NotificationType" ]]:
121
126
"""
122
127
Get all notification types that should use this frequency for the given user.
123
128
This includes both explicit preferences and types that default to this frequency.
124
129
Since notifications are only created for enabled channels, we don't need to check is_enabled.
130
+
131
+ Args:
132
+ user: The user to check preferences for
133
+ wanted_frequency: The frequency to filter by (e.g. DailyFrequency, RealtimeFrequency)
134
+ all_notification_types: List of all registered notification type classes
135
+
136
+ Returns:
137
+ List of notification type classes that use this frequency for this user
125
138
"""
126
- relevant_types = set ()
139
+ relevant_types : list [ type [ "NotificationType" ]] = []
127
140
128
141
for notification_type in all_notification_types :
129
- # Use EmailChannel's get_frequency method to get the frequency for this user/type
130
- user_frequency = email_channel .get_frequency (user , notification_type .key )
131
- if user_frequency .key == frequency_key :
132
- relevant_types .add (notification_type .key )
142
+ user_frequency = notification_type .get_email_frequency (user )
143
+ if user_frequency .key == wanted_frequency .key :
144
+ relevant_types .append (notification_type )
133
145
134
- return list ( relevant_types )
146
+ return relevant_types
0 commit comments