mirror of
https://github.com/GSA/notifications-api.git
synced 2025-12-21 07:51:13 -05:00
Rewrite failed statuses
There are no more notifications whose statuses are "failed", as the "failed" status has now been replaced with statuses that are more specific about the nature of the failure. However, we still want to be able to filter by failing notifications. (ie "/v2/notifications?status=failed"). Created a `.substitute_status()` method which takes a status string or list of status strings and, if it finds 'failure', replaces it with the other failing status types. This way, calling for nottifications with "?status=failed" is internally treated as "status = ['technical-failure', 'temporary-failure', 'permanent-failure']"
This commit is contained in:
@@ -466,6 +466,12 @@ NOTIFICATION_TECHNICAL_FAILURE = 'technical-failure'
|
||||
NOTIFICATION_TEMPORARY_FAILURE = 'temporary-failure'
|
||||
NOTIFICATION_PERMANENT_FAILURE = 'permanent-failure'
|
||||
|
||||
NOTIFICATION_STATUS_TYPES_FAILED = [
|
||||
NOTIFICATION_TECHNICAL_FAILURE,
|
||||
NOTIFICATION_TEMPORARY_FAILURE,
|
||||
NOTIFICATION_PERMANENT_FAILURE,
|
||||
]
|
||||
|
||||
NOTIFICATION_STATUS_TYPES_COMPLETED = [
|
||||
NOTIFICATION_DELIVERED,
|
||||
NOTIFICATION_FAILED,
|
||||
@@ -480,7 +486,7 @@ NOTIFICATION_STATUS_TYPES_BILLABLE = [
|
||||
NOTIFICATION_FAILED,
|
||||
NOTIFICATION_TECHNICAL_FAILURE,
|
||||
NOTIFICATION_TEMPORARY_FAILURE,
|
||||
NOTIFICATION_PERMANENT_FAILURE
|
||||
NOTIFICATION_PERMANENT_FAILURE,
|
||||
]
|
||||
|
||||
NOTIFICATION_STATUS_TYPES = [
|
||||
@@ -491,7 +497,7 @@ NOTIFICATION_STATUS_TYPES = [
|
||||
NOTIFICATION_FAILED,
|
||||
NOTIFICATION_TECHNICAL_FAILURE,
|
||||
NOTIFICATION_TEMPORARY_FAILURE,
|
||||
NOTIFICATION_PERMANENT_FAILURE
|
||||
NOTIFICATION_PERMANENT_FAILURE,
|
||||
]
|
||||
NOTIFICATION_STATUS_TYPES_ENUM = db.Enum(*NOTIFICATION_STATUS_TYPES, name='notify_status_type')
|
||||
|
||||
@@ -558,6 +564,46 @@ class Notification(db.Model):
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def substitute_status(status_or_statuses):
|
||||
"""
|
||||
static function that takes a status or list of statuses and substitutes our new failure types if it finds
|
||||
the deprecated one
|
||||
|
||||
> IN
|
||||
'failed'
|
||||
|
||||
< OUT
|
||||
['technical-failure', 'temporary-failure', 'permanent-failure']
|
||||
|
||||
-
|
||||
|
||||
> IN
|
||||
['failed', 'created']
|
||||
|
||||
< OUT
|
||||
['technical-failure', 'temporary-failure', 'permanent-failure', 'created']
|
||||
|
||||
|
||||
:param status_or_statuses: a single status or list of statuses
|
||||
:return: a single status or list with the current failure statuses substituted for 'failure'
|
||||
"""
|
||||
|
||||
def _substitute_status_str(_status):
|
||||
return NOTIFICATION_STATUS_TYPES_FAILED if _status == NOTIFICATION_FAILED else _status
|
||||
|
||||
def _substitute_status_seq(_statuses):
|
||||
if NOTIFICATION_FAILED in _statuses:
|
||||
_statuses = list(set(
|
||||
NOTIFICATION_STATUS_TYPES_FAILED + [_s for _s in _statuses if _s != NOTIFICATION_FAILED]
|
||||
))
|
||||
return _statuses
|
||||
|
||||
if isinstance(status_or_statuses, str):
|
||||
return _substitute_status_str(status_or_statuses)
|
||||
|
||||
return _substitute_status_seq(status_or_statuses)
|
||||
|
||||
def serialize(self):
|
||||
|
||||
template_dict = {
|
||||
|
||||
@@ -2,7 +2,15 @@ import pytest
|
||||
|
||||
from app.models import (
|
||||
ServiceWhitelist,
|
||||
MOBILE_TYPE, EMAIL_TYPE)
|
||||
Notification,
|
||||
MOBILE_TYPE,
|
||||
EMAIL_TYPE,
|
||||
NOTIFICATION_CREATED,
|
||||
NOTIFICATION_PENDING,
|
||||
NOTIFICATION_FAILED,
|
||||
NOTIFICATION_TECHNICAL_FAILURE,
|
||||
NOTIFICATION_STATUS_TYPES_FAILED
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('mobile_number', [
|
||||
@@ -32,3 +40,28 @@ def test_should_build_service_whitelist_from_email_address(email_address):
|
||||
def test_should_not_build_service_whitelist_from_invalid_contact(recipient_type, contact):
|
||||
with pytest.raises(ValueError):
|
||||
ServiceWhitelist.from_string('service_id', recipient_type, contact)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('initial_statuses, expected_statuses', [
|
||||
# passing in single statuses as strings
|
||||
(NOTIFICATION_FAILED, NOTIFICATION_STATUS_TYPES_FAILED),
|
||||
(NOTIFICATION_CREATED, NOTIFICATION_CREATED),
|
||||
(NOTIFICATION_TECHNICAL_FAILURE, NOTIFICATION_TECHNICAL_FAILURE),
|
||||
# passing in lists containing single statuses
|
||||
([NOTIFICATION_FAILED], NOTIFICATION_STATUS_TYPES_FAILED),
|
||||
([NOTIFICATION_CREATED], [NOTIFICATION_CREATED]),
|
||||
([NOTIFICATION_TECHNICAL_FAILURE], [NOTIFICATION_TECHNICAL_FAILURE]),
|
||||
# passing in lists containing multiple statuses
|
||||
([NOTIFICATION_FAILED, NOTIFICATION_CREATED], NOTIFICATION_STATUS_TYPES_FAILED + [NOTIFICATION_CREATED]),
|
||||
([NOTIFICATION_CREATED, NOTIFICATION_PENDING], [NOTIFICATION_CREATED, NOTIFICATION_PENDING]),
|
||||
([NOTIFICATION_CREATED, NOTIFICATION_TECHNICAL_FAILURE], [NOTIFICATION_CREATED, NOTIFICATION_TECHNICAL_FAILURE]),
|
||||
# checking we don't end up with duplicates
|
||||
(
|
||||
[NOTIFICATION_FAILED, NOTIFICATION_CREATED, NOTIFICATION_TECHNICAL_FAILURE],
|
||||
NOTIFICATION_STATUS_TYPES_FAILED + [NOTIFICATION_CREATED]
|
||||
),
|
||||
])
|
||||
def test_status_conversion_handles_failed_statuses(initial_statuses, expected_statuses):
|
||||
converted_statuses = Notification.substitute_status(initial_statuses)
|
||||
assert len(converted_statuses) == len(expected_statuses)
|
||||
assert set(converted_statuses) == set(expected_statuses)
|
||||
|
||||
Reference in New Issue
Block a user