Skip to content

Commit 2a3cb5d

Browse files
Merge pull request #2312 from IFRCGo/feature/new-notif-strategy
Use dtype, country and region to filter notifications
2 parents 721f555 + 28a5d92 commit 2a3cb5d

File tree

4 files changed

+164
-36
lines changed

4 files changed

+164
-36
lines changed

api/management/commands/index_and_notify.py

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,32 @@ def gather_countries_and_regions(self, records):
116116
countries = ["c%s" % id for id in countries]
117117
return countries, regions
118118

119+
def gather_event_countries_and_regions(self, records):
120+
# Applies to surgealerts, which have a
121+
# many-to-many relationship to countries and regions through event table
122+
countries = []
123+
for record in records:
124+
if record.event.countries is not None:
125+
countries += [country.id for country in record.event.countries.all()]
126+
countries = list(set(countries))
127+
qs = Country.objects.filter(pk__in=countries)
128+
regions = ["r%s" % country.region.id for country in qs if country.region is not None]
129+
countries = ["c%s" % id for id in countries]
130+
return countries, regions
131+
132+
def gather_eventdt_countries_and_regions(self, records):
133+
# Applies to deployments_personneldeployments, which have a
134+
# many-to-many relationship to countries and regions through event_deployed_to
135+
countries = []
136+
for record in records:
137+
if record.event_deployed_to.countries is not None:
138+
countries += [country.id for country in record.event_deployed_to.countries.all()]
139+
countries = list(set(countries))
140+
qs = Country.objects.filter(pk__in=countries)
141+
regions = ["r%s" % country.region.id for country in qs if country.region is not None]
142+
countries = ["c%s" % id for id in countries]
143+
return countries, regions
144+
119145
def fix_types_for_subs(self, rtype, stype=SubscriptionType.NEW):
120146
# Correction for the new notification types:
121147
if rtype == RecordType.EVENT or rtype == RecordType.FIELD_REPORT:
@@ -133,34 +159,68 @@ def gather_subscribers(self, records, rtype, stype):
133159
if self.is_digest_mode():
134160
subscribers = User.objects.filter(subscription__rtype=RecordType.WEEKLY_DIGEST, is_active=True).values("email")
135161
# In digest mode we do not care about other circumstances, just get every subscriber's email.
136-
emails = [subscriber["email"] for subscriber in subscribers]
162+
emails = list(set([subscriber["email"] for subscriber in subscribers]))
137163
return emails
138164
else:
139165
# Start with any users subscribed directly to this record type.
140166
subscribers = User.objects.filter(
141167
subscription__rtype=rtype_of_subscr, subscription__stype=stype, is_active=True
142168
).values("email")
169+
emails = list(set([subscriber["email"] for subscriber in subscribers]))
170+
171+
# For FOLLOWED_EVENTs we do not collect other generic (d*, country, region) subscriptions.
172+
if rtype_of_subscr != RecordType.FOLLOWED_EVENT:
173+
subscribers_no_geo_dtype = (
174+
User.objects.filter(subscription__rtype=rtype_of_subscr, subscription__stype=stype, is_active=True)
175+
.exclude(subscription__rtype__in=[RecordType.COUNTRY, RecordType.REGION, RecordType.DTYPE])
176+
.values("email")
177+
)
178+
emailset_no_geo_dtype = {subscriber["email"] for subscriber in subscribers_no_geo_dtype}
143179

144-
# For FOLLOWED_EVENTs and DEPLOYMENTs we do not collect other generic (d*, country, region) subscriptions, just one.
145-
# This part is not called.
146-
if (
147-
rtype_of_subscr != RecordType.FOLLOWED_EVENT
148-
and rtype_of_subscr != RecordType.SURGE_ALERT
149-
and rtype_of_subscr != RecordType.SURGE_DEPLOYMENT_MESSAGES
150-
):
151-
dtypes = list(set(["d%s" % record.dtype.id for record in records if record.dtype is not None]))
180+
subscribers_geo = (
181+
User.objects.filter(subscription__rtype=rtype_of_subscr, subscription__stype=stype, is_active=True)
182+
.filter(subscription__rtype__in=[RecordType.COUNTRY, RecordType.REGION])
183+
.values("email")
184+
)
185+
emailset_geo = {subscriber["email"] for subscriber in subscribers_geo}
186+
187+
subscribers_dtype = (
188+
User.objects.filter(subscription__rtype=rtype_of_subscr, subscription__stype=stype, is_active=True)
189+
.filter(subscription__rtype=RecordType.DTYPE)
190+
.values("email")
191+
)
192+
emailset_dtype = {subscriber["email"] for subscriber in subscribers_dtype}
152193

153194
if rtype_of_subscr == RecordType.NEW_OPERATIONS:
154195
countries, regions = self.gather_country_and_region(records)
196+
elif rtype_of_subscr == RecordType.SURGE_ALERT:
197+
countries, regions = self.gather_event_countries_and_regions(records)
198+
elif rtype_of_subscr == RecordType.SURGE_DEPLOYMENT_MESSAGES:
199+
countries, regions = self.gather_eventdt_countries_and_regions(records)
155200
else:
156201
countries, regions = self.gather_countries_and_regions(records)
157202

158-
lookups = dtypes + countries + regions
159-
if len(lookups):
160-
subscribers = (
161-
subscribers | User.objects.filter(subscription__lookup_id__in=lookups, is_active=True).values("email")
162-
).distinct()
163-
emails = list(set([subscriber["email"] for subscriber in subscribers]))
203+
if rtype_of_subscr == RecordType.SURGE_ALERT:
204+
dtypes = list(set(["d%s" % record.event.dtype.id for record in records if record.event.dtype is not None]))
205+
elif rtype_of_subscr == RecordType.SURGE_DEPLOYMENT_MESSAGES:
206+
dtypes = list(set(["d%s" % rec.event_deployed_to.dtype.id for rec in records if rec.event_deployed_to.dtype]))
207+
else:
208+
dtypes = list(set(["d%s" % record.dtype.id for record in records if record.dtype is not None]))
209+
210+
geo = countries + regions
211+
if len(geo):
212+
emailset_geo = emailset_geo & {
213+
subscriber["email"]
214+
for subscriber in User.objects.filter(subscription__lookup_id__in=geo, is_active=True).values("email")
215+
}
216+
217+
if len(dtypes):
218+
emailset_dtype = emailset_dtype & {
219+
subscriber["email"]
220+
for subscriber in User.objects.filter(subscription__lookup_id__in=dtypes, is_active=True).values("email")
221+
}
222+
223+
emails = list(emailset_no_geo_dtype | emailset_geo | emailset_dtype)
164224
return emails
165225

166226
def get_template(self, rtype=99):

api/test_scrapers.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ def test_new_record_subscription(self):
5757
def test_country_subscription(self):
5858
# Subscription to a country
5959
user = get_user()
60+
Subscription.objects.create(
61+
user=user,
62+
rtype=RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
63+
stype=SubscriptionType.NEW,
64+
)
6065
c = Country.objects.get(name="c2")
6166
Subscription.objects.create(
6267
user=user,
@@ -66,7 +71,7 @@ def test_country_subscription(self):
6671
notify = Notify()
6772
emails = notify.gather_subscribers(
6873
FieldReport.objects.filter(created_at__gte=notify.diff_5_minutes()),
69-
RecordType.FIELD_REPORT,
74+
RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
7075
SubscriptionType.NEW,
7176
)
7277
self.assertEqual(len(emails), 1)
@@ -75,6 +80,11 @@ def test_country_subscription(self):
7580
def test_region_subscription(self):
7681
# Subscription to a region
7782
user = get_user()
83+
Subscription.objects.create(
84+
user=user,
85+
rtype=RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
86+
stype=SubscriptionType.NEW,
87+
)
7888
r = Region.objects.get(name=1)
7989
Subscription.objects.create(
8090
user=user,
@@ -84,7 +94,7 @@ def test_region_subscription(self):
8494
notify = Notify()
8595
emails = notify.gather_subscribers(
8696
FieldReport.objects.filter(created_at__gte=notify.diff_5_minutes()),
87-
RecordType.FIELD_REPORT,
97+
RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
8898
SubscriptionType.NEW,
8999
)
90100
self.assertEqual(len(emails), 1)
@@ -93,6 +103,11 @@ def test_region_subscription(self):
93103
def test_dtype_subscription(self):
94104
# Subscription to a disaster type
95105
user = get_user()
106+
Subscription.objects.create(
107+
user=user,
108+
rtype=RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
109+
stype=SubscriptionType.NEW,
110+
)
96111
d = DisasterType.objects.get(name="d1")
97112
Subscription.objects.create(
98113
user=user,
@@ -102,7 +117,7 @@ def test_dtype_subscription(self):
102117
notify = Notify()
103118
emails = notify.gather_subscribers(
104119
FieldReport.objects.filter(created_at__gte=notify.diff_5_minutes()),
105-
RecordType.FIELD_REPORT,
120+
RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
106121
SubscriptionType.NEW,
107122
)
108123
self.assertEqual(len(emails), 1)
@@ -112,6 +127,18 @@ def test_multiple_subscription(self):
112127
user1 = get_user()
113128
user2 = get_user()
114129

130+
Subscription.objects.create(
131+
user=user1,
132+
rtype=RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
133+
stype=SubscriptionType.NEW,
134+
)
135+
136+
Subscription.objects.create(
137+
user=user2,
138+
rtype=RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
139+
stype=SubscriptionType.NEW,
140+
)
141+
115142
d = DisasterType.objects.get(name="d1")
116143
r = Region.objects.get(name=1)
117144

@@ -139,7 +166,7 @@ def test_multiple_subscription(self):
139166
notify = Notify()
140167
emails = notify.gather_subscribers(
141168
FieldReport.objects.filter(created_at__gte=notify.diff_5_minutes()),
142-
RecordType.FIELD_REPORT,
169+
RecordType.NEW_EMERGENCIES, # FIELD_REPORT,
143170
SubscriptionType.NEW,
144171
)
145172
self.assertEqual(len(emails), 2)
@@ -161,6 +188,11 @@ def setUp(self):
161188

162189
def test_region_subscription(self):
163190
user = get_user()
191+
Subscription.objects.create(
192+
user=user,
193+
rtype=RecordType.NEW_OPERATIONS,
194+
stype=SubscriptionType.NEW,
195+
)
164196
r = Region.objects.get(name="1")
165197
Subscription.objects.create(user=user, region=r, lookup_id="r%s" % r.id)
166198
notify = Notify()
@@ -174,6 +206,11 @@ def test_region_subscription(self):
174206

175207
def test_region_and_country_subscription(self):
176208
user = get_user()
209+
Subscription.objects.create(
210+
user=user,
211+
rtype=RecordType.NEW_OPERATIONS,
212+
stype=SubscriptionType.NEW,
213+
)
177214
r = Region.objects.get(name="1")
178215
c = Country.objects.get(name="2")
179216
Subscription.objects.create(user=user, region=r, lookup_id="r%s" % r.id)

0 commit comments

Comments
 (0)