From ff32000180ac76f310174794ab8960c16adfc06d Mon Sep 17 00:00:00 2001 From: Ben Thorner Date: Thu, 21 Apr 2022 11:29:43 +0100 Subject: [PATCH] Add "cost" field to monthly usage API This starts to replace the calculation in Admin [^1] and, similar to the yearly API, also correctly attributes free allowance when we have a rate change during a month. [^1]: https://github.com/alphagov/notifications-admin/blob/474d7dfda834ebf2f0966f176fb6da556808d8a1/app/templates/views/usage.html#L98 --- app/billing/billing_schemas.py | 1 + app/dao/fact_billing_dao.py | 1 + tests/app/billing/test_rest.py | 3 +++ tests/app/dao/test_ft_billing_dao.py | 11 +++++++++++ 4 files changed, 16 insertions(+) diff --git a/app/billing/billing_schemas.py b/app/billing/billing_schemas.py index d77f718d5..92144b84d 100644 --- a/app/billing/billing_schemas.py +++ b/app/billing/billing_schemas.py @@ -22,6 +22,7 @@ def serialize_ft_billing_remove_emails(rows): "chargeable_units": row.chargeable_units, "rate": float(row.rate), "postage": row.postage, + "cost": float(row.cost), } for row in rows if row.notification_type != 'email' diff --git a/app/dao/fact_billing_dao.py b/app/dao/fact_billing_dao.py index df2012123..59beac8cc 100644 --- a/app/dao/fact_billing_dao.py +++ b/app/dao/fact_billing_dao.py @@ -244,6 +244,7 @@ def fetch_monthly_billing_for_year(service_id, year): query.c.rate.label("rate"), query.c.postage.label("postage"), query.c.notification_type.label("notification_type"), + func.sum(query.c.cost).label("cost"), ).group_by( query.c.rate, query.c.notification_type, diff --git a/tests/app/billing/test_rest.py b/tests/app/billing/test_rest.py index e740d62c6..a9bac97e1 100644 --- a/tests/app/billing/test_rest.py +++ b/tests/app/billing/test_rest.py @@ -175,6 +175,7 @@ def test_get_yearly_usage_by_monthly_from_ft_billing(admin_request, notify_db_se assert letter_row["chargeable_units"] == 30 assert letter_row["rate"] == 0.33 assert letter_row["postage"] == "second" + assert letter_row["cost"] == 9.9 assert sms_row["month"] == "April" assert sms_row["notification_type"] == "sms" @@ -182,6 +183,8 @@ def test_get_yearly_usage_by_monthly_from_ft_billing(admin_request, notify_db_se assert sms_row["chargeable_units"] == 30 assert sms_row["rate"] == 0.162 assert sms_row["postage"] == "none" + # free allowance is 4, so (30 - 4) * 0.162 + assert sms_row["cost"] == 4.212 def set_up_yearly_data(): diff --git a/tests/app/dao/test_ft_billing_dao.py b/tests/app/dao/test_ft_billing_dao.py index bede8a190..e8f5a685b 100644 --- a/tests/app/dao/test_ft_billing_dao.py +++ b/tests/app/dao/test_ft_billing_dao.py @@ -428,6 +428,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[0].billable_units == 30 assert results[0].chargeable_units == 30 assert results[0].rate == Decimal('0') + assert results[0].cost == Decimal('0') assert str(results[1].month) == "2016-04-01" assert results[1].notification_type == 'letter' @@ -435,6 +436,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[1].billable_units == 30 assert results[1].chargeable_units == 30 assert results[1].rate == Decimal('0.30') + assert results[1].cost == Decimal('9') assert str(results[1].month) == "2016-04-01" assert results[2].notification_type == 'letter' @@ -442,6 +444,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[2].billable_units == 30 assert results[2].chargeable_units == 30 assert results[2].rate == Decimal('0.33') + assert results[2].cost == Decimal('9.9') assert str(results[3].month) == "2016-04-01" assert results[3].notification_type == 'sms' @@ -449,6 +452,8 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[3].billable_units == 30 assert results[3].chargeable_units == 30 assert results[3].rate == Decimal('0.162') + # free allowance is 10, so (30 - 10) * 0.162 + assert results[3].cost == Decimal('3.24') assert str(results[4].month) == "2016-05-01" assert str(results[47].month) == "2017-03-01" @@ -468,6 +473,7 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[0].billable_units == 1 assert results[0].chargeable_units == 1 assert results[0].rate == Decimal('0.33') + assert results[0].cost == Decimal('0.33') assert str(results[1].month) == "2018-05-01" assert results[1].notification_type == 'letter' @@ -475,6 +481,7 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[1].billable_units == 1 assert results[1].chargeable_units == 1 assert results[1].rate == Decimal('0.36') + assert results[1].cost == Decimal('0.36') assert str(results[2].month) == "2018-05-01" assert results[2].notification_type == 'sms' @@ -482,6 +489,8 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[2].billable_units == 4 assert results[2].chargeable_units == 4 assert results[2].rate == Decimal('0.015') + # 4 free units sent on the 16th, 0 on the 17th + assert results[2].cost == Decimal('0') assert str(results[3].month) == "2018-05-01" assert results[3].notification_type == 'sms' @@ -489,6 +498,8 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[3].billable_units == 5 assert results[3].chargeable_units == 5 assert results[3].rate == Decimal('0.162') + # 1 free unit on the 16th, 1 on the 17th (+ 3 paid) + assert results[3].cost == Decimal('0.486') @freeze_time('2018-08-01 13:30:00')