diff --git a/app/billing/rest.py b/app/billing/rest.py index 83adb0b37..782e9cec3 100644 --- a/app/billing/rest.py +++ b/app/billing/rest.py @@ -3,12 +3,14 @@ import json from flask import Blueprint, jsonify, request -from app.dao.notification_usage_dao import get_billing_data_for_month -from app.dao.monthly_billing_dao import get_billing_data_for_financial_year -from app.dao.date_util import get_financial_year +from app.dao.monthly_billing_dao import ( + get_billing_data_for_financial_year, + get_monthly_billing_by_notification_type +) +from app.dao.date_util import get_financial_year, get_months_for_financial_year from app.errors import register_errors from app.models import SMS_TYPE, EMAIL_TYPE - +from app.utils import convert_utc_to_bst billing_blueprint = Blueprint( 'billing', @@ -25,16 +27,13 @@ def get_yearly_usage_by_month(service_id): try: year = int(request.args.get('year')) start_date, end_date = get_financial_year(year) - results = get_billing_data_for_month(service_id, start_date, end_date, SMS_TYPE) - json_results = [{ - "month": datetime.strftime(x[0], "%B"), - "billing_units": x[1], - "rate_multiplier": x[2], - "international": x[3], - "notification_type": x[4], - "rate": x[5] - } for x in results] - return json.dumps(json_results) + results = [] + for month in get_months_for_financial_year(year): + billing_for_month = get_monthly_billing_by_notification_type(service_id, month, SMS_TYPE) + if billing_for_month: + results.append(_transform_billing_for_month(billing_for_month)) + return json.dumps(results) + except TypeError: return jsonify(result='error', message='No valid year provided'), 400 @@ -71,3 +70,23 @@ def _get_total_billable_units_and_rate_for_notification_type(billing_data, noti_ "billing_units": total_sent, "rate": rate } + + +def _transform_billing_for_month(billing_for_month): + month_name = datetime.strftime(convert_utc_to_bst(billing_for_month.start_date), "%B") + billing_units = rate = rate_multiplier = international = 0 + + if billing_for_month.monthly_totals: + billing_units = billing_for_month.monthly_totals[0]['billing_units'] + rate = billing_for_month.monthly_totals[0]['rate'] + rate_multiplier = billing_for_month.monthly_totals[0]['rate_multiplier'] + international = billing_for_month.monthly_totals[0]['international'] + + return { + "month": month_name, + "billing_units": billing_units, + "rate_multiplier": rate_multiplier, + "international": bool(international), + "notification_type": billing_for_month.notification_type, + "rate": rate + } diff --git a/tests/app/billing/test_billing.py b/tests/app/billing/test_billing.py index ac034fe34..d1cb20aff 100644 --- a/tests/app/billing/test_billing.py +++ b/tests/app/billing/test_billing.py @@ -1,14 +1,23 @@ from datetime import datetime, timedelta import json -from app.dao.monthly_billing_dao import create_or_update_monthly_billing +from app.billing.rest import _transform_billing_for_month +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 from tests.app.db import ( create_notification, - create_rate + create_rate, + create_monthly_billing_entry ) + from tests import create_authorization_header +APR_2016_MONTH_START = datetime(2016, 3, 31, 23, 00, 00) +APR_2016_MONTH_END = datetime(2016, 4, 30, 22, 59, 59, 99999) + IN_MAY_2016 = datetime(2016, 5, 10, 23, 00, 00) IN_JUN_2016 = datetime(2016, 6, 3, 23, 00, 00) @@ -76,7 +85,7 @@ def test_get_yearly_usage_by_month_returns_400_if_missing_year(client, sample_se } -def test_get_yearly_usage_by_month_returns_empty_list_if_no_notifications(client, sample_template): +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), @@ -128,3 +137,55 @@ def test_get_yearly_usage_by_month_returns_correctly(client, sample_template): 'rate': 0.12, 'rate_multiplier': 3 }) + + +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(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', + 'international': False, + 'rate_multiplier': 0, + '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(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': 12, + 'month': 'April', + 'international': False, + 'rate_multiplier': 5, + 'rate': 0.0158, + })