diff --git a/app/models.py b/app/models.py index 2432d63105..d4655eae85 100644 --- a/app/models.py +++ b/app/models.py @@ -91,6 +91,7 @@ SMS_STATUS_FORMATTED = { "failed": "Failed", "technical-failure": "Tech issue", + "technical-failure-billable": "Tech issue - billable", "temporary-failure": "Carrier issue", "permanent-failure": "No such number", "delivered": "Delivered", @@ -1605,6 +1606,7 @@ def check_code(self, cde): NOTIFICATION_PENDING = "pending" NOTIFICATION_FAILED = "failed" NOTIFICATION_TECHNICAL_FAILURE = "technical-failure" +NOTIFICATION_TECHNICAL_FAILURE_BILLABLE = "technical-failure-billable" NOTIFICATION_TEMPORARY_FAILURE = "temporary-failure" NOTIFICATION_PERMANENT_FAILURE = "permanent-failure" NOTIFICATION_PROVIDER_FAILURE = "provider-failure" @@ -1616,6 +1618,7 @@ def check_code(self, cde): NOTIFICATION_STATUS_TYPES_FAILED = [ NOTIFICATION_TECHNICAL_FAILURE, + NOTIFICATION_TECHNICAL_FAILURE_BILLABLE, NOTIFICATION_TEMPORARY_FAILURE, NOTIFICATION_PERMANENT_FAILURE, NOTIFICATION_PROVIDER_FAILURE, @@ -1631,6 +1634,7 @@ def check_code(self, cde): NOTIFICATION_DELIVERED, NOTIFICATION_FAILED, NOTIFICATION_TECHNICAL_FAILURE, + NOTIFICATION_TECHNICAL_FAILURE_BILLABLE, NOTIFICATION_TEMPORARY_FAILURE, NOTIFICATION_PERMANENT_FAILURE, NOTIFICATION_RETURNED_LETTER, @@ -1649,6 +1653,7 @@ def check_code(self, cde): NOTIFICATION_SENDING, NOTIFICATION_SENT, NOTIFICATION_DELIVERED, + NOTIFICATION_TECHNICAL_FAILURE_BILLABLE, NOTIFICATION_FAILED, NOTIFICATION_TEMPORARY_FAILURE, NOTIFICATION_PERMANENT_FAILURE, @@ -1664,6 +1669,7 @@ def check_code(self, cde): NOTIFICATION_PENDING, NOTIFICATION_FAILED, NOTIFICATION_TECHNICAL_FAILURE, + NOTIFICATION_TECHNICAL_FAILURE_BILLABLE, NOTIFICATION_TEMPORARY_FAILURE, NOTIFICATION_PERMANENT_FAILURE, NOTIFICATION_PROVIDER_FAILURE, diff --git a/migrations/versions/0505_add_tech_fail_billable.py b/migrations/versions/0505_add_tech_fail_billable.py new file mode 100644 index 0000000000..e2fa59e999 --- /dev/null +++ b/migrations/versions/0505_add_tech_fail_billable.py @@ -0,0 +1,19 @@ +""" +Revision ID: 0505_add_tech_fail_billable +Revises: 0504_fix_template_link +Create Date: 2026-02-23 00:00:00 + +""" +from alembic import op + +revision = "0505_add_tech_fail_billable" +down_revision = "0504_fix_template_link" + +NOTIFICATION_TECHNICAL_FAILURE_BILLABLE = "technical-failure-billable" + +def upgrade(): + op.execute("INSERT INTO notification_status_types (name) VALUES ('{}')".format(NOTIFICATION_TECHNICAL_FAILURE_BILLABLE)) + + +def downgrade(): + op.execute("DELETE FROM notification_status_types where name = '{}'".format(NOTIFICATION_TECHNICAL_FAILURE_BILLABLE)) diff --git a/tests/app/dao/test_ft_billing_dao.py b/tests/app/dao/test_ft_billing_dao.py index ed823971c1..16dee6ac0a 100644 --- a/tests/app/dao/test_ft_billing_dao.py +++ b/tests/app/dao/test_ft_billing_dao.py @@ -319,8 +319,8 @@ def test_fetch_billing_data_for_day_bills_correctly_for_status(notify_db_session sms_results = [x for x in results if x[2] == "sms"] email_results = [x for x in results if x[2] == "email"] letter_results = [x for x in results if x[2] == "letter"] - assert 7 == sms_results[0][7] - assert 7 == email_results[0][7] + assert 8 == sms_results[0][7] + assert 8 == email_results[0][7] assert 3 == letter_results[0][7] diff --git a/tests/app/v2/notifications/test_get_notifications.py b/tests/app/v2/notifications/test_get_notifications.py index cc51b41f50..11aa191564 100644 --- a/tests/app/v2/notifications/test_get_notifications.py +++ b/tests/app/v2/notifications/test_get_notifications.py @@ -464,7 +464,7 @@ def test_get_all_notifications_filter_by_status_invalid_status(client, sample_no assert len(json_response["errors"]) == 1 assert ( json_response["errors"][0]["message"] == "status elephant is not one of [cancelled, created, sending, " - "sent, delivered, pending, failed, technical-failure, temporary-failure, permanent-failure, provider-failure, " + "sent, delivered, pending, failed, technical-failure, technical-failure-billable, temporary-failure, permanent-failure, provider-failure, " "pending-virus-check, validation-failed, virus-scan-failed, returned-letter, " "pii-check-failed, accepted, received]" ) diff --git a/tests/app/v2/notifications/test_notification_schemas.py b/tests/app/v2/notifications/test_notification_schemas.py index 45e7beb459..ba4e95e44b 100644 --- a/tests/app/v2/notifications/test_notification_schemas.py +++ b/tests/app/v2/notifications/test_notification_schemas.py @@ -46,7 +46,7 @@ def test_get_notifications_request_invalid_statuses(invalid_statuses, valid_stat partial_error_status = ( "is not one of " "[cancelled, created, sending, sent, delivered, pending, failed, " - "technical-failure, temporary-failure, permanent-failure, provider-failure, pending-virus-check, " + "technical-failure, technical-failure-billable, temporary-failure, permanent-failure, provider-failure, pending-virus-check, " "validation-failed, virus-scan-failed, returned-letter, pii-check-failed, accepted, received]" ) @@ -103,7 +103,7 @@ def test_get_notifications_request_invalid_statuses_and_template_types(): for invalid_status in ["elephant", "giraffe"]: assert ( "status {} is not one of [cancelled, created, sending, sent, delivered, " - "pending, failed, technical-failure, temporary-failure, permanent-failure, provider-failure, " + "pending, failed, technical-failure, technical-failure-billable, temporary-failure, permanent-failure, provider-failure, " "pending-virus-check, validation-failed, virus-scan-failed, returned-letter, " "pii-check-failed, accepted, received]".format(invalid_status) in error_messages