mirror of
https://github.com/GSA/notifications-api.git
synced 2026-07-19 05:54:18 -04:00
Add "charged_units" to service usage APIs
This can be calculated from the "free_allowance_used" field and the
"chargeable_units" field, but having it included separately is more
convenient as it can be used directly in Admin [^1].
[^1]: 417e7370bb/app/templates/views/usage.html (L38-L39)
This commit is contained in:
@@ -25,6 +25,7 @@ def serialize_ft_billing_remove_emails(rows):
|
|||||||
"postage": row.postage,
|
"postage": row.postage,
|
||||||
"cost": float(row.cost),
|
"cost": float(row.cost),
|
||||||
"free_allowance_used": row.free_allowance_used,
|
"free_allowance_used": row.free_allowance_used,
|
||||||
|
"charged_units": row.charged_units,
|
||||||
}
|
}
|
||||||
for row in rows
|
for row in rows
|
||||||
if row.notification_type != 'email'
|
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,
|
"letter_total": float(row.billable_units * row.rate) if row.notification_type == 'letter' else 0,
|
||||||
"cost": float(row.cost),
|
"cost": float(row.cost),
|
||||||
"free_allowance_used": row.free_allowance_used,
|
"free_allowance_used": row.free_allowance_used,
|
||||||
|
"charged_units": row.charged_units,
|
||||||
}
|
}
|
||||||
for row in rows
|
for row in rows
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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.chargeable_units).label("chargeable_units"),
|
||||||
func.sum(query.c.cost).label("cost"),
|
func.sum(query.c.cost).label("cost"),
|
||||||
func.sum(query.c.free_allowance_used).label("free_allowance_used"),
|
func.sum(query.c.free_allowance_used).label("free_allowance_used"),
|
||||||
|
func.sum(query.c.charged_units).label("charged_units"),
|
||||||
).group_by(
|
).group_by(
|
||||||
query.c.rate,
|
query.c.rate,
|
||||||
query.c.notification_type
|
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.chargeable_units).label("chargeable_units"),
|
||||||
func.sum(query.c.cost).label("cost"),
|
func.sum(query.c.cost).label("cost"),
|
||||||
func.sum(query.c.free_allowance_used).label("free_allowance_used"),
|
func.sum(query.c.free_allowance_used).label("free_allowance_used"),
|
||||||
|
func.sum(query.c.charged_units).label("charged_units"),
|
||||||
).group_by(
|
).group_by(
|
||||||
query.c.rate,
|
query.c.rate,
|
||||||
query.c.notification_type,
|
query.c.notification_type,
|
||||||
@@ -317,6 +319,7 @@ def query_service_email_usage_for_year(service_id, year):
|
|||||||
FactBilling.notification_type,
|
FactBilling.notification_type,
|
||||||
literal(0).label("cost"),
|
literal(0).label("cost"),
|
||||||
literal(0).label("free_allowance_used"),
|
literal(0).label("free_allowance_used"),
|
||||||
|
FactBilling.billable_units.label("charged_units"),
|
||||||
).filter(
|
).filter(
|
||||||
FactBilling.service_id == service_id,
|
FactBilling.service_id == service_id,
|
||||||
FactBilling.bst_date >= year_start,
|
FactBilling.bst_date >= year_start,
|
||||||
@@ -342,6 +345,7 @@ def query_service_letter_usage_for_year(service_id, year):
|
|||||||
FactBilling.notification_type,
|
FactBilling.notification_type,
|
||||||
(FactBilling.notifications_sent * FactBilling.rate).label("cost"),
|
(FactBilling.notifications_sent * FactBilling.rate).label("cost"),
|
||||||
literal(0).label("free_allowance_used"),
|
literal(0).label("free_allowance_used"),
|
||||||
|
FactBilling.notifications_sent.label("charged_units"),
|
||||||
).filter(
|
).filter(
|
||||||
FactBilling.service_id == service_id,
|
FactBilling.service_id == service_id,
|
||||||
FactBilling.bst_date >= year_start,
|
FactBilling.bst_date >= year_start,
|
||||||
@@ -421,6 +425,7 @@ def query_service_sms_usage_for_year(service_id, year):
|
|||||||
FactBilling.notification_type,
|
FactBilling.notification_type,
|
||||||
(charged_units * FactBilling.rate).label("cost"),
|
(charged_units * FactBilling.rate).label("cost"),
|
||||||
free_allowance_used.label("free_allowance_used"),
|
free_allowance_used.label("free_allowance_used"),
|
||||||
|
charged_units.label("charged_units"),
|
||||||
).join(
|
).join(
|
||||||
AnnualBilling,
|
AnnualBilling,
|
||||||
AnnualBilling.service_id == service_id
|
AnnualBilling.service_id == service_id
|
||||||
|
|||||||
@@ -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["postage"] == "second"
|
||||||
assert letter_row["cost"] == 9.9
|
assert letter_row["cost"] == 9.9
|
||||||
assert letter_row["free_allowance_used"] == 0
|
assert letter_row["free_allowance_used"] == 0
|
||||||
|
assert letter_row["charged_units"] == 30
|
||||||
|
|
||||||
assert sms_row["month"] == "April"
|
assert sms_row["month"] == "April"
|
||||||
assert sms_row["notification_type"] == "sms"
|
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
|
# free allowance is 4, so (30 - 4) * 0.162
|
||||||
assert sms_row["cost"] == 4.212
|
assert sms_row["cost"] == 4.212
|
||||||
assert sms_row["free_allowance_used"] == 4
|
assert sms_row["free_allowance_used"] == 4
|
||||||
|
assert sms_row["charged_units"] == 26
|
||||||
|
|
||||||
|
|
||||||
def set_up_yearly_data():
|
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]['letter_total'] == 0
|
||||||
assert json_response[0]['cost'] == 0
|
assert json_response[0]['cost'] == 0
|
||||||
assert json_response[0]['free_allowance_used'] == 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]['notification_type'] == 'letter'
|
||||||
assert json_response[1]['billing_units'] == 275
|
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]['letter_total'] == 90.75
|
||||||
assert json_response[1]['cost'] == 90.75
|
assert json_response[1]['cost'] == 90.75
|
||||||
assert json_response[1]['free_allowance_used'] == 0
|
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]['notification_type'] == 'sms'
|
||||||
assert json_response[2]['billing_units'] == 825
|
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]['letter_total'] == 0
|
||||||
assert json_response[2]['cost'] == 13.3002
|
assert json_response[2]['cost'] == 13.3002
|
||||||
assert json_response[2]['free_allowance_used'] == 4
|
assert json_response[2]['free_allowance_used'] == 4
|
||||||
|
assert json_response[2]['charged_units'] == 821
|
||||||
|
|||||||
@@ -439,6 +439,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session):
|
|||||||
assert results[0].rate == Decimal('0')
|
assert results[0].rate == Decimal('0')
|
||||||
assert results[0].cost == Decimal('0')
|
assert results[0].cost == Decimal('0')
|
||||||
assert results[0].free_allowance_used == 0
|
assert results[0].free_allowance_used == 0
|
||||||
|
assert results[0].charged_units == 0
|
||||||
|
|
||||||
assert str(results[1].month) == "2016-04-01"
|
assert str(results[1].month) == "2016-04-01"
|
||||||
assert results[1].notification_type == 'letter'
|
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].rate == Decimal('0.30')
|
||||||
assert results[1].cost == Decimal('9')
|
assert results[1].cost == Decimal('9')
|
||||||
assert results[1].free_allowance_used == 0
|
assert results[1].free_allowance_used == 0
|
||||||
|
assert results[1].charged_units == 30
|
||||||
|
|
||||||
assert str(results[1].month) == "2016-04-01"
|
assert str(results[1].month) == "2016-04-01"
|
||||||
assert results[2].notification_type == 'letter'
|
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].rate == Decimal('0.33')
|
||||||
assert results[2].cost == Decimal('9.9')
|
assert results[2].cost == Decimal('9.9')
|
||||||
assert results[2].free_allowance_used == 0
|
assert results[2].free_allowance_used == 0
|
||||||
|
assert results[2].charged_units == 30
|
||||||
|
|
||||||
assert str(results[3].month) == "2016-04-01"
|
assert str(results[3].month) == "2016-04-01"
|
||||||
assert results[3].notification_type == 'sms'
|
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
|
# free allowance is 10, so (30 - 10) * 0.162
|
||||||
assert results[3].cost == Decimal('3.24')
|
assert results[3].cost == Decimal('3.24')
|
||||||
assert results[3].free_allowance_used == 10
|
assert results[3].free_allowance_used == 10
|
||||||
|
assert results[3].charged_units == 20
|
||||||
|
|
||||||
assert str(results[4].month) == "2016-05-01"
|
assert str(results[4].month) == "2016-05-01"
|
||||||
assert str(results[47].month) == "2017-03-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].rate == Decimal('0.33')
|
||||||
assert results[0].cost == Decimal('0.33')
|
assert results[0].cost == Decimal('0.33')
|
||||||
assert results[0].free_allowance_used == 0
|
assert results[0].free_allowance_used == 0
|
||||||
|
assert results[0].charged_units == 1
|
||||||
|
|
||||||
assert str(results[1].month) == "2018-05-01"
|
assert str(results[1].month) == "2018-05-01"
|
||||||
assert results[1].notification_type == 'letter'
|
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].rate == Decimal('0.36')
|
||||||
assert results[1].cost == Decimal('0.72')
|
assert results[1].cost == Decimal('0.72')
|
||||||
assert results[1].free_allowance_used == 0
|
assert results[1].free_allowance_used == 0
|
||||||
|
assert results[1].charged_units == 2
|
||||||
|
|
||||||
assert str(results[2].month) == "2018-05-01"
|
assert str(results[2].month) == "2018-05-01"
|
||||||
assert results[2].notification_type == 'sms'
|
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
|
# 1 free units on the 17th
|
||||||
assert results[2].cost == Decimal('0.045')
|
assert results[2].cost == Decimal('0.045')
|
||||||
assert results[2].free_allowance_used == 1
|
assert results[2].free_allowance_used == 1
|
||||||
|
assert results[2].charged_units == 3
|
||||||
|
|
||||||
assert str(results[3].month) == "2018-05-01"
|
assert str(results[3].month) == "2018-05-01"
|
||||||
assert results[3].notification_type == 'sms'
|
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
|
# 5 free units on the 16th
|
||||||
assert results[3].cost == Decimal('0')
|
assert results[3].cost == Decimal('0')
|
||||||
assert results[3].free_allowance_used == 5
|
assert results[3].free_allowance_used == 5
|
||||||
|
assert results[3].charged_units == 0
|
||||||
|
|
||||||
|
|
||||||
@freeze_time('2018-08-01 13:30:00')
|
@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].rate == Decimal('0')
|
||||||
assert results[0].cost == Decimal('0')
|
assert results[0].cost == Decimal('0')
|
||||||
assert results[0].free_allowance_used == 0
|
assert results[0].free_allowance_used == 0
|
||||||
|
assert results[0].charged_units == 0
|
||||||
|
|
||||||
assert results[1].notification_type == 'letter'
|
assert results[1].notification_type == 'letter'
|
||||||
assert results[1].notifications_sent == 365
|
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].rate == Decimal('0.3')
|
||||||
assert results[1].cost == Decimal('109.5')
|
assert results[1].cost == Decimal('109.5')
|
||||||
assert results[1].free_allowance_used == 0
|
assert results[1].free_allowance_used == 0
|
||||||
|
assert results[1].charged_units == 365
|
||||||
|
|
||||||
assert results[2].notification_type == 'letter'
|
assert results[2].notification_type == 'letter'
|
||||||
assert results[2].notifications_sent == 365
|
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].rate == Decimal('0.33')
|
||||||
assert results[2].cost == Decimal('120.45')
|
assert results[2].cost == Decimal('120.45')
|
||||||
assert results[2].free_allowance_used == 0
|
assert results[2].free_allowance_used == 0
|
||||||
|
assert results[2].charged_units == 365
|
||||||
|
|
||||||
assert results[3].notification_type == 'sms'
|
assert results[3].notification_type == 'sms'
|
||||||
assert results[3].notifications_sent == 365
|
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].rate == Decimal('0.162')
|
||||||
assert results[3].cost == Decimal('0')
|
assert results[3].cost == Decimal('0')
|
||||||
assert results[3].free_allowance_used == 365
|
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):
|
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].rate == Decimal('0.33')
|
||||||
assert results[0].cost == Decimal('0.33')
|
assert results[0].cost == Decimal('0.33')
|
||||||
assert results[0].free_allowance_used == 0
|
assert results[0].free_allowance_used == 0
|
||||||
|
assert results[0].charged_units == 1
|
||||||
|
|
||||||
assert results[1].notification_type == 'letter'
|
assert results[1].notification_type == 'letter'
|
||||||
assert results[1].notifications_sent == 2
|
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].rate == Decimal('0.36')
|
||||||
assert results[1].cost == Decimal('0.72')
|
assert results[1].cost == Decimal('0.72')
|
||||||
assert results[1].free_allowance_used == 0
|
assert results[1].free_allowance_used == 0
|
||||||
|
assert results[1].charged_units == 2
|
||||||
|
|
||||||
assert results[2].notification_type == 'sms'
|
assert results[2].notification_type == 'sms'
|
||||||
assert results[2].notifications_sent == 1
|
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
|
# 1 free unit on the 17th
|
||||||
assert results[2].cost == Decimal('0.045')
|
assert results[2].cost == Decimal('0.045')
|
||||||
assert results[2].free_allowance_used == 1
|
assert results[2].free_allowance_used == 1
|
||||||
|
assert results[2].charged_units == 3
|
||||||
|
|
||||||
assert results[3].notification_type == 'sms'
|
assert results[3].notification_type == 'sms'
|
||||||
assert results[3].notifications_sent == 2
|
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
|
# 5 free units on the 16th
|
||||||
assert results[3].cost == Decimal('0')
|
assert results[3].cost == Decimal('0')
|
||||||
assert results[3].free_allowance_used == 5
|
assert results[3].free_allowance_used == 5
|
||||||
|
assert results[3].charged_units == 0
|
||||||
|
|
||||||
|
|
||||||
def test_delete_billing_data(notify_db_session):
|
def test_delete_billing_data(notify_db_session):
|
||||||
|
|||||||
Reference in New Issue
Block a user