diff --git a/app/billing/billing_schemas.py b/app/billing/billing_schemas.py index 1c1f6e8ee..ba92a8a9e 100644 --- a/app/billing/billing_schemas.py +++ b/app/billing/billing_schemas.py @@ -25,6 +25,7 @@ def serialize_ft_billing_remove_emails(rows): "postage": row.postage, "cost": float(row.cost), "free_allowance_used": row.free_allowance_used, + "charged_units": row.charged_units, } for row in rows if row.notification_type != 'email' @@ -44,6 +45,7 @@ def serialize_ft_billing_yearly_totals(rows): "letter_total": float(row.billable_units * row.rate) if row.notification_type == 'letter' else 0, "cost": float(row.cost), "free_allowance_used": row.free_allowance_used, + "charged_units": row.charged_units, } for row in rows ] diff --git a/app/dao/fact_billing_dao.py b/app/dao/fact_billing_dao.py index 0ad1b0334..899cc780f 100644 --- a/app/dao/fact_billing_dao.py +++ b/app/dao/fact_billing_dao.py @@ -225,6 +225,7 @@ def fetch_billing_totals_for_year(service_id, year): func.sum(query.c.chargeable_units).label("chargeable_units"), func.sum(query.c.cost).label("cost"), func.sum(query.c.free_allowance_used).label("free_allowance_used"), + func.sum(query.c.charged_units).label("charged_units"), ).group_by( query.c.rate, query.c.notification_type @@ -284,6 +285,7 @@ def fetch_monthly_billing_for_year(service_id, year): func.sum(query.c.chargeable_units).label("chargeable_units"), func.sum(query.c.cost).label("cost"), func.sum(query.c.free_allowance_used).label("free_allowance_used"), + func.sum(query.c.charged_units).label("charged_units"), ).group_by( query.c.rate, query.c.notification_type, @@ -317,6 +319,7 @@ def query_service_email_usage_for_year(service_id, year): FactBilling.notification_type, literal(0).label("cost"), literal(0).label("free_allowance_used"), + FactBilling.billable_units.label("charged_units"), ).filter( FactBilling.service_id == service_id, FactBilling.bst_date >= year_start, @@ -342,6 +345,7 @@ def query_service_letter_usage_for_year(service_id, year): FactBilling.notification_type, (FactBilling.notifications_sent * FactBilling.rate).label("cost"), literal(0).label("free_allowance_used"), + FactBilling.notifications_sent.label("charged_units"), ).filter( FactBilling.service_id == service_id, FactBilling.bst_date >= year_start, @@ -421,6 +425,7 @@ def query_service_sms_usage_for_year(service_id, year): FactBilling.notification_type, (charged_units * FactBilling.rate).label("cost"), free_allowance_used.label("free_allowance_used"), + charged_units.label("charged_units"), ).join( AnnualBilling, AnnualBilling.service_id == service_id diff --git a/tests/app/billing/test_rest.py b/tests/app/billing/test_rest.py index 8dad33ed0..e0d979066 100644 --- a/tests/app/billing/test_rest.py +++ b/tests/app/billing/test_rest.py @@ -178,6 +178,7 @@ def test_get_yearly_usage_by_monthly_from_ft_billing(admin_request, notify_db_se assert letter_row["postage"] == "second" assert letter_row["cost"] == 9.9 assert letter_row["free_allowance_used"] == 0 + assert letter_row["charged_units"] == 30 assert sms_row["month"] == "April" assert sms_row["notification_type"] == "sms" @@ -189,6 +190,7 @@ def test_get_yearly_usage_by_monthly_from_ft_billing(admin_request, notify_db_se # free allowance is 4, so (30 - 4) * 0.162 assert sms_row["cost"] == 4.212 assert sms_row["free_allowance_used"] == 4 + assert sms_row["charged_units"] == 26 def set_up_yearly_data(): @@ -263,6 +265,7 @@ def test_get_yearly_billing_usage_summary_from_ft_billing(admin_request, notify_ assert json_response[0]['letter_total'] == 0 assert json_response[0]['cost'] == 0 assert json_response[0]['free_allowance_used'] == 0 + assert json_response[0]['charged_units'] == 0 assert json_response[1]['notification_type'] == 'letter' assert json_response[1]['billing_units'] == 275 @@ -272,6 +275,7 @@ def test_get_yearly_billing_usage_summary_from_ft_billing(admin_request, notify_ assert json_response[1]['letter_total'] == 90.75 assert json_response[1]['cost'] == 90.75 assert json_response[1]['free_allowance_used'] == 0 + assert json_response[1]['charged_units'] == 275 assert json_response[2]['notification_type'] == 'sms' assert json_response[2]['billing_units'] == 825 @@ -281,3 +285,4 @@ def test_get_yearly_billing_usage_summary_from_ft_billing(admin_request, notify_ assert json_response[2]['letter_total'] == 0 assert json_response[2]['cost'] == 13.3002 assert json_response[2]['free_allowance_used'] == 4 + assert json_response[2]['charged_units'] == 821 diff --git a/tests/app/dao/test_ft_billing_dao.py b/tests/app/dao/test_ft_billing_dao.py index 2b515e3e9..96b699c95 100644 --- a/tests/app/dao/test_ft_billing_dao.py +++ b/tests/app/dao/test_ft_billing_dao.py @@ -439,6 +439,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[0].rate == Decimal('0') assert results[0].cost == Decimal('0') assert results[0].free_allowance_used == 0 + assert results[0].charged_units == 0 assert str(results[1].month) == "2016-04-01" assert results[1].notification_type == 'letter' @@ -448,6 +449,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[1].rate == Decimal('0.30') assert results[1].cost == Decimal('9') assert results[1].free_allowance_used == 0 + assert results[1].charged_units == 30 assert str(results[1].month) == "2016-04-01" assert results[2].notification_type == 'letter' @@ -457,6 +459,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[2].rate == Decimal('0.33') assert results[2].cost == Decimal('9.9') assert results[2].free_allowance_used == 0 + assert results[2].charged_units == 30 assert str(results[3].month) == "2016-04-01" assert results[3].notification_type == 'sms' @@ -467,6 +470,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): # free allowance is 10, so (30 - 10) * 0.162 assert results[3].cost == Decimal('3.24') assert results[3].free_allowance_used == 10 + assert results[3].charged_units == 20 assert str(results[4].month) == "2016-05-01" assert str(results[47].month) == "2017-03-01" @@ -488,6 +492,7 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[0].rate == Decimal('0.33') assert results[0].cost == Decimal('0.33') assert results[0].free_allowance_used == 0 + assert results[0].charged_units == 1 assert str(results[1].month) == "2018-05-01" assert results[1].notification_type == 'letter' @@ -497,6 +502,7 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[1].rate == Decimal('0.36') assert results[1].cost == Decimal('0.72') assert results[1].free_allowance_used == 0 + assert results[1].charged_units == 2 assert str(results[2].month) == "2018-05-01" assert results[2].notification_type == 'sms' @@ -507,6 +513,7 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): # 1 free units on the 17th assert results[2].cost == Decimal('0.045') assert results[2].free_allowance_used == 1 + assert results[2].charged_units == 3 assert str(results[3].month) == "2018-05-01" assert results[3].notification_type == 'sms' @@ -517,6 +524,7 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): # 5 free units on the 16th assert results[3].cost == Decimal('0') assert results[3].free_allowance_used == 5 + assert results[3].charged_units == 0 @freeze_time('2018-08-01 13:30:00') @@ -552,6 +560,7 @@ def test_fetch_billing_totals_for_year(notify_db_session): assert results[0].rate == Decimal('0') assert results[0].cost == Decimal('0') assert results[0].free_allowance_used == 0 + assert results[0].charged_units == 0 assert results[1].notification_type == 'letter' assert results[1].notifications_sent == 365 @@ -560,6 +569,7 @@ def test_fetch_billing_totals_for_year(notify_db_session): assert results[1].rate == Decimal('0.3') assert results[1].cost == Decimal('109.5') assert results[1].free_allowance_used == 0 + assert results[1].charged_units == 365 assert results[2].notification_type == 'letter' assert results[2].notifications_sent == 365 @@ -568,6 +578,7 @@ def test_fetch_billing_totals_for_year(notify_db_session): assert results[2].rate == Decimal('0.33') assert results[2].cost == Decimal('120.45') assert results[2].free_allowance_used == 0 + assert results[2].charged_units == 365 assert results[3].notification_type == 'sms' assert results[3].notifications_sent == 365 @@ -576,6 +587,7 @@ def test_fetch_billing_totals_for_year(notify_db_session): assert results[3].rate == Decimal('0.162') assert results[3].cost == Decimal('0') assert results[3].free_allowance_used == 365 + assert results[3].charged_units == 0 def test_fetch_billing_totals_for_year_uses_current_annual_billing(notify_db_session): @@ -606,6 +618,7 @@ def test_fetch_billing_totals_for_year_variable_rates(notify_db_session): assert results[0].rate == Decimal('0.33') assert results[0].cost == Decimal('0.33') assert results[0].free_allowance_used == 0 + assert results[0].charged_units == 1 assert results[1].notification_type == 'letter' assert results[1].notifications_sent == 2 @@ -614,6 +627,7 @@ def test_fetch_billing_totals_for_year_variable_rates(notify_db_session): assert results[1].rate == Decimal('0.36') assert results[1].cost == Decimal('0.72') assert results[1].free_allowance_used == 0 + assert results[1].charged_units == 2 assert results[2].notification_type == 'sms' assert results[2].notifications_sent == 1 @@ -623,6 +637,7 @@ def test_fetch_billing_totals_for_year_variable_rates(notify_db_session): # 1 free unit on the 17th assert results[2].cost == Decimal('0.045') assert results[2].free_allowance_used == 1 + assert results[2].charged_units == 3 assert results[3].notification_type == 'sms' assert results[3].notifications_sent == 2 @@ -632,6 +647,7 @@ def test_fetch_billing_totals_for_year_variable_rates(notify_db_session): # 5 free units on the 16th assert results[3].cost == Decimal('0') assert results[3].free_allowance_used == 5 + assert results[3].charged_units == 0 def test_delete_billing_data(notify_db_session):