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:
Ben Thorner
2022-04-29 17:44:27 +01:00
parent f6dc30665f
commit d798a0d60f
4 changed files with 105 additions and 86 deletions

View File

@@ -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 (

View File

@@ -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
) }}

View File

@@ -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]

View File

@@ -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,
},
]