mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-14 10:58:58 -04:00
Replace manual SMS monthly calculations with API
This starts using the sms_{cost, charged, free_allowance_used}
fields in the new API to replace the "get_free_paid_breakdown"
function we had before, which could not support multiple rates.
In order to use "get_free_paid_breakdown" the calling method had
to store a "cumulative" variable to calculate the free allowance
used so far, which is now done by the API.
To calculate the data for conftest.py, I had to start from the
bottom ("April") and manually calculate the free allowance used
to emulate the API - this is what "cumulative" used to do.
This commit is contained in:
@@ -139,11 +139,7 @@ def usage(service_id):
|
||||
|
||||
return render_template(
|
||||
'views/usage.html',
|
||||
months=list(get_monthly_usage_breakdown(
|
||||
year,
|
||||
free_sms_allowance,
|
||||
units
|
||||
)),
|
||||
months=list(get_monthly_usage_breakdown(year, units)),
|
||||
selected_year=year,
|
||||
years=get_tuples_of_financial_years(
|
||||
partial(url_for, '.usage', service_id=service_id),
|
||||
@@ -398,19 +394,19 @@ def get_usage_breakdown_by_type(usage, notification_type):
|
||||
return [row for row in usage if row['notification_type'] == notification_type]
|
||||
|
||||
|
||||
def get_monthly_usage_breakdown(year, free_sms_fragment_limit, monthly_usage):
|
||||
cumulative = 0
|
||||
def get_monthly_usage_breakdown(year, monthly_usage):
|
||||
sms = get_usage_breakdown_by_type(monthly_usage, 'sms')
|
||||
letters = get_usage_breakdown_by_type(monthly_usage, 'letter')
|
||||
|
||||
for month in get_months_for_financial_year(year):
|
||||
monthly_sms = [row for row in sms if row['month'] == month]
|
||||
previous_cumulative = cumulative
|
||||
monthly_chargeable_units = sum(row['billing_units'] for row in monthly_sms)
|
||||
cumulative += monthly_chargeable_units
|
||||
sms_breakdown = get_free_paid_breakdown_for_month(
|
||||
free_sms_fragment_limit, cumulative, previous_cumulative, monthly_sms
|
||||
)
|
||||
sms_charged = sum(row['sms_charged'] for row in monthly_sms)
|
||||
sms_free_allowance_used = sum(row['sms_free_allowance_used'] for row in monthly_sms)
|
||||
sms_cost = sum(row['sms_cost'] for row in monthly_sms)
|
||||
# makes the assumption that there is either no item in `monthly_sms` because they
|
||||
# have not sent any SMS or that they have sent SMS and that there is only a single
|
||||
# item in `monthly_sms` because they have only been sent at a single rate
|
||||
sms_rate = monthly_sms[0]['rate'] if len(monthly_sms) else 0
|
||||
|
||||
monthly_letters = [row for row in letters if row['month'] == month]
|
||||
letter_breakdown = format_letter_details_for_month(monthly_letters)
|
||||
@@ -422,9 +418,10 @@ def get_monthly_usage_breakdown(year, free_sms_fragment_limit, monthly_usage):
|
||||
'month': month,
|
||||
'letter_cost': letter_cost,
|
||||
'letter_breakdown': letter_breakdown,
|
||||
'sms_charged': sms_breakdown['paid'],
|
||||
'sms_free_allowance_used': sms_breakdown['free'],
|
||||
'sms_rate': sms_breakdown['sms_rate'],
|
||||
'sms_charged': sms_charged,
|
||||
'sms_free_allowance_used': sms_free_allowance_used,
|
||||
'sms_rate': sms_rate,
|
||||
'sms_cost': sms_cost,
|
||||
}
|
||||
|
||||
|
||||
@@ -464,42 +461,6 @@ def get_postage_description(postage):
|
||||
return 'international'
|
||||
|
||||
|
||||
def get_free_paid_breakdown_for_month(
|
||||
free_sms_fragment_limit,
|
||||
cumulative,
|
||||
previous_cumulative,
|
||||
monthly_usage
|
||||
):
|
||||
allowance = free_sms_fragment_limit
|
||||
|
||||
# makes the assumption that there is either no item in `monthly_usage` because they have not sent any SMS
|
||||
# or that they have sent SMS and that there is only a single item in `monthly_usage` because they have only
|
||||
# been sent at a single rate during the month
|
||||
sms_rate = monthly_usage[0]['rate'] if len(monthly_usage) else 0
|
||||
|
||||
total_monthly_billing_units = sum(row['billing_units'] for row in monthly_usage)
|
||||
|
||||
if cumulative < allowance:
|
||||
return {
|
||||
'paid': 0,
|
||||
'free': total_monthly_billing_units,
|
||||
'sms_rate': sms_rate,
|
||||
}
|
||||
elif previous_cumulative < allowance:
|
||||
remaining_allowance = allowance - previous_cumulative
|
||||
return {
|
||||
'paid': total_monthly_billing_units - remaining_allowance,
|
||||
'free': remaining_allowance,
|
||||
'sms_rate': sms_rate,
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'paid': total_monthly_billing_units,
|
||||
'free': 0,
|
||||
'sms_rate': sms_rate,
|
||||
}
|
||||
|
||||
|
||||
def requested_and_current_financial_year(request):
|
||||
try:
|
||||
return (
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
{% endcall %}
|
||||
{% call field(align='left') %}
|
||||
{{ big_number(
|
||||
(item.sms_rate * item.sms_charged) + item.letter_cost,
|
||||
item.sms_cost + item.letter_cost,
|
||||
currency="£",
|
||||
smallest=True
|
||||
) }}
|
||||
|
||||
@@ -1578,28 +1578,53 @@ def test_aggregate_status_types(dict_in, expected_failed, expected_requested):
|
||||
]
|
||||
)
|
||||
def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
sms_allowance = 250000
|
||||
with now:
|
||||
breakdown = get_monthly_usage_breakdown(
|
||||
2016, sms_allowance, [
|
||||
{
|
||||
'month': 'April', 'international': False, 'rate_multiplier': 1,
|
||||
'notification_type': 'sms', 'rate': 1.65, 'billing_units': 100000
|
||||
},
|
||||
{
|
||||
'month': 'May', 'international': False, 'rate_multiplier': 1,
|
||||
'notification_type': 'sms', 'rate': 1.65, 'billing_units': 100000
|
||||
},
|
||||
{
|
||||
'month': 'June', 'international': False, 'rate_multiplier': 1,
|
||||
'notification_type': 'sms', 'rate': 1.71, 'billing_units': 100000
|
||||
},
|
||||
{
|
||||
'month': 'February', 'international': False, 'rate_multiplier': 1,
|
||||
'notification_type': 'sms', 'rate': 1.71, 'billing_units': 2000
|
||||
},
|
||||
]
|
||||
)
|
||||
breakdown = get_monthly_usage_breakdown(2016, [
|
||||
{
|
||||
'month': 'April',
|
||||
'international': False,
|
||||
'rate_multiplier': 1,
|
||||
'notification_type': 'sms',
|
||||
'rate': 1.65,
|
||||
'billing_units': 100000,
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 100000,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'month': 'May',
|
||||
'international': False,
|
||||
'rate_multiplier': 1,
|
||||
'notification_type': 'sms',
|
||||
'rate': 1.65,
|
||||
'billing_units': 100000,
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 100000,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'month': 'June',
|
||||
'international': False,
|
||||
'rate_multiplier': 1,
|
||||
'notification_type': 'sms',
|
||||
'rate': 1.71,
|
||||
'billing_units': 100000,
|
||||
'sms_charged': 50000,
|
||||
'sms_free_allowance_used': 50000,
|
||||
'sms_cost': 85500,
|
||||
},
|
||||
{
|
||||
'month': 'February',
|
||||
'international': False,
|
||||
'rate_multiplier': 1,
|
||||
'notification_type': 'sms',
|
||||
'rate': 1.71,
|
||||
'billing_units': 2000,
|
||||
'sms_charged': 2000,
|
||||
'sms_free_allowance_used': 0,
|
||||
'sms_cost': 3420,
|
||||
},
|
||||
])
|
||||
|
||||
assert list(breakdown) == [
|
||||
{
|
||||
@@ -1608,7 +1633,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 1.65,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 100000,
|
||||
@@ -1616,7 +1642,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 1.65,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 50000,
|
||||
@@ -1624,7 +1651,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 50000,
|
||||
'sms_rate': 1.71,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 85500,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1632,7 +1660,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1640,7 +1669,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1648,7 +1678,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1656,7 +1687,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1664,7 +1696,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1672,7 +1705,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1680,7 +1714,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1688,7 +1723,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 2000,
|
||||
'sms_rate': 1.71,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 3420,
|
||||
},
|
||||
{
|
||||
'sms_free_allowance_used': 0,
|
||||
@@ -1696,7 +1732,8 @@ def test_get_monthly_usage_breakdown(now, expected_number_of_months):
|
||||
'sms_charged': 0,
|
||||
'sms_rate': 0,
|
||||
'letter_cost': 0,
|
||||
'letter_breakdown': []
|
||||
'letter_breakdown': [],
|
||||
'sms_cost': 0,
|
||||
},
|
||||
][:expected_number_of_months]
|
||||
|
||||
|
||||
@@ -2364,6 +2364,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.017,
|
||||
'billing_units': 1230,
|
||||
'postage': 'none',
|
||||
'sms_charged': 1230,
|
||||
'sms_free_allowance_used': 0,
|
||||
'sms_cost': 20.91,
|
||||
},
|
||||
{
|
||||
'month': 'February',
|
||||
@@ -2371,6 +2374,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.0165,
|
||||
'billing_units': 1100,
|
||||
'postage': 'none',
|
||||
'sms_charged': 960,
|
||||
'sms_free_allowance_used': 140,
|
||||
'sms_cost': 15.84,
|
||||
},
|
||||
{
|
||||
'month': 'February',
|
||||
@@ -2378,6 +2384,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.31,
|
||||
'billing_units': 10,
|
||||
'postage': 'second',
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 0,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'month': 'February',
|
||||
@@ -2385,6 +2394,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.33,
|
||||
'billing_units': 5,
|
||||
'postage': 'first',
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 0,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'month': 'February',
|
||||
@@ -2392,6 +2404,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.84,
|
||||
'billing_units': 3,
|
||||
'postage': 'europe',
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 0,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'month': 'February',
|
||||
@@ -2399,6 +2414,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.84,
|
||||
'billing_units': 7,
|
||||
'postage': 'rest-of-world',
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 0,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
{
|
||||
'month': 'April',
|
||||
@@ -2406,6 +2424,9 @@ def mock_get_monthly_usage_for_service(mocker):
|
||||
'rate': 0.017,
|
||||
'billing_units': 249860,
|
||||
'postage': 'none',
|
||||
'sms_charged': 0,
|
||||
'sms_free_allowance_used': 249860,
|
||||
'sms_cost': 0,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user