Add tests for sms breakdown adjusted free allowance

This commit is contained in:
Ken Tsang
2017-04-26 17:08:33 +01:00
parent 260dfb1e32
commit 79b4b37b0e
3 changed files with 174 additions and 48 deletions

View File

@@ -102,18 +102,19 @@ def template_history(service_id):
@user_has_permissions('manage_settings', admin_override=True)
def usage(service_id):
year, current_financial_year = requested_and_current_financial_year(request)
monthly_breakdown = get_free_paid_breakdown_for_billable_units(
year, service_api_client.get_billable_units(service_id, year))
return render_template(
'views/usage.html',
months=list(get_free_paid_breakdown_for_billable_units(
year, service_api_client.get_billable_units(service_id, year)
)),
months=list(monthly_breakdown),
selected_year=year,
years=get_tuples_of_financial_years(
partial(url_for, '.usage', service_id=service_id),
start=current_financial_year - 1,
end=current_financial_year + 1,
),
**calculate_usage(service_api_client.get_service_usage(service_id, year)['data'])
# **calculate_usage(dict(monthly_breakdown))
**calculate_usage(service_api_client.get_service_usage(service_id, year)['data'], monthly_breakdown)
)
@@ -201,21 +202,24 @@ def get_dashboard_totals(statistics):
return statistics
def calculate_usage(usage):
def calculate_usage(usage, monthly_breakdown):
# TODO: Don't hardcode these - get em from the API
sms_free_allowance = 250000
sms_rate = 0.0165
sms_sent = usage.get('sms_count', 0)
sms_sent = get_sum_units(usage.get('sms_breakdown', []))
emails_sent = usage.get('email_count', 0)
sms_breakdown = get_sms_breakdown_adjusted_free_allowance(
usage.get('sms_breakdown', []), sms_free_allowance)
return {
'emails_sent': emails_sent,
'sms_free_allowance': sms_free_allowance,
'sms_sent': sms_sent,
'sms_allowance_remaining': max(0, (sms_free_allowance - sms_sent)),
'sms_chargeable': max(0, sms_sent - sms_free_allowance),
'sms_rate': sms_rate
'sms_rate': sms_rate,
'sms_breakdown': sms_breakdown,
'sms_free_units_used': usage.get('free_units_used', 0)
}
@@ -262,18 +266,23 @@ def get_months_for_year(start, end, year):
return [datetime(year, month, 1) for month in range(start, end)]
def get_total_units_for_month(monthly_usage):
total = 0
for rate_group in monthly_usage:
total += rate_group['units'] * rate_group['multiplier']
return total
def get_sum_billable_units(usage):
return sum(rate['units'] * rate['multiplier'] for rate in usage)
def get_sum_units(usage):
return sum(rate['units'] for rate in usage)
def get_sum_free_units(usage):
return sum(rate.get('free_units', 0) * rate['multiplier'] for rate in usage)
def get_free_paid_breakdown_for_billable_units(year, billable_units):
cumulative = 0
for month in get_months_for_financial_year(year):
previous_cumulative = cumulative
monthly_usage = get_total_units_for_month(billable_units.get(month, []))
monthly_usage = get_sum_billable_units(billable_units.get(month, []))
cumulative += monthly_usage
breakdown = get_free_paid_breakdown_for_month(
cumulative, previous_cumulative, billable_units.get(month, [])
@@ -282,35 +291,40 @@ def get_free_paid_breakdown_for_billable_units(year, billable_units):
'name': month,
'paid': breakdown['paid'],
'free': breakdown['free'],
'rate_groups': breakdown['rate_groups']
'sms_breakdown': breakdown.get('sms_breakdown', []),
'free_units_used': get_sum_free_units(breakdown.get('sms_breakdown', []))
}
def get_rate_groups(monthly_usage, free_allowance=0):
rate_groups = []
def get_sms_breakdown_adjusted_free_allowance(breakdown_list, free_allowance=0):
sms_breakdown = []
for rate_group in monthly_usage:
for breakdown in breakdown_list:
free_units = 0
units = rate_group["units"]
if free_allowance > 0:
units = rate_group["units"] * rate_group["multiplier"] - free_allowance
if units < 0:
free_units = rate_group["units"] * rate_group["multiplier"]
free_allowance = abs(units)
units = 0
normalised_units = breakdown["units"] * breakdown["multiplier"]
billable_units = normalised_units - free_allowance
if billable_units <= 0:
free_units = breakdown["units"]
free_allowance = abs(billable_units)
else:
free_units = free_allowance
free_allowance = 0
free_units = int(free_allowance / breakdown["multiplier"])
rate_group = {
"international": rate_group["international"],
if free_allowance < normalised_units:
free_allowance = 0
else:
free_allowance -= normalised_units
adj_breakdown = {
"international": breakdown["international"],
"free_units": free_units,
"units": units,
"multiplier": rate_group["multiplier"]
"units": breakdown["units"] - free_units,
"multiplier": breakdown["multiplier"]
}
rate_groups.append(rate_group)
sms_breakdown.append(adj_breakdown)
return rate_groups
return sms_breakdown
def get_free_paid_breakdown_for_month(
@@ -320,25 +334,25 @@ def get_free_paid_breakdown_for_month(
):
allowance = 250000
total_monthly_units = get_total_units_for_month(monthly_usage)
total_monthly_billable_units = get_sum_billable_units(monthly_usage)
if cumulative < allowance:
return {
'paid': 0,
'free': total_monthly_units,
'free': total_monthly_billable_units,
}
elif previous_cumulative < allowance:
remaining_allowance = allowance - previous_cumulative
return {
'paid': total_monthly_units - remaining_allowance,
'paid': total_monthly_billable_units - remaining_allowance,
'free': remaining_allowance,
'rate_groups': get_rate_groups(monthly_usage, remaining_allowance)
'sms_breakdown': get_sms_breakdown_adjusted_free_allowance(monthly_usage, remaining_allowance)
}
else:
return {
'paid': total_monthly_units,
'paid': total_monthly_billable_units,
'free': 0,
'rate_groups': get_rate_groups(monthly_usage)
'sms_breakdown': get_sms_breakdown_adjusted_free_allowance(monthly_usage)
}

View File

@@ -11,6 +11,7 @@ from app.main.views.dashboard import (
get_dashboard_totals,
format_monthly_stats_to_list,
get_free_paid_breakdown_for_billable_units,
get_sms_breakdown_adjusted_free_allowance,
aggregate_status_types,
format_template_stats_to_list,
get_tuples_of_financial_years,
@@ -301,20 +302,17 @@ def test_international_usage_page(
nav = page.find('ul', {'class': 'pill', 'role': 'tablist'})
nav_links = nav.find_all('a')
assert '252,390' in cols[1].text
assert '252,180' in cols[1].text
assert 'Text messages' in cols[1].text
table = page.find('table').text.strip()
print(table)
assert '249,900 UK free text messages' in table
assert '100 international free text messages' in table
assert '900 international text messages at 1.65p' in table
assert '250000 free allowance used' in table
assert '20 international text at 4.95p' in table
assert 'April' in table
assert 'March' in table
assert '£0.99' in table
assert '£20.30' in table
assert '£19.14' in table
def test_usage_page_with_year_argument(
@@ -652,6 +650,89 @@ def test_get_free_paid_breakdown_for_billable_units(now, expected_number_of_mont
][:expected_number_of_months]
@pytest.mark.parametrize(
'usage, expected_breakdown', [
(
[
{"international": False, "multiplier": 1, "units": 240000},
{"international": True, "multiplier": 2, "units": 20},
],
[
{'units': 0, 'free_units': 240000, 'international': False, 'multiplier': 1},
{'units': 0, 'free_units': 20, 'international': True, 'multiplier': 2}
]
),
(
[
{"international": False, "multiplier": 1, "units": 250000},
{"international": True, "multiplier": 2, "units": 20},
],
[
{'units': 0, 'free_units': 250000, 'international': False, 'multiplier': 1},
{'units': 20, 'free_units': 0, 'international': True, 'multiplier': 2}
]
),
(
[
{"international": False, "multiplier": 1, "units": 300000},
{"international": True, "multiplier": 2, "units": 20},
],
[
{'units': 50000, 'free_units': 250000, 'international': False, 'multiplier': 1},
{'units': 20, 'free_units': 0, 'international': True, 'multiplier': 2}
]
),
(
[
{"international": False, "rate": 1.65, "multiplier": 1, "units": 249700},
{"international": True, "rate": 1.65, "multiplier": 1, "units": 100},
{"international": True, "rate": 1.65, "multiplier": 2, "units": 100},
{"international": True, "rate": 1.65, "multiplier": 3, "units": 20},
],
[
{'international': False, 'free_units': 249700, 'units': 0, 'multiplier': 1},
{'international': True, 'free_units': 100, 'units': 0, 'multiplier': 1},
{'international': True, 'free_units': 100, 'units': 0, 'multiplier': 2},
{'international': True, 'free_units': 0, 'units': 20, 'multiplier': 3}
]
),
(
[
{"international": False, "rate": 1.65, "multiplier": 1, "units": 249600},
{"international": True, "rate": 1.65, "multiplier": 1, "units": 100},
{"international": True, "rate": 1.65, "multiplier": 2, "units": 100},
{"international": True, "rate": 1.65,"multiplier": 3, "units": 20},
],
[
{'units': 0, 'free_units': 249600, 'international': False, 'multiplier': 1},
{'units': 0, 'free_units': 100, 'international': True, 'multiplier': 1},
{'units': 0, 'free_units': 100, 'international': True, 'multiplier': 2},
{'units': 0, 'free_units': 20, 'international': True, 'multiplier': 3}
]
),
(
[
{"international": False, "rate": 1.65, "multiplier": 1, "units": 249800},
{"international": True, "rate": 1.65, "multiplier": 1, "units": 100},
{"international": True, "rate": 1.65, "multiplier": 2, "units": 100},
{"international": True, "rate": 1.65,"multiplier": 3, "units": 20},
],
[
{'units': 0, 'free_units': 249800, 'international': False, 'multiplier': 1},
{'units': 0, 'free_units': 100, 'international': True, 'multiplier': 1},
{'units': 50, 'free_units': 50, 'international': True, 'multiplier': 2},
{'units': 20, 'free_units': 0, 'international': True, 'multiplier': 3}
]
)
]
)
def test_get_sms_breakdown_adjusted_free_allowance(usage, expected_breakdown):
free_allowance = 250000
breakdown = get_sms_breakdown_adjusted_free_allowance(usage, free_allowance)
print(breakdown)
assert breakdown == expected_breakdown
def test_format_template_stats_to_list_with_no_stats():
assert list(format_template_stats_to_list({})) == []

View File

@@ -1338,9 +1338,40 @@ def mock_get_billable_units(mocker):
@pytest.fixture(scope='function')
def mock_get_international_usage(mocker, service_one, fake_uuid):
# def _get_usage(service_id, year=None):
# return {'data': {
# "sms_count": 252390,
# "email_count": 0
# }}
def _get_usage(service_id, year=None):
return {'data': {
"sms_count": 252390,
"sms_breakdown": [
{
"international": False,
"rate": 1.65,
"multiplier": 1,
"units": 250900
},
{
"international": True,
"rate": 1.65,
"multiplier": 1,
"units": 1100
},
{
"international": True,
"rate": 1.65,
"multiplier": 2,
"units": 150
},
{
"international": True,
"rate": 1.65,
"multiplier": 3,
"units": 30
}
],
"email_count": 0
}}
@@ -1357,13 +1388,13 @@ def mock_get_billable_international_units(mocker):
"international": False,
"rate": 1.65,
"multiplier": 1,
"units": 249900
"units": 249700
},
{
"international": True,
"rate": 1.65,
"multiplier": 1,
"units": 1000
"units": 100
},
{
"international": True,