diff --git a/notifications_utils/recipients.py b/notifications_utils/recipients.py index 0fc4ff0b..193a1e17 100644 --- a/notifications_utils/recipients.py +++ b/notifications_utils/recipients.py @@ -89,7 +89,9 @@ def __init__( max_initial_rows_shown=10, safelist=None, template=None, - remaining_messages=sys.maxsize, + remaining_messages=sys.maxsize, # TODO FF_ANNUAL_LIMIT removal - remove this param + remaining_daily_messages=sys.maxsize, + remaining_annual_messages=sys.maxsize, international_sms=False, max_rows=50000, user_language="en", @@ -104,6 +106,8 @@ def __init__( self.template = template if isinstance(template, Template) else None self.international_sms = international_sms self.remaining_messages = remaining_messages + self.remaining_daily_messages = remaining_daily_messages + self.remaining_annual_messages = remaining_annual_messages self.rows_as_list = None self.max_rows = max_rows @@ -162,7 +166,9 @@ def has_errors(self): return bool( self.missing_column_headers or self.duplicate_recipient_column_headers - or self.more_rows_than_can_send + or self.more_rows_than_can_send # TODO FF_ANNUAL_LIMIT removal - Remove this check + or self.more_rows_than_can_send_this_year + or self.more_rows_than_can_send_today or self.too_many_rows or (not self.allowed_to_send_to) or any(self.rows_with_errors) @@ -229,10 +235,19 @@ def get_rows(self): else: yield None + # TODO FF_ANNUAL_LIMIT removal - remove this property @property def more_rows_than_can_send(self): return len(self) > self.remaining_messages + @property + def more_rows_than_can_send_today(self): + return len(self) > self.remaining_daily_messages + + @property + def more_rows_than_can_send_this_year(self): + return len(self) > self.remaining_annual_messages + @property def sms_fragment_count(self): if self.template_type != "sms": diff --git a/pyproject.toml b/pyproject.toml index b8ce18b0..f3f1b6a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "notifications-utils" -version = "53.0.2" +version = "53.0.3" description = "Shared python code for Notification - Provides logging utils etc." authors = ["Canadian Digital Service"] license = "MIT license" diff --git a/tests/conftest.py b/tests/conftest.py index 8963c50a..2a5965d9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +from contextlib import contextmanager from unittest.mock import Mock import pytest @@ -9,6 +10,16 @@ class FakeService: id = "1234" +@contextmanager +def set_config(app, name, value): + old_val = app.config.get(name) + app.config[name] = value + try: + yield + finally: + app.config[name] = old_val + + @pytest.fixture def app(): flask_app = Flask(__name__) diff --git a/tests/test_recipient_csv.py b/tests/test_recipient_csv.py index 06442f56..1f832009 100644 --- a/tests/test_recipient_csv.py +++ b/tests/test_recipient_csv.py @@ -9,6 +9,8 @@ from notifications_utils.template import SMSMessageTemplate from ordered_set import OrderedSet +from tests.conftest import set_config + def _index_rows(rows): return set(row.index for row in rows) @@ -873,17 +875,100 @@ def test_ignores_leading_whitespace_in_file(character, name): assert not recipients.has_errors -def test_error_if_too_many_email_recipients(): +def test_error_if_too_many_email_recipients_for_year(app): + with set_config(app, "FF_ANNUAL_LIMIT", True): + recipients = RecipientCSV( + "email address,\ntest@test.com,\ntest@test.com,\ntest@test.com,", + placeholders=["email_address"], + template_type="email", + remaining_annual_messages=2, + ) + assert recipients.has_errors + assert recipients.more_rows_than_can_send_this_year + + +def test_error_if_too_many_sms_recipients_for_year(app): + with set_config(app, "FF_ANNUAL_LIMIT", True): + recipients = RecipientCSV( + "phone number,\n6502532222,\n6502532222,\n6502532222,", + placeholders=["phone_number"], + template_type="sms", + template=SMSMessageTemplate( + {"content": "test message", "template_type": "sms"}, + sender=None, + prefix=None, + ), + remaining_annual_messages=2, + ) + assert recipients.has_errors + assert recipients.more_rows_than_can_send_this_year + + +def test_dont_error_if_too_many_recipients_not_specified_for_year(app): + with set_config(app, "FF_ANNUAL_LIMIT", True): + recipients = RecipientCSV( + "phone number,\n6502532222,\n6502532222,\n6502532222,", placeholders=["phone_number"], template_type="sms" + ) + assert not recipients.has_errors + assert not recipients.more_rows_than_can_send_this_year + + +def test_error_if_too_many_email_recipients_for_today(app): + with set_config(app, "FF_ANNUAL_LIMIT", True): + recipients = RecipientCSV( + "email address,\ntest@test.com,\ntest@test.com,\ntest@test.com,", + placeholders=["email_address"], + template_type="email", + remaining_daily_messages=2, + ) + assert recipients.has_errors + assert recipients.more_rows_than_can_send_today + + +def test_error_if_too_many_sms_recipients_for_today(app): + with set_config(app, "FF_ANNUAL_LIMIT", True): + recipients = RecipientCSV( + "phone number,\n6502532222,\n6502532222,\n6502532222,", + placeholders=["phone_number"], + template_type="sms", + template=SMSMessageTemplate( + {"content": "test message", "template_type": "sms"}, + sender=None, + prefix=None, + ), + remaining_daily_messages=2, + ) + assert recipients.has_errors + assert recipients.more_rows_than_can_send_today + + +def test_dont_error_if_too_many_recipients_not_specified_for_today(app): + with set_config(app, "FF_ANNUAL_LIMIT", True): + recipients = RecipientCSV( + "phone number,\n6502532222,\n6502532222,\n6502532222,", placeholders=["phone_number"], template_type="sms" + ) + assert not recipients.has_errors + assert not recipients.more_rows_than_can_send_today + + +# TODO: FF_ANNUAL_LIMIT removal - remove this test +def test_error_if_too_many_email_recipients(app): recipients = RecipientCSV( - "email address,\ntest@test.com,\ntest@test.com,\ntest@test.com,", - placeholders=["email_address"], - template_type="email", + "phone number,\n6502532222,\n6502532222,\n6502532222,", + placeholders=["phone_number"], + template_type="sms", + template=SMSMessageTemplate( + {"content": "test message", "template_type": "sms"}, + sender=None, + prefix=None, + ), remaining_messages=2, ) assert recipients.has_errors assert recipients.more_rows_than_can_send +# TODO: FF_ANNUAL_LIMIT removal - remove this test def test_error_if_too_many_sms_recipients(): recipients = RecipientCSV( "phone number,\n6502532222,\n6502532222,\n6502532222,", @@ -900,6 +985,7 @@ def test_error_if_too_many_sms_recipients(): assert recipients.more_rows_than_can_send +# TODO: FF_ANNUAL_LIMIT removal - remove this test def test_dont_error_if_too_many_recipients_not_specified(): recipients = RecipientCSV( "phone number,\n6502532222,\n6502532222,\n6502532222,", placeholders=["phone_number"], template_type="sms"