diff --git a/app/celery/broadcast_message_tasks.py b/app/celery/broadcast_message_tasks.py index 9def33129..b512e0739 100644 --- a/app/celery/broadcast_message_tasks.py +++ b/app/celery/broadcast_message_tasks.py @@ -2,12 +2,15 @@ import uuid from flask import current_app from notifications_utils.statsd_decorators import statsd +from sqlalchemy.schema import Sequence -from app import cbc_proxy_client, notify_celery +from app import cbc_proxy_client, db, notify_celery from app.config import QueueNames -from app.models import BroadcastEventMessageType +from app.models import BroadcastEventMessageType, BroadcastProvider from app.dao.broadcast_message_dao import dao_get_broadcast_event_by_id, create_broadcast_provider_message +from app.utils import format_sequential_number + @notify_celery.task(name="send-broadcast-event") @statsd(namespace="tasks") @@ -30,6 +33,9 @@ def send_broadcast_provider_message(broadcast_event_id, provider): broadcast_event = dao_get_broadcast_event_by_id(broadcast_event_id) broadcast_provider_message = create_broadcast_provider_message(broadcast_event, provider) + formatted_message_number = None + if provider == BroadcastProvider.VODAFONE: + formatted_message_number = format_sequential_number(broadcast_provider_message.message_number) current_app.logger.info( f'invoking cbc proxy to send ' @@ -47,6 +53,7 @@ def send_broadcast_provider_message(broadcast_event_id, provider): if broadcast_event.message_type == BroadcastEventMessageType.ALERT: cbc_proxy_provider_client.create_and_send_broadcast( identifier=str(broadcast_provider_message.id), + message_number=formatted_message_number, headline="GOV.UK Notify Broadcast", description=broadcast_event.transmitted_content['body'], areas=areas, @@ -56,6 +63,7 @@ def send_broadcast_provider_message(broadcast_event_id, provider): elif broadcast_event.message_type == BroadcastEventMessageType.UPDATE: cbc_proxy_provider_client.update_and_send_broadcast( identifier=str(broadcast_provider_message.id), + message_number=formatted_message_number, headline="GOV.UK Notify Broadcast", description=broadcast_event.transmitted_content['body'], areas=areas, @@ -66,6 +74,7 @@ def send_broadcast_provider_message(broadcast_event_id, provider): elif broadcast_event.message_type == BroadcastEventMessageType.CANCEL: cbc_proxy_provider_client.cancel_broadcast( identifier=str(broadcast_provider_message.id), + message_number=formatted_message_number, headline="GOV.UK Notify Broadcast", description=broadcast_event.transmitted_content['body'], areas=areas, @@ -78,6 +87,11 @@ def send_broadcast_provider_message(broadcast_event_id, provider): @notify_celery.task(name='trigger-link-test') def trigger_link_test(provider): identifier = str(uuid.uuid4()) + formatted_seq_number = None + if provider == BroadcastProvider.VODAFONE: + sequence = Sequence('broadcast_provider_message_number_seq') + sequential_number = db.session.connection().execute(sequence) + formatted_seq_number = format_sequential_number(sequential_number) message = f"Sending a link test to CBC proxy for provider {provider} with ID {identifier}" current_app.logger.info(message) - cbc_proxy_client.get_proxy(provider).send_link_test(identifier) + cbc_proxy_client.get_proxy(provider).send_link_test(identifier, formatted_seq_number) diff --git a/app/clients/cbc_proxy.py b/app/clients/cbc_proxy.py index 81d1a34d0..7b80b107c 100644 --- a/app/clients/cbc_proxy.py +++ b/app/clients/cbc_proxy.py @@ -42,6 +42,7 @@ class CBCProxyClient: proxy_classes = { 'canary': CBCProxyCanary, BroadcastProvider.EE: CBCProxyEE, + BroadcastProvider.VODAFONE: CBCProxyVodafone, } return proxy_classes[provider](self._lambda_client) @@ -61,13 +62,13 @@ class CBCProxyClientBase: def send_link_test( self, identifier, + sequential_number, + message_format ): pass def create_and_send_broadcast( - self, - identifier, headline, description, areas, - sent, expires, + self, identifier, message_number, message_format, headline, description, areas, sent, expires, ): pass @@ -75,7 +76,7 @@ class CBCProxyClientBase: def update_and_send_broadcast( self, identifier, previous_provider_messages, headline, description, areas, - sent, expires, + sent, expires, message_number, message_format ): pass @@ -83,7 +84,7 @@ class CBCProxyClientBase: def cancel_broadcast( self, identifier, previous_provider_messages, headline, description, areas, - sent, expires, + sent, expires, message_number, message_format ): pass @@ -131,23 +132,69 @@ class CBCProxyEE(CBCProxyClientBase): def send_link_test( self, identifier, + sequential_number=None, ): + pass """ link test - open up a connection to a specific provider, and send them an xml payload with a of test. """ - payload = {'message_type': 'test', 'identifier': identifier} + payload = { + 'message_type': 'test', + 'identifier': identifier, + 'message_format': 'cbc' + } self._invoke_lambda(payload=payload) def create_and_send_broadcast( - self, - identifier, headline, description, areas, - sent, expires, + self, identifier, headline, description, areas, sent, expires, message_number=None ): + pass payload = { 'message_type': 'alert', 'identifier': identifier, + 'message_format': 'cbc', + 'headline': headline, + 'description': description, + 'areas': areas, + 'sent': sent, + 'expires': expires, + } + self._invoke_lambda(payload=payload) + + +class CBCProxyVodafone(CBCProxyClientBase): + lambda_name = 'vodafone-1-proxy' + + def send_link_test( + self, + identifier, + sequential_number, + ): + pass + """ + link test - open up a connection to a specific provider, and send them an xml payload with a of + test. + """ + payload = { + 'message_type': 'test', + 'identifier': identifier, + 'message_number': sequential_number, + 'message_format': 'ibag' + } + + self._invoke_lambda(payload=payload) + + def create_and_send_broadcast( + self, identifier, message_number, headline, description, areas, sent, expires, + ): + pass + payload = { + 'message_type': 'alert', + 'identifier': identifier, + 'message_number': message_number, + 'message_format': 'ibag', 'headline': headline, 'description': description, 'areas': areas, diff --git a/app/config.py b/app/config.py index 056e4e4a6..f9750b90c 100644 --- a/app/config.py +++ b/app/config.py @@ -378,7 +378,7 @@ class Config(object): CBC_PROXY_ENABLED = bool(CBC_PROXY_AWS_ACCESS_KEY_ID) - ENABLED_CBCS = {BroadcastProvider.EE} + ENABLED_CBCS = {BroadcastProvider.EE, BroadcastProvider.VODAFONE} ###################### diff --git a/app/dao/broadcast_message_dao.py b/app/dao/broadcast_message_dao.py index 3c05f2ab9..f7016fdcb 100644 --- a/app/dao/broadcast_message_dao.py +++ b/app/dao/broadcast_message_dao.py @@ -1,6 +1,15 @@ +import uuid + from app import db from app.dao.dao_utils import transactional -from app.models import BroadcastMessage, BroadcastEvent, BroadcastProviderMessage, BroadcastProviderMessageStatus +from app.models import ( + BroadcastMessage, + BroadcastEvent, + BroadcastProvider, + BroadcastProviderMessage, + BroadcastProviderMessageNumber, + BroadcastProviderMessageStatus +) def dao_get_broadcast_message_by_id_and_service_id(broadcast_message_id, service_id): @@ -36,10 +45,19 @@ def get_earlier_events_for_broadcast_event(broadcast_event_id): @transactional def create_broadcast_provider_message(broadcast_event, provider): + broadcast_provider_message_id = uuid.uuid4() provider_message = BroadcastProviderMessage( + id=broadcast_provider_message_id, broadcast_event=broadcast_event, provider=provider, status=BroadcastProviderMessageStatus.SENDING, ) db.session.add(provider_message) + db.session.commit() + provider_message_number = None + if provider == BroadcastProvider.VODAFONE: + provider_message_number = BroadcastProviderMessageNumber( + broadcast_provider_message_id=broadcast_provider_message_id) + db.session.add(provider_message_number) + db.session.commit() return provider_message diff --git a/app/models.py b/app/models.py index 4edf8fac5..c14408784 100644 --- a/app/models.py +++ b/app/models.py @@ -6,6 +6,7 @@ from flask import url_for, current_app from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.schema import Sequence from sqlalchemy.dialects.postgresql import ( UUID, JSON, @@ -2482,6 +2483,29 @@ class BroadcastProviderMessage(db.Model): UniqueConstraint(broadcast_event_id, provider) + message_number = association_proxy('broadcast_provider_message_number', 'broadcast_provider_message_number') + + +class BroadcastProviderMessageNumber(db.Model): + """ + To send IBAG messages via the CBC proxy to Nokia CBC appliances, Notify must generate and store a numeric + message_number alongside the message ID (GUID). + Subsequent messages (Update, Cancel) in IBAG format must reference the original message_number & message_id. + This model relates broadcast_provider_message_id to that numeric message_number. + """ + __tablename__ = 'broadcast_provider_message_number' + + sequence = Sequence('broadcast_provider_message_number_seq') + broadcast_provider_message_number = db.Column( + db.Integer, sequence, server_default=sequence.next_value(), primary_key=True + ) + broadcast_provider_message_id = db.Column( + UUID(as_uuid=True), db.ForeignKey('broadcast_provider_message.id'), nullable=False + ) + broadcast_provider_message = db.relationship( + 'BroadcastProviderMessage', backref=db.backref("broadcast_provider_message_number", uselist=False) + ) + class ServiceBroadcastProviderRestriction(db.Model): """ diff --git a/app/utils.py b/app/utils.py index 719958399..b0f0aa8e2 100644 --- a/app/utils.py +++ b/app/utils.py @@ -146,3 +146,7 @@ def get_archived_db_column_value(column): def get_dt_string_or_none(val): return val.strftime(DATETIME_FORMAT) if val else None + + +def format_sequential_number(sequential_number): + return format(sequential_number, "x").zfill(8) diff --git a/migrations/versions/0334_broadcast_message_number.py b/migrations/versions/0334_broadcast_message_number.py new file mode 100644 index 000000000..db8360f98 --- /dev/null +++ b/migrations/versions/0334_broadcast_message_number.py @@ -0,0 +1,38 @@ +""" + +Revision ID: 0334_broadcast_message_number +Revises: 0333_service_broadcast_provider +Create Date: 2020-12-04 15:06:22.544803 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +revision = '0334_broadcast_message_number' +down_revision = '0333_service_broadcast_provider' + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute("create sequence broadcast_provider_message_number_seq") + op.create_table( + 'broadcast_provider_message_number', + sa.Column( + 'broadcast_provider_message_number', + sa.Integer(), + server_default=sa.text("nextval('broadcast_provider_message_number_seq')"), + nullable=False + ), + sa.Column('broadcast_provider_message_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.ForeignKeyConstraint(['broadcast_provider_message_id'], ['broadcast_provider_message.id'], ), + sa.PrimaryKeyConstraint('broadcast_provider_message_number') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('broadcast_provider_message_number') + op.execute("drop sequence broadcast_provider_message_number_seq") + # ### end Alembic commands ### diff --git a/tests/app/celery/test_broadcast_message_tasks.py b/tests/app/celery/test_broadcast_message_tasks.py index c6afb6998..7bfb9e334 100644 --- a/tests/app/celery/test_broadcast_message_tasks.py +++ b/tests/app/celery/test_broadcast_message_tasks.py @@ -105,7 +105,13 @@ def test_send_broadcast_event_does_nothing_if_cbc_proxy_disabled(mocker, notify_ @freeze_time('2020-08-01 12:00') -def test_send_broadcast_provider_message_sends_data_correctly(mocker, sample_service): +@pytest.mark.parametrize('provider,provider_capitalised', [ + ['ee', 'EE'], + ['vodafone', 'Vodafone'], +]) +def test_send_broadcast_provider_message_sends_data_correctly( + mocker, sample_service, provider, provider_capitalised +): template = create_template(sample_service, BROADCAST_TYPE) broadcast_message = create_broadcast_message( template, @@ -121,18 +127,19 @@ def test_send_broadcast_provider_message_sends_data_correctly(mocker, sample_ser event = create_broadcast_event(broadcast_message) mock_create_broadcast = mocker.patch( - 'app.clients.cbc_proxy.CBCProxyEE.create_and_send_broadcast', + f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.create_and_send_broadcast', ) - assert event.get_provider_message('ee') is None + assert event.get_provider_message(provider) is None - send_broadcast_provider_message(provider='ee', broadcast_event_id=str(event.id)) + send_broadcast_provider_message(provider=provider, broadcast_event_id=str(event.id)) - broadcast_provider_message = event.get_provider_message('ee') + broadcast_provider_message = event.get_provider_message(provider) assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING mock_create_broadcast.assert_called_once_with( identifier=str(broadcast_provider_message.id), + message_number=mocker.ANY, headline='GOV.UK Notify Broadcast', description='this is an emergency broadcast message', areas=[{ @@ -149,7 +156,13 @@ def test_send_broadcast_provider_message_sends_data_correctly(mocker, sample_ser ) -def test_send_broadcast_provider_message_sends_update_with_references(mocker, sample_service): +@pytest.mark.parametrize('provider,provider_capitalised', [ + ['ee', 'EE'], + ['vodafone', 'Vodafone'], +]) +def test_send_broadcast_provider_message_sends_update_with_references( + mocker, sample_service, provider, provider_capitalised +): template = create_template(sample_service, BROADCAST_TYPE, content='content') broadcast_message = create_broadcast_message( @@ -164,34 +177,41 @@ def test_send_broadcast_provider_message_sends_update_with_references(mocker, sa ) alert_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.ALERT) - create_broadcast_provider_message(alert_event, 'ee') + create_broadcast_provider_message(alert_event, provider) update_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.UPDATE) mock_update_broadcast = mocker.patch( - 'app.clients.cbc_proxy.CBCProxyEE.update_and_send_broadcast', + f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.update_and_send_broadcast', ) - send_broadcast_provider_message(provider='ee', broadcast_event_id=str(update_event.id)) + send_broadcast_provider_message(provider=provider, broadcast_event_id=str(update_event.id)) - broadcast_provider_message = update_event.get_provider_message('ee') + broadcast_provider_message = update_event.get_provider_message(provider) assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING mock_update_broadcast.assert_called_once_with( identifier=str(broadcast_provider_message.id), + message_number=mocker.ANY, headline="GOV.UK Notify Broadcast", description='this is an emergency broadcast message', areas=[{ "polygon": [[50.12, 1.2], [50.13, 1.2], [50.14, 1.21]], }], previous_provider_messages=[ - alert_event.get_provider_message('ee') + alert_event.get_provider_message(provider) ], sent=update_event.sent_at_as_cap_datetime_string, expires=update_event.transmitted_finishes_at_as_cap_datetime_string, ) -def test_send_broadcast_provider_message_sends_cancel_with_references(mocker, sample_service): +@pytest.mark.parametrize('provider,provider_capitalised', [ + ['ee', 'EE'], + ['vodafone', 'Vodafone'], +]) +def test_send_broadcast_provider_message_sends_cancel_with_references( + mocker, sample_service, provider, provider_capitalised +): template = create_template(sample_service, BROADCAST_TYPE, content='content') broadcast_message = create_broadcast_message( @@ -209,28 +229,29 @@ def test_send_broadcast_provider_message_sends_cancel_with_references(mocker, sa update_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.UPDATE) cancel_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.CANCEL) - create_broadcast_provider_message(alert_event, 'ee') - create_broadcast_provider_message(update_event, 'ee') + create_broadcast_provider_message(alert_event, provider) + create_broadcast_provider_message(update_event, provider) mock_cancel_broadcast = mocker.patch( - 'app.clients.cbc_proxy.CBCProxyEE.cancel_broadcast', + f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.cancel_broadcast', ) - send_broadcast_provider_message(provider='ee', broadcast_event_id=str(cancel_event.id)) + send_broadcast_provider_message(provider=provider, broadcast_event_id=str(cancel_event.id)) - broadcast_provider_message = cancel_event.get_provider_message('ee') + broadcast_provider_message = cancel_event.get_provider_message(provider) assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING mock_cancel_broadcast.assert_called_once_with( identifier=str(broadcast_provider_message.id), + message_number=mocker.ANY, headline="GOV.UK Notify Broadcast", description='this is an emergency broadcast message', areas=[{ "polygon": [[50.12, 1.2], [50.13, 1.2], [50.14, 1.21]], }], previous_provider_messages=[ - alert_event.get_provider_message('ee'), - update_event.get_provider_message('ee') + alert_event.get_provider_message(provider), + update_event.get_provider_message(provider) ], sent=cancel_event.sent_at_as_cap_datetime_string, expires=cancel_event.transmitted_finishes_at_as_cap_datetime_string, @@ -265,6 +286,7 @@ def test_send_broadcast_provider_message_errors(mocker, sample_service): mock_create_broadcast.assert_called_once_with( identifier=ANY, + message_number=mocker.ANY, headline="GOV.UK Notify Broadcast", description='this is an emergency broadcast message', areas=[{ @@ -279,14 +301,18 @@ def test_send_broadcast_provider_message_errors(mocker, sample_service): ) +@pytest.mark.parametrize("provider,provider_capitalised", [ + ["ee", "EE"], + ["vodafone", "Vodafone"] +]) def test_trigger_link_tests_invokes_cbc_proxy_client( - mocker, + mocker, provider, provider_capitalised ): mock_send_link_test = mocker.patch( - 'app.clients.cbc_proxy.CBCProxyEE.send_link_test', + f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.send_link_test', ) - trigger_link_test('ee') + trigger_link_test(provider) assert mock_send_link_test.called # the 0th argument of the call to send_link_test @@ -296,3 +322,10 @@ def test_trigger_link_tests_invokes_cbc_proxy_client( uuid.UUID(identifier) except BaseException: pytest.fail(f"{identifier} is not a valid uuid") + + # testing sequential number: + if provider == 'vodafone': + assert type(mock_send_link_test.mock_calls[0][1][1]) is str + assert len(mock_send_link_test.mock_calls[0][1][1]) == 8 + else: + assert not mock_send_link_test.mock_calls[0][1][1] diff --git a/tests/app/clients/test_cbc_proxy.py b/tests/app/clients/test_cbc_proxy.py index ed3fad3fa..1f0f5efaa 100644 --- a/tests/app/clients/test_cbc_proxy.py +++ b/tests/app/clients/test_cbc_proxy.py @@ -24,6 +24,11 @@ def cbc_proxy_ee(cbc_proxy_client): return cbc_proxy_client.get_proxy('ee') +@pytest.fixture +def cbc_proxy_vodafone(cbc_proxy_client): + return cbc_proxy_client.get_proxy('vodafone') + + @pytest.mark.parametrize('provider_name, expected_provider_class', [ ('ee', CBCProxyEE), ('canary', CBCProxyCanary), @@ -51,7 +56,7 @@ def test_cbc_proxy_lambda_client_has_correct_keys(cbc_proxy_ee): assert secret == 'cbc-proxy-aws-secret-access-key' -def test_cbc_proxy_create_and_send_invokes_function(mocker, cbc_proxy_ee): +def test_cbc_proxy_ee_create_and_send_invokes_function(mocker, cbc_proxy_ee): identifier = 'my-identifier' headline = 'my-headline' description = 'my-description' @@ -83,6 +88,7 @@ def test_cbc_proxy_create_and_send_invokes_function(mocker, cbc_proxy_ee): cbc_proxy_ee.create_and_send_broadcast( identifier=identifier, + message_number='0000007b', headline=headline, description=description, areas=areas, @@ -100,6 +106,68 @@ def test_cbc_proxy_create_and_send_invokes_function(mocker, cbc_proxy_ee): payload = json.loads(payload_bytes) assert payload['identifier'] == identifier + assert 'message_number' not in payload + assert payload['message_format'] == 'cbc' + assert payload['message_type'] == 'alert' + assert payload['headline'] == headline + assert payload['description'] == description + assert payload['areas'] == areas + assert payload['sent'] == sent + assert payload['expires'] == expires + + +def test_cbc_proxy_vodafone_create_and_send_invokes_function(mocker, cbc_proxy_vodafone): + identifier = 'my-identifier' + headline = 'my-headline' + description = 'my-description' + + sent = 'a-passed-through-sent-value' + expires = 'a-passed-through-expires-value' + + # a single area which is a square including london + areas = [{ + 'description': 'london', + 'polygon': [ + [51.12, -1.2], + [51.12, 1.2], + [51.74, 1.2], + [51.74, -1.2], + [51.12, -1.2], + ], + }] + + ld_client_mock = mocker.patch.object( + cbc_proxy_vodafone, + '_lambda_client', + create=True, + ) + + ld_client_mock.invoke.return_value = { + 'StatusCode': 200, + } + + cbc_proxy_vodafone.create_and_send_broadcast( + identifier=identifier, + message_number='0000007b', + headline=headline, + description=description, + areas=areas, + sent=sent, expires=expires, + ) + + ld_client_mock.invoke.assert_called_once_with( + FunctionName='vodafone-1-proxy', + InvocationType='RequestResponse', + Payload=mocker.ANY, + ) + + kwargs = ld_client_mock.invoke.mock_calls[0][-1] + payload_bytes = kwargs['Payload'] + payload = json.loads(payload_bytes) + + assert payload['identifier'] == identifier + assert payload['message_number'] == '0000007b' + assert payload['message_format'] == 'ibag' assert payload['message_type'] == 'alert' assert payload['headline'] == headline assert payload['description'] == description @@ -141,6 +209,7 @@ def test_cbc_proxy_create_and_send_handles_invoke_error(mocker, cbc_proxy_ee): with pytest.raises(CBCProxyException) as e: cbc_proxy_ee.create_and_send_broadcast( identifier=identifier, + message_number='0000007b', headline=headline, description=description, areas=areas, @@ -190,6 +259,7 @@ def test_cbc_proxy_create_and_send_handles_function_error(mocker, cbc_proxy_ee): with pytest.raises(CBCProxyException) as e: cbc_proxy_ee.create_and_send_broadcast( identifier=identifier, + message_number='0000007b', headline=headline, description=description, areas=areas, @@ -237,7 +307,7 @@ def test_cbc_proxy_send_canary_invokes_function(mocker, cbc_proxy_client): assert payload['identifier'] == identifier -def test_cbc_proxy_send_link_test_invokes_function(mocker, cbc_proxy_ee): +def test_cbc_proxy_ee_send_link_test_invokes_function(mocker, cbc_proxy_ee): identifier = str(uuid.uuid4()) ld_client_mock = mocker.patch.object( @@ -252,6 +322,7 @@ def test_cbc_proxy_send_link_test_invokes_function(mocker, cbc_proxy_ee): cbc_proxy_ee.send_link_test( identifier=identifier, + sequential_number='0000007b', ) ld_client_mock.invoke.assert_called_once_with( @@ -266,3 +337,39 @@ def test_cbc_proxy_send_link_test_invokes_function(mocker, cbc_proxy_ee): assert payload['identifier'] == identifier assert payload['message_type'] == 'test' + assert 'message_number' not in payload + assert payload['message_format'] == 'cbc' + + +def test_cbc_proxy_vodafone_send_link_test_invokes_function(mocker, cbc_proxy_vodafone): + identifier = str(uuid.uuid4()) + + ld_client_mock = mocker.patch.object( + cbc_proxy_vodafone, + '_lambda_client', + create=True, + ) + + ld_client_mock.invoke.return_value = { + 'StatusCode': 200, + } + + cbc_proxy_vodafone.send_link_test( + identifier=identifier, + sequential_number='0000007b', + ) + + ld_client_mock.invoke.assert_called_once_with( + FunctionName='vodafone-1-proxy', + InvocationType='RequestResponse', + Payload=mocker.ANY, + ) + + kwargs = ld_client_mock.invoke.mock_calls[0][-1] + payload_bytes = kwargs['Payload'] + payload = json.loads(payload_bytes) + + assert payload['identifier'] == identifier + assert payload['message_type'] == 'test' + assert payload['message_number'] == '0000007b' + assert payload['message_format'] == 'ibag' diff --git a/tests/app/db.py b/tests/app/db.py index 30f00e7b6..8208fee49 100644 --- a/tests/app/db.py +++ b/tests/app/db.py @@ -63,7 +63,9 @@ from app.models import ( BroadcastMessage, BroadcastStatusType, BroadcastEvent, - BroadcastProviderMessage + BroadcastProvider, + BroadcastProviderMessage, + BroadcastProviderMessageNumber ) @@ -1058,11 +1060,20 @@ def create_broadcast_provider_message( provider, status='sending' ): + broadcast_provider_message_id = uuid.uuid4() provider_message = BroadcastProviderMessage( + id=broadcast_provider_message_id, broadcast_event=broadcast_event, provider=provider, - status=status + status=status, ) db.session.add(provider_message) db.session.commit() - return provider_message + + provider_message_number = None + if provider == BroadcastProvider.VODAFONE: + provider_message_number = BroadcastProviderMessageNumber( + broadcast_provider_message_id=broadcast_provider_message_id) + db.session.add(provider_message_number) + db.session.commit() + return provider_message, provider_message_number diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py index 70c16e08d..d8e117eab 100644 --- a/tests/app/test_utils.py +++ b/tests/app/test_utils.py @@ -4,10 +4,11 @@ import pytest from freezegun import freeze_time from app.utils import ( + format_sequential_number, get_london_midnight_in_utc, get_midnight_for_day_before, - midnight_n_days_ago, get_notification_table_to_use, + midnight_n_days_ago ) from app.models import Notification, NotificationHistory @@ -99,3 +100,7 @@ def test_get_notification_table_to_use_checks_service_data_retention(sample_serv # falls back to 7 days if not specified assert get_notification_table_to_use(sample_service, 'sms', date(2019, 1, 1), False) == NotificationHistory assert get_notification_table_to_use(sample_service, 'sms', date(2019, 1, 2), False) == Notification + + +def test_format_sequential_number(): + assert format_sequential_number(123) == '0000007b'