Merge branch 'master' into check-data-retention-before-purging-notifications

This commit is contained in:
Rebecca Law
2018-07-31 11:40:58 +01:00
30 changed files with 373 additions and 1340 deletions

View File

@@ -4,18 +4,12 @@ import json
import pytest
from app.billing.rest import _transform_billing_for_month_sms
from app.dao.monthly_billing_dao import (
create_or_update_monthly_billing,
get_monthly_billing_by_notification_type,
)
from app.models import SMS_TYPE, EMAIL_TYPE, LETTER_TYPE, FactBilling
from app.models import FactBilling
from app.dao.date_util import get_current_financial_year_start_year, get_month_start_and_end_date_in_utc
from app.dao.annual_billing_dao import dao_get_free_sms_fragment_limit_for_year
from tests.app.db import (
create_notification,
create_rate,
create_monthly_billing_entry,
create_annual_billing,
create_template,
create_service,
@@ -36,253 +30,6 @@ def _assert_dict_equals(actual, expected_dict):
assert actual == expected_dict
def test_get_yearly_billing_summary_returns_correct_breakdown(client, sample_template):
create_rate(start_date=IN_MAY_2016 - timedelta(days=1), value=0.12, notification_type=SMS_TYPE)
create_notification(
template=sample_template, created_at=IN_MAY_2016,
billable_units=1, rate_multiplier=2, status='delivered'
)
create_notification(
template=sample_template, created_at=IN_JUN_2016,
billable_units=2, rate_multiplier=3, status='delivered'
)
letter_template = create_template(service=sample_template.service, template_type=LETTER_TYPE)
create_notification(template=letter_template, created_at=IN_MAY_2016, status='delivered', billable_units=1)
create_notification(template=letter_template, created_at=IN_JUN_2016, status='delivered', billable_units=1)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=IN_MAY_2016)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=IN_JUN_2016)
response = client.get(
'/service/{}/billing/yearly-usage-summary?year=2016'.format(sample_template.service.id),
headers=[create_authorization_header()]
)
assert response.status_code == 200
resp_json = json.loads(response.get_data(as_text=True))
assert len(resp_json) == 3
_assert_dict_equals(resp_json[0], {
'notification_type': EMAIL_TYPE,
'billing_units': 0,
'rate': 0,
'letter_total': 0
})
_assert_dict_equals(resp_json[1], {
'notification_type': LETTER_TYPE,
'billing_units': 2,
'rate': 0,
'letter_total': 0.66
})
_assert_dict_equals(resp_json[2], {
'notification_type': SMS_TYPE,
'billing_units': 8,
'rate': 0.12,
'letter_total': 0
})
def test_get_yearly_billing_usage_breakdown_returns_400_if_missing_year(client, sample_service):
response = client.get(
'/service/{}/billing/yearly-usage-summary'.format(sample_service.id),
headers=[create_authorization_header()]
)
assert response.status_code == 400
assert json.loads(response.get_data(as_text=True)) == {
'message': 'No valid year provided', 'result': 'error'
}
def test_get_yearly_usage_by_month_returns_400_if_missing_year(client, sample_service):
response = client.get(
'/service/{}/billing/monthly-usage'.format(sample_service.id),
headers=[create_authorization_header()]
)
assert response.status_code == 400
assert json.loads(response.get_data(as_text=True)) == {
'message': 'No valid year provided', 'result': 'error'
}
def test_get_yearly_usage_by_month_returns_empty_list_if_no_usage(client, sample_template):
create_rate(start_date=IN_MAY_2016 - timedelta(days=1), value=0.12, notification_type=SMS_TYPE)
response = client.get(
'/service/{}/billing/monthly-usage?year=2016'.format(sample_template.service.id),
headers=[create_authorization_header()]
)
assert response.status_code == 200
results = json.loads(response.get_data(as_text=True))
assert results == []
def test_get_yearly_usage_by_month_returns_correctly(client, sample_template):
create_rate(start_date=IN_MAY_2016 - timedelta(days=1), value=0.12, notification_type=SMS_TYPE)
create_notification(
template=sample_template, created_at=IN_MAY_2016,
billable_units=1, rate_multiplier=2, status='delivered'
)
create_notification(
template=sample_template, created_at=IN_JUN_2016,
billable_units=2, rate_multiplier=3, status='delivered'
)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=IN_MAY_2016)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=IN_JUN_2016)
response = client.get(
'/service/{}/billing/monthly-usage?year=2016'.format(sample_template.service.id),
headers=[create_authorization_header()]
)
assert response.status_code == 200
resp_json = json.loads(response.get_data(as_text=True))
_assert_dict_equals(resp_json[0], {
'billing_units': 0,
'month': 'May',
'notification_type': LETTER_TYPE,
'rate': 0
})
_assert_dict_equals(resp_json[1], {
'billing_units': 2,
'month': 'May',
'notification_type': SMS_TYPE,
'rate': 0.12
})
_assert_dict_equals(resp_json[2], {
'billing_units': 0,
'month': 'June',
'notification_type': LETTER_TYPE,
'rate': 0
})
_assert_dict_equals(resp_json[3], {
'billing_units': 6,
'month': 'June',
'notification_type': SMS_TYPE,
'rate': 0.12
})
def test_transform_billing_for_month_returns_empty_if_no_monthly_totals(sample_service):
create_monthly_billing_entry(
service=sample_service,
monthly_totals=[],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
transformed_billing_data = _transform_billing_for_month_sms(get_monthly_billing_by_notification_type(
sample_service.id, APR_2016_MONTH_START, SMS_TYPE
))
_assert_dict_equals(transformed_billing_data, {
'notification_type': SMS_TYPE,
'billing_units': 0,
'month': 'April',
'rate': 0,
})
def test_transform_billing_for_month_formats_monthly_totals_correctly(sample_service):
create_monthly_billing_entry(
service=sample_service,
monthly_totals=[{
"billing_units": 12,
"rate": 0.0158,
"rate_multiplier": 5,
"total_cost": 2.1804,
"international": False
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
transformed_billing_data = _transform_billing_for_month_sms(get_monthly_billing_by_notification_type(
sample_service.id, APR_2016_MONTH_START, SMS_TYPE
))
_assert_dict_equals(transformed_billing_data, {
'notification_type': SMS_TYPE,
'billing_units': 60,
'month': 'April',
'rate': 0.0158,
})
def test_transform_billing_sums_billable_units(sample_service):
create_monthly_billing_entry(
service=sample_service,
monthly_totals=[{
'billing_units': 1321,
'international': False,
'month': 'May',
'notification_type': SMS_TYPE,
'rate': 0.12,
'rate_multiplier': 1
}, {
'billing_units': 1,
'international': False,
'month': 'May',
'notification_type': SMS_TYPE,
'rate': 0.12,
'rate_multiplier': 1
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
transformed_billing_data = _transform_billing_for_month_sms(get_monthly_billing_by_notification_type(
sample_service.id, APR_2016_MONTH_START, SMS_TYPE
))
_assert_dict_equals(transformed_billing_data, {
'notification_type': SMS_TYPE,
'billing_units': 1322,
'month': 'April',
'rate': 0.12,
})
def test_transform_billing_calculates_with_different_rate_multipliers(sample_service):
create_monthly_billing_entry(
service=sample_service,
monthly_totals=[{
'billing_units': 1321,
'international': False,
'month': 'May',
'notification_type': SMS_TYPE,
'rate': 0.12,
'rate_multiplier': 1
}, {
'billing_units': 1,
'international': False,
'month': 'May',
'notification_type': SMS_TYPE,
'rate': 0.12,
'rate_multiplier': 3
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
transformed_billing_data = _transform_billing_for_month_sms(get_monthly_billing_by_notification_type(
sample_service.id, APR_2016_MONTH_START, SMS_TYPE
))
_assert_dict_equals(transformed_billing_data, {
'notification_type': SMS_TYPE,
'billing_units': 1324,
'month': 'April',
'rate': 0.12,
})
def test_create_update_free_sms_fragment_limit_invalid_schema(client, sample_service):
response = client.post('service/{}/billing/free-sms-fragment-limit'.format(sample_service.id),
@@ -480,21 +227,6 @@ def test_get_yearly_usage_by_monthly_from_ft_billing(client, notify_db_session):
assert len(ft_email) == 0
def test_compare_ft_billing_to_monthly_billing(client, notify_db_session):
service = set_up_yearly_data()
monthly_billing_response = client.get('/service/{}/billing/monthly-usage?year=2016'.format(service.id),
headers=[create_authorization_header()])
ft_billing_response = client.get('service/{}/billing/ft-monthly-usage?year=2016'.format(service.id),
headers=[('Content-Type', 'application/json'), create_authorization_header()])
monthly_billing_json_resp = json.loads(monthly_billing_response.get_data(as_text=True))
ft_billing_json_resp = json.loads(ft_billing_response.get_data(as_text=True))
assert monthly_billing_json_resp == ft_billing_json_resp
def set_up_yearly_data():
service = create_service()
sms_template = create_template(service=service, template_type="sms")
@@ -527,55 +259,9 @@ def set_up_yearly_data():
notification_type='letter',
rate=0.33)
start_date, end_date = get_month_start_and_end_date_in_utc(datetime(2016, int(mon), 1))
create_monthly_billing_entry(service=service, start_date=start_date,
end_date=end_date,
notification_type='sms',
monthly_totals=[
{"rate": 0.0162, "international": False,
"rate_multiplier": 1, "billing_units": int(d),
"total_cost": 0.0162 * int(d)},
{"rate": 0.0162, "international": False,
"rate_multiplier": 2, "billing_units": int(d),
"total_cost": 0.0162 * int(d)}]
)
create_monthly_billing_entry(service=service, start_date=start_date,
end_date=end_date,
notification_type='email',
monthly_totals=[
{"rate": 0, "international": False,
"rate_multiplier": 1, "billing_units": int(d),
"total_cost": 0}]
)
create_monthly_billing_entry(service=service, start_date=start_date,
end_date=end_date,
notification_type='letter',
monthly_totals=[
{"rate": 0.33, "international": False,
"rate_multiplier": 1, "billing_units": int(d),
"total_cost": 0.33 * int(d)}]
)
return service
def test_get_yearly_billing_usage_summary_from_ft_billing_compare_to_monthly_billing(
client, notify_db_session
):
service = set_up_yearly_data()
monthly_billing_response = client.get('/service/{}/billing/yearly-usage-summary?year=2016'.format(service.id),
headers=[create_authorization_header()])
ft_billing_response = client.get('service/{}/billing/ft-yearly-usage-summary?year=2016'.format(service.id),
headers=[('Content-Type', 'application/json'), create_authorization_header()])
monthly_billing_json_resp = json.loads(monthly_billing_response.get_data(as_text=True))
ft_billing_json_resp = json.loads(ft_billing_response.get_data(as_text=True))
assert len(monthly_billing_json_resp) == 3
assert len(ft_billing_json_resp) == 3
for i in range(0, 3):
assert sorted(monthly_billing_json_resp[i]) == sorted(ft_billing_json_resp[i])
def test_get_yearly_billing_usage_summary_from_ft_billing_returns_400_if_missing_year(client, sample_service):
response = client.get(
'/service/{}/billing/ft-yearly-usage-summary'.format(sample_service.id),

View File

@@ -308,7 +308,7 @@ def test_check_billable_units_when_billable_units_does_not_match_page_count(
mocker,
notification_update
):
mock_logger = mocker.patch('app.celery.tasks.current_app.logger.error')
mock_logger = mocker.patch('app.celery.tasks.current_app.logger.exception')
notification = create_notification(sample_letter_template, reference='REFERENCE_ABC', billable_units=3)

View File

@@ -287,7 +287,7 @@ def test_create_nightly_billing_consolidate_from_3_days_delta(
mocker.patch('app.dao.fact_billing_dao.get_rate', side_effect=mocker_get_rate)
# create records from 11th to 15th
for i in range(0, 5):
for i in range(0, 11):
sample_notification(
notify_db,
notify_db_session,
@@ -302,7 +302,7 @@ def test_create_nightly_billing_consolidate_from_3_days_delta(
)
notification = Notification.query.order_by(Notification.created_at).all()
assert datetime.date(notification[0].created_at) == date(2018, 1, 11)
assert datetime.date(notification[0].created_at) == date(2018, 1, 5)
records = FactBilling.query.all()
assert len(records) == 0
@@ -310,8 +310,8 @@ def test_create_nightly_billing_consolidate_from_3_days_delta(
create_nightly_billing()
records = FactBilling.query.order_by(FactBilling.bst_date).all()
assert len(records) == 3
assert records[0].bst_date == date(2018, 1, 12)
assert len(records) == 10
assert records[0].bst_date == date(2018, 1, 5)
assert records[-1].bst_date == date(2018, 1, 14)

View File

@@ -27,7 +27,6 @@ from app.celery.scheduled_tasks import (
run_scheduled_jobs,
run_letter_jobs,
trigger_letter_pdfs_for_day,
populate_monthly_billing,
s3,
send_daily_performance_platform_stats,
send_scheduled_notifications,
@@ -48,7 +47,6 @@ from app.dao.provider_details_dao import (
)
from app.exceptions import NotificationTechnicalFailureException
from app.models import (
MonthlyBilling,
NotificationHistory,
Service,
StatsTemplateUsageByMonth,
@@ -60,11 +58,10 @@ from app.models import (
SMS_TYPE
)
from app.utils import get_london_midnight_in_utc
from app.celery.service_callback_tasks import create_encrypted_callback_data
from app.celery.service_callback_tasks import create_delivery_status_callback_data
from app.v2.errors import JobIncompleteError
from tests.app.db import (
create_notification, create_service, create_template, create_job, create_rate,
create_service_callback_api
create_notification, create_service, create_template, create_job, create_service_callback_api
)
from tests.app.conftest import (
@@ -125,8 +122,6 @@ def test_should_have_decorated_tasks_functions():
'remove_transformed_dvla_files'
assert delete_dvla_response_files_older_than_seven_days.__wrapped__.__name__ == \
'delete_dvla_response_files_older_than_seven_days'
assert populate_monthly_billing.__wrapped__.__name__ == \
'populate_monthly_billing'
@pytest.fixture(scope='function')
@@ -224,7 +219,7 @@ def test_timeout_notifications_sends_status_update_to_service(client, sample_tem
seconds=current_app.config.get('SENDING_NOTIFICATIONS_TIMEOUT_PERIOD') + 10))
timeout_notifications()
encrypted_data = create_encrypted_callback_data(notification, callback_api)
encrypted_data = create_delivery_status_callback_data(notification, callback_api)
mocked.assert_called_once_with([str(notification.id), encrypted_data], queue=QueueNames.CALLBACKS)
@@ -751,85 +746,6 @@ def test_tuesday_alert_if_letter_notifications_still_sending_reports_friday_lett
)
@freeze_time("2017-07-12 02:00:00")
def test_populate_monthly_billing_populates_correctly(sample_template):
yesterday = datetime(2017, 7, 11, 13, 30)
jul_month_start = datetime(2017, 6, 30, 23)
jul_month_end = datetime(2017, 7, 31, 22, 59, 59, 99999)
create_rate(datetime(2016, 1, 1), 0.0123, 'sms')
create_notification(template=sample_template, status='delivered', created_at=yesterday)
create_notification(template=sample_template, status='delivered', created_at=yesterday - timedelta(days=1))
create_notification(template=sample_template, status='delivered', created_at=yesterday + timedelta(days=1))
# not included in billing
create_notification(template=sample_template, status='delivered', created_at=yesterday - timedelta(days=30))
populate_monthly_billing()
monthly_billing = MonthlyBilling.query.order_by(MonthlyBilling.notification_type).all()
assert len(monthly_billing) == 3
assert monthly_billing[0].service_id == sample_template.service_id
assert monthly_billing[0].start_date == jul_month_start
assert monthly_billing[0].end_date == jul_month_end
assert monthly_billing[0].notification_type == 'email'
assert monthly_billing[0].monthly_totals == []
assert monthly_billing[1].service_id == sample_template.service_id
assert monthly_billing[1].start_date == jul_month_start
assert monthly_billing[1].end_date == jul_month_end
assert monthly_billing[1].notification_type == 'sms'
assert sorted(monthly_billing[1].monthly_totals[0]) == sorted(
{
'international': False,
'rate_multiplier': 1,
'billing_units': 3,
'rate': 0.0123,
'total_cost': 0.0369
}
)
assert monthly_billing[2].service_id == sample_template.service_id
assert monthly_billing[2].start_date == jul_month_start
assert monthly_billing[2].end_date == jul_month_end
assert monthly_billing[2].notification_type == 'letter'
assert monthly_billing[2].monthly_totals == []
@freeze_time("2016-04-01 23:00:00")
def test_populate_monthly_billing_updates_correct_month_in_bst(sample_template):
yesterday = datetime.utcnow() - timedelta(days=1)
apr_month_start = datetime(2016, 3, 31, 23)
apr_month_end = datetime(2016, 4, 30, 22, 59, 59, 99999)
create_rate(datetime(2016, 1, 1), 0.0123, 'sms')
create_notification(template=sample_template, status='delivered', created_at=yesterday)
populate_monthly_billing()
monthly_billing = MonthlyBilling.query.order_by(MonthlyBilling.notification_type).all()
assert len(monthly_billing) == 3
assert monthly_billing[0].service_id == sample_template.service_id
assert monthly_billing[0].start_date == apr_month_start
assert monthly_billing[0].end_date == apr_month_end
assert monthly_billing[0].notification_type == 'email'
assert monthly_billing[0].monthly_totals == []
assert monthly_billing[1].service_id == sample_template.service_id
assert monthly_billing[1].start_date == apr_month_start
assert monthly_billing[1].end_date == apr_month_end
assert monthly_billing[1].notification_type == 'sms'
assert monthly_billing[1].monthly_totals[0]['billing_units'] == 1
assert monthly_billing[1].monthly_totals[0]['total_cost'] == 0.0123
assert monthly_billing[2].service_id == sample_template.service_id
assert monthly_billing[2].start_date == apr_month_start
assert monthly_billing[2].end_date == apr_month_end
assert monthly_billing[2].notification_type == 'letter'
assert monthly_billing[2].monthly_totals == []
def test_run_letter_jobs(client, mocker, sample_letter_template):
jobs = [create_job(template=sample_letter_template, job_status=JOB_STATUS_READY_TO_SEND),
create_job(template=sample_letter_template, job_status=JOB_STATUS_READY_TO_SEND)]

View File

@@ -3,10 +3,12 @@ from datetime import datetime
import pytest
import requests_mock
from freezegun import freeze_time
from app import (DATETIME_FORMAT, encryption)
from app.celery.service_callback_tasks import send_delivery_status_to_service
from app.celery.service_callback_tasks import send_delivery_status_to_service, send_complaint_to_service
from tests.app.db import (
create_complaint,
create_notification,
create_service_callback_api,
create_service,
@@ -19,7 +21,7 @@ from tests.app.db import (
def test_send_delivery_status_to_service_post_https_request_to_service_with_encrypted_data(
notify_db_session, notification_type):
callback_api, template = _set_up_test_data(notification_type)
callback_api, template = _set_up_test_data(notification_type, "delivery_status")
datestr = datetime(2017, 6, 20)
notification = create_notification(template=template,
@@ -28,7 +30,7 @@ def test_send_delivery_status_to_service_post_https_request_to_service_with_encr
sent_at=datestr,
status='sent'
)
encrypted_status_update = _set_up_encrypted_data(callback_api, notification)
encrypted_status_update = _set_up_data_for_status_update(callback_api, notification)
with requests_mock.Mocker() as request_mock:
request_mock.post(callback_api.url,
json={},
@@ -54,12 +56,42 @@ def test_send_delivery_status_to_service_post_https_request_to_service_with_encr
assert request_mock.request_history[0].headers["Authorization"] == "Bearer {}".format(callback_api.bearer_token)
def test_send_complaint_to_service_posts_https_request_to_service_with_encrypted_data(notify_db_session):
with freeze_time('2001-01-01T12:00:00'):
callback_api, template = _set_up_test_data('email', "complaint")
notification = create_notification(template=template)
complaint = create_complaint(service=template.service, notification=notification)
complaint_data = _set_up_data_for_complaint(callback_api, complaint, notification)
with requests_mock.Mocker() as request_mock:
request_mock.post(callback_api.url,
json={},
status_code=200)
send_complaint_to_service(complaint_data)
mock_data = {
"notification_id": str(notification.id),
"complaint_id": str(complaint.id),
"reference": notification.client_reference,
"to": notification.to,
"complaint_date": datetime.utcnow().strftime(
DATETIME_FORMAT),
}
assert request_mock.call_count == 1
assert request_mock.request_history[0].url == callback_api.url
assert request_mock.request_history[0].method == 'POST'
assert request_mock.request_history[0].text == json.dumps(mock_data)
assert request_mock.request_history[0].headers["Content-type"] == "application/json"
assert request_mock.request_history[0].headers["Authorization"] == "Bearer {}".format(callback_api.bearer_token)
@pytest.mark.parametrize("notification_type",
["email", "letter", "sms"])
def test_send_delivery_status_to_service_retries_if_request_returns_500_with_encrypted_data(
def test__send_data_to_service_callback_api_retries_if_request_returns_500_with_encrypted_data(
notify_db_session, mocker, notification_type
):
callback_api, template = _set_up_test_data(notification_type)
callback_api, template = _set_up_test_data(notification_type, "delivery_status")
datestr = datetime(2017, 6, 20)
notification = create_notification(template=template,
created_at=datestr,
@@ -67,7 +99,7 @@ def test_send_delivery_status_to_service_retries_if_request_returns_500_with_enc
sent_at=datestr,
status='sent'
)
encrypted_data = _set_up_encrypted_data(callback_api, notification)
encrypted_data = _set_up_data_for_status_update(callback_api, notification)
mocked = mocker.patch('app.celery.service_callback_tasks.send_delivery_status_to_service.retry')
with requests_mock.Mocker() as request_mock:
request_mock.post(callback_api.url,
@@ -81,12 +113,12 @@ def test_send_delivery_status_to_service_retries_if_request_returns_500_with_enc
@pytest.mark.parametrize("notification_type",
["email", "letter", "sms"])
def test_send_delivery_status_to_service_does_not_retries_if_request_returns_404_with_encrypted_data(
def test__send_data_to_service_callback_api_does_not_retry_if_request_returns_404_with_encrypted_data(
notify_db_session,
mocker,
notification_type
):
callback_api, template = _set_up_test_data(notification_type)
callback_api, template = _set_up_test_data(notification_type, "delivery_status")
datestr = datetime(2017, 6, 20)
notification = create_notification(template=template,
created_at=datestr,
@@ -94,7 +126,7 @@ def test_send_delivery_status_to_service_does_not_retries_if_request_returns_404
sent_at=datestr,
status='sent'
)
encrypted_data = _set_up_encrypted_data(callback_api, notification)
encrypted_data = _set_up_data_for_status_update(callback_api, notification)
mocked = mocker.patch('app.celery.service_callback_tasks.send_delivery_status_to_service.retry')
with requests_mock.Mocker() as request_mock:
request_mock.post(callback_api.url,
@@ -109,7 +141,7 @@ def test_send_delivery_status_to_service_succeeds_if_sent_at_is_none(
notify_db_session,
mocker
):
callback_api, template = _set_up_test_data('email')
callback_api, template = _set_up_test_data('email', "delivery_status")
datestr = datetime(2017, 6, 20)
notification = create_notification(template=template,
created_at=datestr,
@@ -117,7 +149,7 @@ def test_send_delivery_status_to_service_succeeds_if_sent_at_is_none(
sent_at=None,
status='technical-failure'
)
encrypted_data = _set_up_encrypted_data(callback_api, notification)
encrypted_data = _set_up_data_for_status_update(callback_api, notification)
mocked = mocker.patch('app.celery.service_callback_tasks.send_delivery_status_to_service.retry')
with requests_mock.Mocker() as request_mock:
request_mock.post(callback_api.url,
@@ -128,15 +160,15 @@ def test_send_delivery_status_to_service_succeeds_if_sent_at_is_none(
assert mocked.call_count == 0
def _set_up_test_data(notification_type):
def _set_up_test_data(notification_type, callback_type):
service = create_service(restricted=True)
template = create_template(service=service, template_type=notification_type, subject='Hello')
callback_api = create_service_callback_api(service=service, url="https://some.service.gov.uk/",
bearer_token="something_unique")
bearer_token="something_unique", callback_type=callback_type)
return callback_api, template
def _set_up_encrypted_data(callback_api, notification):
def _set_up_data_for_status_update(callback_api, notification):
data = {
"notification_id": str(notification.id),
"notification_client_reference": notification.client_reference,
@@ -152,3 +184,17 @@ def _set_up_encrypted_data(callback_api, notification):
}
encrypted_status_update = encryption.encrypt(data)
return encrypted_status_update
def _set_up_data_for_complaint(callback_api, complaint, notification):
data = {
"complaint_id": str(complaint.id),
"notification_id": str(notification.id),
"reference": notification.client_reference,
"to": notification.to,
"complaint_date": complaint.complaint_date.strftime(DATETIME_FORMAT),
"service_callback_api_url": callback_api.url,
"service_callback_api_bearer_token": callback_api.bearer_token,
}
obscured_status_update = encryption.encrypt(data)
return obscured_status_update

View File

@@ -6,9 +6,12 @@ from freezegun import freeze_time
from app import db
from app.dao.fact_billing_dao import (
fetch_monthly_billing_for_year, fetch_billing_data_for_day, get_rates_for_billing,
get_rate,
delete_billing_data_for_service_for_day,
fetch_billing_data_for_day,
fetch_billing_totals_for_year,
fetch_monthly_billing_for_year,
get_rate,
get_rates_for_billing,
)
from app.models import FactBilling, Notification
from app.utils import convert_utc_to_bst
@@ -353,3 +356,25 @@ def test_fetch_billing_totals_for_year(notify_db_session):
assert results[3].notifications_sent == 365
assert results[3].billable_units == 365
assert results[3].rate == Decimal('0.162')
def test_delete_billing_data(notify_db_session):
service_1 = create_service(service_name='1')
service_2 = create_service(service_name='2')
sms_template = create_template(service_1, 'sms')
email_template = create_template(service_1, 'email')
other_service_template = create_template(service_2, 'sms')
existing_rows_to_delete = [ # noqa
create_ft_billing('2018-01-01', 'sms', sms_template, service_1, billable_unit=1),
create_ft_billing('2018-01-01', 'email', email_template, service_1, billable_unit=2)
]
other_day = create_ft_billing('2018-01-02', 'sms', sms_template, service_1, billable_unit=3)
other_service = create_ft_billing('2018-01-01', 'sms', other_service_template, service_2, billable_unit=4)
delete_billing_data_for_service_for_day('2018-01-01', service_1.id)
current_rows = FactBilling.query.all()
assert sorted(x.billable_units for x in current_rows) == sorted(
[other_day.billable_units, other_service.billable_units]
)

View File

@@ -1,521 +0,0 @@
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
from functools import partial
from app.dao.monthly_billing_dao import (
create_or_update_monthly_billing,
get_monthly_billing_entry,
get_monthly_billing_by_notification_type,
get_service_ids_that_need_billing_populated,
get_billing_data_for_financial_year
)
from app.models import MonthlyBilling, SMS_TYPE, EMAIL_TYPE
from tests.app.conftest import sample_letter_template
from tests.app.db import (
create_notification,
create_rate,
create_service,
create_template,
create_monthly_billing_entry,
)
FEB_2016_MONTH_START = datetime(2016, 2, 1)
FEB_2016_MONTH_END = datetime(2016, 2, 29, 23, 59, 59, 99999)
MAR_2016_MONTH_START = datetime(2016, 3, 1)
MAR_2016_MONTH_END = datetime(2016, 3, 31, 22, 59, 59, 99999)
APR_2016_MONTH_START = datetime(2016, 3, 31, 23, 00, 00)
APR_2016_MONTH_END = datetime(2016, 4, 30, 22, 59, 59, 99999)
MAY_2016_MONTH_START = datetime(2016, 5, 31, 23, 00, 00)
MAY_2016_MONTH_END = MAY_2016_MONTH_START + relativedelta(months=1, seconds=-1)
APR_2017_MONTH_START = datetime(2017, 3, 31, 23, 00, 00)
APR_2017_MONTH_END = datetime(2017, 4, 30, 23, 59, 59, 99999)
JAN_2017_MONTH_START = datetime(2017, 1, 1)
JAN_2017_MONTH_END = datetime(2017, 1, 31, 23, 59, 59, 99999)
FEB_2017 = datetime(2017, 2, 15)
APR_2016 = datetime(2016, 4, 10)
NO_BILLING_DATA = {
"billing_units": 0,
"rate_multiplier": 1,
"international": False,
"rate": 0,
"total_cost": 0
}
def _assert_monthly_billing(monthly_billing, service_id, notification_type, month_start, month_end):
assert monthly_billing.service_id == service_id
assert monthly_billing.notification_type == notification_type
assert monthly_billing.start_date == month_start
assert monthly_billing.end_date == month_end
def _assert_monthly_billing_totals(monthly_billing_totals, expected_dict):
assert sorted(monthly_billing_totals.keys()) == sorted(expected_dict.keys())
assert sorted(monthly_billing_totals.values()) == sorted(expected_dict.values())
def test_get_monthly_billing_by_notification_type_returns_correct_totals(notify_db, notify_db_session):
service = create_service(service_name="Service One")
create_monthly_billing_entry(
service=service,
monthly_totals=[{
"billing_units": 12,
"rate": 0.0158,
"rate_multiplier": 5,
"total_cost": 2.1804,
"international": False
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
monthly_billing_data = get_monthly_billing_by_notification_type(service.id, APR_2016, SMS_TYPE)
_assert_monthly_billing(
monthly_billing_data, service.id, 'sms', APR_2016_MONTH_START, APR_2016_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing_data.monthly_totals[0], {
"billing_units": 12,
"rate_multiplier": 5,
"international": False,
"rate": 0.0158,
"total_cost": 2.1804
})
def test_get_monthly_billing_by_notification_type_filters_by_type(notify_db, notify_db_session):
service = create_service(service_name="Service One")
create_monthly_billing_entry(
service=service,
monthly_totals=[{
"billing_units": 138,
"rate": 0.0158,
"rate_multiplier": 1,
"total_cost": 2.1804,
"international": None
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
create_monthly_billing_entry(
service=service,
monthly_totals=[],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=EMAIL_TYPE
)
monthly_billing_data = get_monthly_billing_by_notification_type(service.id, APR_2016, EMAIL_TYPE)
_assert_monthly_billing(
monthly_billing_data, service.id, 'email', APR_2016_MONTH_START, APR_2016_MONTH_END
)
assert monthly_billing_data.monthly_totals == []
def test_get_monthly_billing_by_notification_type_normalises_start_date(notify_db, notify_db_session):
service = create_service(service_name="Service One")
create_monthly_billing_entry(
service=service,
monthly_totals=[{
"billing_units": 321,
"rate": 0.0158,
"rate_multiplier": 1,
"total_cost": 2.1804,
"international": None
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
monthly_billing_data = get_monthly_billing_by_notification_type(service.id, APR_2016 + timedelta(days=5), SMS_TYPE)
assert monthly_billing_data.start_date == APR_2016_MONTH_START
assert monthly_billing_data.monthly_totals[0]['billing_units'] == 321
def test_add_monthly_billing_for_single_month_populates_correctly(
sample_template, sample_email_template
):
create_rate(start_date=JAN_2017_MONTH_START, value=0.0158, notification_type=SMS_TYPE)
letter_template = sample_letter_template(sample_template.service)
create_notification(
template=sample_template, created_at=JAN_2017_MONTH_START,
billable_units=1, rate_multiplier=2, status='delivered'
)
create_notification(template=sample_email_template, created_at=JAN_2017_MONTH_START,
status='delivered')
create_notification(template=letter_template, created_at=JAN_2017_MONTH_START, status='delivered')
create_or_update_monthly_billing(
service_id=sample_template.service_id,
billing_month=JAN_2017_MONTH_START
)
monthly_billing = MonthlyBilling.query.order_by(MonthlyBilling.notification_type).all()
assert len(monthly_billing) == 3
_assert_monthly_billing(
monthly_billing[0], sample_template.service.id, 'email', JAN_2017_MONTH_START, JAN_2017_MONTH_END
)
_assert_monthly_billing_totals(
monthly_billing[0].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 1,
"international": False,
"rate": 0.0,
"total_cost": 0
})
_assert_monthly_billing(
monthly_billing[1], sample_template.service.id, 'sms', JAN_2017_MONTH_START, JAN_2017_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[1].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 2,
"international": False,
"rate": 0.0158,
"total_cost": 1 * 2 * 0.0158
})
_assert_monthly_billing(
monthly_billing[2], sample_template.service.id, 'letter', JAN_2017_MONTH_START, JAN_2017_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[2].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 1,
"international": False,
"rate": 0.33,
"total_cost": 1 * 0.33
})
def test_add_monthly_billing_for_multiple_months_populate_correctly(
sample_template
):
create_rate(start_date=FEB_2016_MONTH_START - timedelta(days=1), value=0.12, notification_type=SMS_TYPE)
create_notification(
template=sample_template, created_at=FEB_2016_MONTH_START,
billable_units=1, rate_multiplier=2, status='delivered'
)
create_notification(
template=sample_template, created_at=MAR_2016_MONTH_START,
billable_units=2, rate_multiplier=3, status='delivered'
)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=FEB_2016_MONTH_START)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=MAR_2016_MONTH_START)
monthly_billing = MonthlyBilling.query.order_by(
MonthlyBilling.notification_type,
MonthlyBilling.start_date
).all()
assert len(monthly_billing) == 6
_assert_monthly_billing(
monthly_billing[0], sample_template.service.id, 'email', FEB_2016_MONTH_START, FEB_2016_MONTH_END
)
assert monthly_billing[0].monthly_totals == []
_assert_monthly_billing(
monthly_billing[1], sample_template.service.id, 'email', MAR_2016_MONTH_START, MAR_2016_MONTH_END
)
assert monthly_billing[1].monthly_totals == []
_assert_monthly_billing(
monthly_billing[2], sample_template.service.id, 'sms', FEB_2016_MONTH_START, FEB_2016_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[2].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 2,
"international": False,
"rate": 0.12,
"total_cost": 0.24
})
_assert_monthly_billing(
monthly_billing[3], sample_template.service.id, 'sms', MAR_2016_MONTH_START, MAR_2016_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[3].monthly_totals[0], {
"billing_units": 2,
"rate_multiplier": 3,
"international": False,
"rate": 0.12,
"total_cost": 0.72
})
_assert_monthly_billing(
monthly_billing[4], sample_template.service.id, 'letter', FEB_2016_MONTH_START, FEB_2016_MONTH_END
)
assert monthly_billing[4].monthly_totals == []
_assert_monthly_billing(
monthly_billing[5], sample_template.service.id, 'letter', MAR_2016_MONTH_START, MAR_2016_MONTH_END
)
assert monthly_billing[5].monthly_totals == []
def test_add_monthly_billing_with_multiple_rates_populate_correctly(
sample_template, sample_email_template
):
letter_template = sample_letter_template(sample_template.service)
create_rate(start_date=JAN_2017_MONTH_START, value=0.0158, notification_type=SMS_TYPE)
create_rate(start_date=JAN_2017_MONTH_START + timedelta(days=5), value=0.123, notification_type=SMS_TYPE)
create_notification(template=sample_template, created_at=JAN_2017_MONTH_START, billable_units=1, status='delivered')
create_notification(
template=sample_template, created_at=JAN_2017_MONTH_START + timedelta(days=6),
billable_units=2, status='delivered'
)
create_notification(template=sample_email_template, created_at=JAN_2017_MONTH_START, status='delivered')
create_notification(template=letter_template, created_at=JAN_2017_MONTH_START, status='delivered',
billable_units=1)
create_or_update_monthly_billing(service_id=sample_template.service_id, billing_month=JAN_2017_MONTH_START)
monthly_billing = MonthlyBilling.query.order_by(MonthlyBilling.notification_type).all()
assert len(monthly_billing) == 3
_assert_monthly_billing(
monthly_billing[0], sample_template.service.id, 'email', JAN_2017_MONTH_START, JAN_2017_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[0].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 1,
"international": False,
"rate": 0.0,
"total_cost": 0.0
})
_assert_monthly_billing(
monthly_billing[1], sample_template.service.id, 'sms', JAN_2017_MONTH_START, JAN_2017_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[1].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 1,
"international": False,
"rate": 0.0158,
"total_cost": 0.0158
})
_assert_monthly_billing_totals(monthly_billing[1].monthly_totals[1], {
"billing_units": 2,
"rate_multiplier": 1,
"international": False,
"rate": 0.123,
"total_cost": 0.246
})
_assert_monthly_billing(
monthly_billing[2], sample_template.service.id, 'letter', JAN_2017_MONTH_START, JAN_2017_MONTH_END
)
_assert_monthly_billing_totals(monthly_billing[2].monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 1,
"international": False,
"rate": 0.33,
"total_cost": 0.33
})
def test_update_monthly_billing_overwrites_old_totals(sample_template):
create_rate(APR_2016_MONTH_START, 0.123, SMS_TYPE)
create_notification(template=sample_template, created_at=APR_2016_MONTH_START, billable_units=1, status='delivered')
create_or_update_monthly_billing(sample_template.service_id, APR_2016_MONTH_END)
first_update = get_monthly_billing_by_notification_type(sample_template.service_id, APR_2016_MONTH_START, SMS_TYPE)
_assert_monthly_billing(
first_update, sample_template.service.id, 'sms', APR_2016_MONTH_START, APR_2016_MONTH_END
)
_assert_monthly_billing_totals(first_update.monthly_totals[0], {
"billing_units": 1,
"rate_multiplier": 1,
"international": False,
"rate": 0.123,
"total_cost": 0.123
})
first_updated_at = first_update.updated_at
with freeze_time(APR_2016_MONTH_START + timedelta(days=3)):
create_notification(template=sample_template, billable_units=2, status='delivered')
create_or_update_monthly_billing(sample_template.service_id, APR_2016_MONTH_END)
second_update = get_monthly_billing_by_notification_type(sample_template.service_id, APR_2016_MONTH_START, SMS_TYPE)
_assert_monthly_billing_totals(second_update.monthly_totals[0], {
"billing_units": 3,
"rate_multiplier": 1,
"international": False,
"rate": 0.123,
"total_cost": 0.369
})
assert second_update.updated_at == APR_2016_MONTH_START + timedelta(days=3)
assert first_updated_at != second_update.updated_at
def test_get_service_ids_that_need_billing_populated_return_correctly(notify_db_session):
service_1 = create_service(service_name="Service One")
template_1 = create_template(service=service_1)
service_2 = create_service(service_name="Service Two")
template_2 = create_template(service=service_2)
create_notification(template=template_1, created_at=datetime(2017, 6, 30, 13, 30), status='delivered')
create_notification(template=template_1, created_at=datetime(2017, 7, 1, 14, 30), status='delivered')
create_notification(template=template_2, created_at=datetime(2017, 7, 15, 13, 30))
create_notification(template=template_2, created_at=datetime(2017, 7, 31, 13, 30))
services = get_service_ids_that_need_billing_populated(
start_date=datetime(2017, 7, 1), end_date=datetime(2017, 7, 16)
)
expected_services = [service_1.id, service_2.id]
assert sorted([x.service_id for x in services]) == sorted(expected_services)
def test_get_monthly_billing_entry_filters_by_service(notify_db, notify_db_session):
service_1 = create_service(service_name="Service One")
service_2 = create_service(service_name="Service Two")
now = datetime.utcnow()
create_monthly_billing_entry(
service=service_1,
monthly_totals=[],
start_date=now,
end_date=now + timedelta(days=30),
notification_type=SMS_TYPE
)
create_monthly_billing_entry(
service=service_2,
monthly_totals=[],
start_date=now,
end_date=now + timedelta(days=30),
notification_type=SMS_TYPE
)
entry = get_monthly_billing_entry(service_2.id, now, SMS_TYPE)
assert entry.start_date == now
assert entry.service_id == service_2.id
def test_get_yearly_billing_data_for_year_returns_within_year_only(
sample_template
):
monthly_billing_entry = partial(
create_monthly_billing_entry, service=sample_template.service, notification_type=SMS_TYPE
)
monthly_billing_entry(start_date=FEB_2016_MONTH_START, end_date=FEB_2016_MONTH_END)
monthly_billing_entry(
monthly_totals=[{
"billing_units": 138,
"rate": 0.0158,
"rate_multiplier": 1,
"total_cost": 2.1804,
"international": None
}],
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
monthly_billing_entry(start_date=APR_2017_MONTH_START, end_date=APR_2017_MONTH_END)
billing_data = get_billing_data_for_financial_year(sample_template.service.id, 2016, [SMS_TYPE])
assert len(billing_data) == 1
assert billing_data[0].monthly_totals[0]['billing_units'] == 138
def test_get_yearly_billing_data_for_year_returns_multiple_notification_types(sample_template):
monthly_billing_entry = partial(
create_monthly_billing_entry, service=sample_template.service,
start_date=APR_2016_MONTH_START, end_date=APR_2016_MONTH_END
)
monthly_billing_entry(
notification_type=SMS_TYPE, monthly_totals=[]
)
monthly_billing_entry(
notification_type=EMAIL_TYPE,
monthly_totals=[{
"billing_units": 2,
"rate": 1.3,
"rate_multiplier": 3,
"total_cost": 2.1804,
"international": False
}]
)
billing_data = get_billing_data_for_financial_year(
service_id=sample_template.service.id,
year=2016,
notification_types=[SMS_TYPE, EMAIL_TYPE]
)
assert len(billing_data) == 2
assert billing_data[0].notification_type == EMAIL_TYPE
assert billing_data[0].monthly_totals[0]['billing_units'] == 2
assert billing_data[1].notification_type == SMS_TYPE
@freeze_time("2016-04-21 11:00:00")
def test_get_yearly_billing_data_for_year_includes_current_day_totals(sample_template):
create_rate(start_date=FEB_2016_MONTH_START, value=0.0158, notification_type=SMS_TYPE)
create_monthly_billing_entry(
service=sample_template.service,
start_date=APR_2016_MONTH_START,
end_date=APR_2016_MONTH_END,
notification_type=SMS_TYPE
)
billing_data = get_billing_data_for_financial_year(
service_id=sample_template.service.id,
year=2016,
notification_types=[SMS_TYPE]
)
assert len(billing_data) == 1
assert billing_data[0].notification_type == SMS_TYPE
assert billing_data[0].monthly_totals == []
create_notification(
template=sample_template,
created_at=datetime.utcnow(),
sent_at=datetime.utcnow(),
status='sending',
billable_units=3
)
billing_data = get_billing_data_for_financial_year(
service_id=sample_template.service.id,
year=2016,
notification_types=[SMS_TYPE]
)
assert billing_data[0].monthly_totals[0]['billing_units'] == 3
@freeze_time("2017-06-16 13:00:00")
def test_get_billing_data_for_financial_year_updated_monthly_billing_if_today_is_in_current_year(
sample_service,
mocker
):
mock = mocker.patch("app.dao.monthly_billing_dao.create_or_update_monthly_billing")
get_billing_data_for_financial_year(sample_service.id, 2016)
mock.assert_not_called()

View File

@@ -56,6 +56,49 @@ def test_save_service_callback_api_fails_if_service_does_not_exist(notify_db, no
save_service_callback_api(service_callback_api)
def test_update_service_callback_api_unique_constraint(sample_service):
service_callback_api = ServiceCallbackApi(
service_id=sample_service.id,
url="https://some_service/callback_endpoint",
bearer_token="some_unique_string",
updated_by_id=sample_service.users[0].id,
callback_type='delivery_status'
)
save_service_callback_api(service_callback_api)
another = ServiceCallbackApi(
service_id=sample_service.id,
url="https://some_service/another_callback_endpoint",
bearer_token="different_string",
updated_by_id=sample_service.users[0].id,
callback_type='delivery_status'
)
with pytest.raises(expected_exception=SQLAlchemyError):
save_service_callback_api(another)
def test_update_service_callback_can_add_two_api_of_different_types(sample_service):
delivery_status = ServiceCallbackApi(
service_id=sample_service.id,
url="https://some_service/callback_endpoint",
bearer_token="some_unique_string",
updated_by_id=sample_service.users[0].id,
callback_type='delivery_status'
)
save_service_callback_api(delivery_status)
complaint = ServiceCallbackApi(
service_id=sample_service.id,
url="https://some_service/another_callback_endpoint",
bearer_token="different_string",
updated_by_id=sample_service.users[0].id,
callback_type='complaint'
)
save_service_callback_api(complaint)
results = ServiceCallbackApi.query.order_by(ServiceCallbackApi.callback_type).all()
assert len(results) == 2
assert results[0].serialize() == complaint.serialize()
assert results[1].serialize() == delivery_status.serialize()
def test_update_service_callback_api(sample_service):
service_callback_api = ServiceCallbackApi(
service_id=sample_service.id,

View File

@@ -14,7 +14,6 @@ from app.models import (
InboundSms,
InboundNumber,
Job,
MonthlyBilling,
Notification,
EmailBranding,
Organisation,
@@ -382,27 +381,6 @@ def create_inbound_number(number, provider='mmg', active=True, service_id=None):
return inbound_number
def create_monthly_billing_entry(
service,
start_date,
end_date,
notification_type,
monthly_totals=[]
):
entry = MonthlyBilling(
service_id=service.id,
notification_type=notification_type,
monthly_totals=monthly_totals,
start_date=start_date,
end_date=end_date
)
db.session.add(entry)
db.session.commit()
return entry
def create_reply_to_email(
service,
email_address,

View File

@@ -5,7 +5,7 @@ from flask import json
from freezegun import freeze_time
from sqlalchemy.exc import SQLAlchemyError
from app import statsd_client
from app import statsd_client, encryption
from app.dao.notifications_dao import get_notification_by_id
from app.models import Notification, Complaint
from app.notifications.notifications_ses_callback import (
@@ -13,7 +13,7 @@ from app.notifications.notifications_ses_callback import (
handle_complaint
)
from app.celery.research_mode_tasks import ses_hard_bounce_callback, ses_soft_bounce_callback, ses_notification_callback
from app.celery.service_callback_tasks import create_encrypted_callback_data
from app.celery.service_callback_tasks import create_delivery_status_callback_data
from tests.app.conftest import sample_notification as create_sample_notification
from tests.app.db import (
@@ -55,7 +55,7 @@ def test_ses_callback_should_update_notification_status(
)
statsd_client.incr.assert_any_call("callback.ses.delivered")
updated_notification = Notification.query.get(notification.id)
encrypted_data = create_encrypted_callback_data(updated_notification, callback_api)
encrypted_data = create_delivery_status_callback_data(updated_notification, callback_api)
send_mock.assert_called_once_with([str(notification.id), encrypted_data], queue="service-callbacks")
@@ -220,3 +220,28 @@ def test_process_ses_results_in_complaint_save_complaint_with_null_complaint_typ
assert len(complaints) == 1
assert complaints[0].notification_id == notification.id
assert not complaints[0].complaint_type
def test_ses_callback_should_send_on_complaint_to_user_callback_api(sample_email_template, mocker):
send_mock = mocker.patch(
'app.celery.service_callback_tasks.send_complaint_to_service.apply_async'
)
create_service_callback_api(
service=sample_email_template.service, url="https://original_url.com", callback_type="complaint"
)
notification = create_notification(template=sample_email_template, reference='ref1')
response = ses_complaint_callback()
errors = process_ses_response(response)
assert errors is None
assert send_mock.call_count == 1
assert encryption.decrypt(send_mock.call_args[0][0][0]) == {
'complaint_date': '2018-06-05T13:59:58.000000Z',
'complaint_id': str(Complaint.query.one().id),
'notification_id': str(notification.id),
'reference': None,
'service_callback_api_bearer_token': 'some_super_secret',
'service_callback_api_url': 'https://original_url.com',
'to': 'recipient1@example.com'
}

View File

@@ -7,7 +7,7 @@ from app.notifications.process_client_response import (
validate_callback_data,
process_sms_client_response
)
from app.celery.service_callback_tasks import create_encrypted_callback_data
from app.celery.service_callback_tasks import create_delivery_status_callback_data
from tests.app.db import create_service_callback_api
@@ -64,7 +64,7 @@ def test_outcome_statistics_called_for_successful_callback(sample_notification,
success, error = process_sms_client_response(status='3', provider_reference=reference, client_name='MMG')
assert success == "MMG callback succeeded. reference {} updated".format(str(reference))
assert error is None
encrypted_data = create_encrypted_callback_data(sample_notification, callback_api)
encrypted_data = create_delivery_status_callback_data(sample_notification, callback_api)
send_mock.assert_called_once_with([str(sample_notification.id), encrypted_data],
queue="service-callbacks")