diff --git a/app/dao/monthly_billing_dao.py b/app/dao/monthly_billing_dao.py index 83766e33a..e83fbf751 100644 --- a/app/dao/monthly_billing_dao.py +++ b/app/dao/monthly_billing_dao.py @@ -79,19 +79,38 @@ def get_monthly_billing_entry(service_id, start_date, notification_type): @statsd(namespace="dao") -def get_monthly_billing_sms(service_id, billing_month): - start_date, end_date = get_month_start_end_date(billing_month) - monthly = MonthlyBilling.query.filter_by(service_id=service_id, - start_date=start_date, - notification_type=SMS_TYPE).first() - return monthly +def get_yearly_billing_data_for_date_range( + service_id, start_date, end_date, notification_types +): + results = MonthlyBilling.query.filter( + MonthlyBilling.service_id == service_id, + MonthlyBilling.start_date >= start_date, + MonthlyBilling.end_date <= end_date, + MonthlyBilling.notification_type.in_(notification_types) + ).order_by( + MonthlyBilling.notification_type + ).all() + + return results -def _monthly_billing_data_to_json(monthly): - # total cost must take into account the free allowance. - # might be a good idea to capture free allowance in this table - return [{"billing_units": x.billing_units, - "rate_multiplier": x.rate_multiplier, - "international": x.international, - "rate": x.rate, - "total_cost": (x.billing_units * x.rate_multiplier) * x.rate} for x in monthly] +@statsd(namespace="dao") +def get_monthly_billing_by_notification_type(service_id, billing_month, notification_type): + billing_month_in_bst = convert_utc_to_bst(billing_month) + start_date, _ = get_month_start_and_end_date_in_utc(billing_month_in_bst) + return get_monthly_billing_entry(service_id, start_date, notification_type) + + +@statsd(namespace="dao") +def get_billing_data_for_financial_year(service_id, year, notification_types=[SMS_TYPE, EMAIL_TYPE]): + # Update totals to the latest so we include data for today + now = convert_utc_to_bst(datetime.utcnow()) + create_or_update_monthly_billing(service_id=service_id, billing_month=now) + + start_date, end_date = get_financial_year(year) + + results = get_yearly_billing_data_for_date_range( + service_id, start_date, end_date, notification_types + ) + + return results diff --git a/tests/app/dao/test_monthly_billing.py b/tests/app/dao/test_monthly_billing.py index 5c6218a58..044b497b7 100644 --- a/tests/app/dao/test_monthly_billing.py +++ b/tests/app/dao/test_monthly_billing.py @@ -378,3 +378,114 @@ def test_get_monthly_billing_entry_filters_by_service(notify_db, notify_db_sessi 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_monthly_billing( + billing_data[0], sample_template.service.id, 'email', APR_2016_MONTH_START, APR_2016_MONTH_END + ) + _assert_monthly_billing_totals(billing_data[0].monthly_totals[0], { + "billing_units": 2, + "rate_multiplier": 3, + "international": False, + "rate": 1.3, + "total_cost": 2.1804 + }) + + _assert_monthly_billing( + billing_data[1], sample_template.service.id, 'sms', APR_2016_MONTH_START, APR_2016_MONTH_END + ) + assert billing_data[1].monthly_totals == [] + + +@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_monthly_billing( + billing_data[0], sample_template.service.id, 'sms', APR_2016_MONTH_START, APR_2016_MONTH_END + ) + 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