Skip to content

Commit 2c8d426

Browse files
authored
Merge pull request #662 from praekeltfoundation/feature-whatsapp-actions-failure-count
Increment failure count for specific error codes
2 parents 08210a1 + 6781631 commit 2c8d426

File tree

3 files changed

+98
-6
lines changed

3 files changed

+98
-6
lines changed

.github/workflows/test.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ jobs:
2424
env:
2525
HUB_DATABASE: postgres://postgres:postgres@localhost:5432/ndoh_hub
2626
steps:
27-
- uses: actions/checkout@v2
27+
- uses: actions/checkout@v4
2828
- name: Install gettext
2929
run: sudo apt-get install gettext
30-
- uses: actions/cache@v2
30+
- uses: actions/cache@v4
3131
with:
3232
path: ~/.cache/pip
3333
key: ${{ hashFiles('requirements.txt', 'requirements-dev.txt') }}-pip
34-
- uses: actions/setup-python@v2
34+
- uses: actions/setup-python@v5
3535
with:
3636
python-version: 3.9
3737
- name: Install dependancies

eventstore/tests/test_whatsapp_actions.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,19 @@ def test_whatsapp_delivery_failure_error(self):
340340
event.status = Event.FAILED
341341
event.recipient_id = "27820001001"
342342
event.timestamp = str(timezone.now() + timedelta(days=2))
343+
event.data = {
344+
"errors": [
345+
{
346+
"code": 131026,
347+
"error_data": {
348+
"details": "Message failed to send because more than "
349+
"24 hours have passed since the customer "
350+
"last replied to this number."
351+
},
352+
"title": "Re-engagement message",
353+
}
354+
]
355+
}
343356
event.save()
344357

345358
event.refresh_from_db()
@@ -436,6 +449,19 @@ def test_fallback_channel_delivery_failure_error(self):
436449
event.status = Event.FAILED
437450
event.recipient_id = "27820001001"
438451
event.timestamp = timezone.now() + timedelta(days=2)
452+
event.data = {
453+
"errors": [
454+
{
455+
"code": 131026,
456+
"error_data": {
457+
"details": "Message failed to send because more "
458+
"than 24 hours have passed since the customer "
459+
"last replied to this number."
460+
},
461+
"title": "Re-engagement message",
462+
}
463+
]
464+
}
439465
event.save()
440466

441467
DeliveryFailure.objects.create(number_of_failures=4, contact_id="27820001001")
@@ -490,6 +516,19 @@ def test_fallback_channel_delivery_failure_error_more_than_5(self):
490516
event.status = Event.FAILED
491517
event.recipient_id = "27820001001"
492518
event.timestamp = timezone.now() + timedelta(days=2)
519+
event.data = {
520+
"errors": [
521+
{
522+
"code": 131026,
523+
"error_data": {
524+
"details": "Message failed to send because "
525+
"more than 24 hours have passed since the "
526+
"customer last replied to this number."
527+
},
528+
"title": "Re-engagement message",
529+
}
530+
]
531+
}
493532
event.save()
494533

495534
DeliveryFailure.objects.create(number_of_failures=5, contact_id="27820001001")
@@ -512,6 +551,19 @@ def test_fallback_channel_delivery_failure_less_than_5(self):
512551
event.status = Event.FAILED
513552
event.recipient_id = "27820001001"
514553
event.timestamp = timezone.now() + timedelta(days=2)
554+
event.data = {
555+
"errors": [
556+
{
557+
"code": 131026,
558+
"error_data": {
559+
"details": "Message failed to send because more "
560+
"than 24 hours have passed since the customer "
561+
"last replied to this number."
562+
},
563+
"title": "Re-engagement message",
564+
}
565+
]
566+
}
515567
event.save()
516568

517569
with patch("eventstore.tasks.rapidpro") as p:
@@ -521,6 +573,39 @@ def test_fallback_channel_delivery_failure_less_than_5(self):
521573
df = DeliveryFailure.objects.get(contact_id="27820001001")
522574
self.assertEqual(df.number_of_failures, 1)
523575

576+
def test_whatsapp_delivery_failure_excluded_error_code(self):
577+
"""
578+
If it's a failed event and the error code is not in the
579+
included_error_codes list, it should not increment
580+
the failure count.
581+
"""
582+
event = Event.objects.create()
583+
event.fallback_channel = False
584+
event.status = Event.FAILED
585+
event.recipient_id = "27820001001"
586+
event.timestamp = timezone.now() + timedelta(days=2)
587+
event.data = {
588+
"errors": [
589+
{
590+
"code": 131000,
591+
"error_data": {
592+
"details": "Message failed to send due " "to an unknown error."
593+
},
594+
"title": "Something went wrong",
595+
}
596+
]
597+
}
598+
event.save()
599+
600+
DeliveryFailure.objects.create(number_of_failures=1, contact_id="27820001001")
601+
602+
with patch("eventstore.whatsapp_actions.increment_failure_count") as p:
603+
handle_event(event)
604+
p.assert_not_called()
605+
606+
df = DeliveryFailure.objects.get(contact_id="27820001001")
607+
self.assertEqual(df.number_of_failures, 1)
608+
524609
@override_settings(DISABLE_SMS_FAILURE_OPTOUTS=True)
525610
def test_fallback_channel_delivery_failure_optouts_disabled(self):
526611
"""

eventstore/whatsapp_actions.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ def handle_event(event):
9595
"""
9696
Triggers all the actions that are required for this event
9797
"""
98+
99+
included_error_codes = [
100+
131026, # Not a WhatsApp number, outdated app or unaccepted terms
101+
131050, # User has stopped receipt of marketing messages
102+
]
103+
98104
if event.status == Event.FAILED:
99105
reason = OptOut.WHATSAPP_FAILURE_REASON
100106
if event.fallback_channel is True:
@@ -103,11 +109,12 @@ def handle_event(event):
103109
if settings.DISABLE_SMS_FAILURE_OPTOUTS:
104110
return
105111

106-
increment_failure_count(event.recipient_id, event.timestamp, reason)
107-
108112
errors = event.data.get("errors", [])
109113
for error in errors:
110-
if error.get("code") == 131026:
114+
error_code = error.get("code")
115+
if error_code in included_error_codes:
116+
increment_failure_count(event.recipient_id, event.timestamp, reason)
117+
if error_code == 131026:
111118
update_whatsapp_template_send_status.delay(
112119
event.message_id, SMS_CHANNELTYPE
113120
)

0 commit comments

Comments
 (0)