mirror of
https://github.com/GSA/notifications-api.git
synced 2025-12-20 15:31:15 -05:00
Add new total_letters field to the billing report data
This adds total_letters to the data that is returned by the `/platform-stats/data-for-billing-report` endpoint so that we can add total letters as a column in the CSV file that can be downloaded.
This commit is contained in:
@@ -114,12 +114,13 @@ def fetch_sms_billing_for_all_services(start_date, end_date):
|
|||||||
return query.all()
|
return query.all()
|
||||||
|
|
||||||
|
|
||||||
def fetch_letter_costs_for_all_services(start_date, end_date):
|
def fetch_letter_costs_and_totals_for_all_services(start_date, end_date):
|
||||||
query = db.session.query(
|
query = db.session.query(
|
||||||
Organisation.name.label("organisation_name"),
|
Organisation.name.label("organisation_name"),
|
||||||
Organisation.id.label("organisation_id"),
|
Organisation.id.label("organisation_id"),
|
||||||
Service.name.label("service_name"),
|
Service.name.label("service_name"),
|
||||||
Service.id.label("service_id"),
|
Service.id.label("service_id"),
|
||||||
|
func.sum(FactBilling.notifications_sent).label("total_letters"),
|
||||||
func.sum(FactBilling.notifications_sent * FactBilling.rate).label("letter_cost")
|
func.sum(FactBilling.notifications_sent * FactBilling.rate).label("letter_cost")
|
||||||
).select_from(
|
).select_from(
|
||||||
Service
|
Service
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from flask import Blueprint, jsonify, request
|
|||||||
from app.dao.date_util import get_financial_year_for_datetime
|
from app.dao.date_util import get_financial_year_for_datetime
|
||||||
from app.dao.fact_billing_dao import (
|
from app.dao.fact_billing_dao import (
|
||||||
fetch_billing_details_for_all_services,
|
fetch_billing_details_for_all_services,
|
||||||
fetch_letter_costs_for_all_services,
|
fetch_letter_costs_and_totals_for_all_services,
|
||||||
fetch_letter_line_items_for_all_services,
|
fetch_letter_line_items_for_all_services,
|
||||||
fetch_sms_billing_for_all_services,
|
fetch_sms_billing_for_all_services,
|
||||||
)
|
)
|
||||||
@@ -67,7 +67,7 @@ def get_data_for_billing_report():
|
|||||||
start_date, end_date = validate_date_range_is_within_a_financial_year(start_date, end_date)
|
start_date, end_date = validate_date_range_is_within_a_financial_year(start_date, end_date)
|
||||||
|
|
||||||
sms_costs = fetch_sms_billing_for_all_services(start_date, end_date)
|
sms_costs = fetch_sms_billing_for_all_services(start_date, end_date)
|
||||||
letter_costs = fetch_letter_costs_for_all_services(start_date, end_date)
|
letter_overview = fetch_letter_costs_and_totals_for_all_services(start_date, end_date)
|
||||||
letter_breakdown = fetch_letter_line_items_for_all_services(start_date, end_date)
|
letter_breakdown = fetch_letter_line_items_for_all_services(start_date, end_date)
|
||||||
|
|
||||||
lb_by_service = [
|
lb_by_service = [
|
||||||
@@ -85,26 +85,31 @@ def get_data_for_billing_report():
|
|||||||
"service_name": s.service_name,
|
"service_name": s.service_name,
|
||||||
"sms_cost": float(s.sms_cost),
|
"sms_cost": float(s.sms_cost),
|
||||||
"sms_fragments": s.chargeable_billable_sms,
|
"sms_fragments": s.chargeable_billable_sms,
|
||||||
|
"total_letters": 0,
|
||||||
"letter_cost": 0,
|
"letter_cost": 0,
|
||||||
"letter_breakdown": ""
|
"letter_breakdown": ""
|
||||||
}
|
}
|
||||||
combined[s.service_id] = entry
|
combined[s.service_id] = entry
|
||||||
|
|
||||||
for letter_cost in letter_costs:
|
for data in letter_overview:
|
||||||
if letter_cost.service_id in combined:
|
if data.service_id in combined:
|
||||||
combined[letter_cost.service_id].update({'letter_cost': float(letter_cost.letter_cost)})
|
combined[data.service_id].update(
|
||||||
|
{'total_letters': data.total_letters, 'letter_cost': float(data.letter_cost)}
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
letter_entry = {
|
letter_entry = {
|
||||||
"organisation_id": str(letter_cost.organisation_id) if letter_cost.organisation_id else "",
|
"organisation_id": str(data.organisation_id) if data.organisation_id else "",
|
||||||
"organisation_name": letter_cost.organisation_name or "",
|
"organisation_name": data.organisation_name or "",
|
||||||
"service_id": str(letter_cost.service_id),
|
"service_id": str(data.service_id),
|
||||||
"service_name": letter_cost.service_name,
|
"service_name": data.service_name,
|
||||||
"sms_cost": 0,
|
"sms_cost": 0,
|
||||||
"sms_fragments": 0,
|
"sms_fragments": 0,
|
||||||
"letter_cost": float(letter_cost.letter_cost),
|
"total_letters": data.total_letters,
|
||||||
|
"letter_cost": float(data.letter_cost),
|
||||||
"letter_breakdown": ""
|
"letter_breakdown": ""
|
||||||
}
|
}
|
||||||
combined[letter_cost.service_id] = letter_entry
|
combined[data.service_id] = letter_entry
|
||||||
for service_id, breakdown in lb_by_service:
|
for service_id, breakdown in lb_by_service:
|
||||||
combined[service_id]['letter_breakdown'] += (breakdown + '\n')
|
combined[service_id]['letter_breakdown'] += (breakdown + '\n')
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from app.dao.fact_billing_dao import (
|
|||||||
delete_billing_data_for_service_for_day,
|
delete_billing_data_for_service_for_day,
|
||||||
fetch_billing_data_for_day,
|
fetch_billing_data_for_day,
|
||||||
fetch_billing_totals_for_year,
|
fetch_billing_totals_for_year,
|
||||||
fetch_letter_costs_for_all_services,
|
fetch_letter_costs_and_totals_for_all_services,
|
||||||
fetch_letter_line_items_for_all_services,
|
fetch_letter_line_items_for_all_services,
|
||||||
fetch_monthly_billing_for_year,
|
fetch_monthly_billing_for_year,
|
||||||
fetch_sms_billing_for_all_services,
|
fetch_sms_billing_for_all_services,
|
||||||
@@ -628,26 +628,26 @@ def test_fetch_sms_billing_for_all_services_without_an_organisation_appears(noti
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_fetch_letter_costs_for_all_services(notify_db_session):
|
def test_fetch_letter_costs_and_totals_for_all_services(notify_db_session):
|
||||||
fixtures = set_up_usage_data(datetime(2019, 6, 1))
|
fixtures = set_up_usage_data(datetime(2019, 6, 1))
|
||||||
|
|
||||||
results = fetch_letter_costs_for_all_services(datetime(2019, 6, 1), datetime(2019, 9, 30))
|
results = fetch_letter_costs_and_totals_for_all_services(datetime(2019, 6, 1), datetime(2019, 9, 30))
|
||||||
|
|
||||||
assert len(results) == 3
|
assert len(results) == 3
|
||||||
assert results[0] == (
|
assert results[0] == (
|
||||||
fixtures["org_1"].name, fixtures["org_1"].id,
|
fixtures["org_1"].name, fixtures["org_1"].id,
|
||||||
fixtures["service_1_sms_and_letter"].name, fixtures["service_1_sms_and_letter"].id,
|
fixtures["service_1_sms_and_letter"].name, fixtures["service_1_sms_and_letter"].id,
|
||||||
Decimal('3.40')
|
8, Decimal('3.40')
|
||||||
)
|
)
|
||||||
assert results[1] == (
|
assert results[1] == (
|
||||||
fixtures["org_for_service_with_letters"].name, fixtures["org_for_service_with_letters"].id,
|
fixtures["org_for_service_with_letters"].name, fixtures["org_for_service_with_letters"].id,
|
||||||
fixtures["service_with_letters"].name, fixtures["service_with_letters"].id,
|
fixtures["service_with_letters"].name, fixtures["service_with_letters"].id,
|
||||||
Decimal('14.00')
|
22, Decimal('14.00')
|
||||||
)
|
)
|
||||||
assert results[2] == (
|
assert results[2] == (
|
||||||
None, None,
|
None, None,
|
||||||
fixtures["service_with_letters_without_org"].name, fixtures["service_with_letters_without_org"].id,
|
fixtures["service_with_letters_without_org"].name, fixtures["service_with_letters_without_org"].id,
|
||||||
Decimal('24.45')
|
18, Decimal('24.45')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ def test_get_data_for_billing_report(notify_db_session, admin_request):
|
|||||||
assert response[0]["service_id"] == str(fixtures["service_1_sms_and_letter"].id)
|
assert response[0]["service_id"] == str(fixtures["service_1_sms_and_letter"].id)
|
||||||
assert response[0]["sms_cost"] == 0
|
assert response[0]["sms_cost"] == 0
|
||||||
assert response[0]["sms_fragments"] == 0
|
assert response[0]["sms_fragments"] == 0
|
||||||
|
assert response[0]["total_letters"] == 8
|
||||||
assert response[0]["letter_cost"] == 3.40
|
assert response[0]["letter_cost"] == 3.40
|
||||||
assert response[0]["letter_breakdown"] == "6 second class letters at 45p\n2 first class letters at 35p\n"
|
assert response[0]["letter_breakdown"] == "6 second class letters at 45p\n2 first class letters at 35p\n"
|
||||||
assert response[0]["purchase_order_number"] == "service purchase order number"
|
assert response[0]["purchase_order_number"] == "service purchase order number"
|
||||||
@@ -152,6 +153,7 @@ def test_get_data_for_billing_report(notify_db_session, admin_request):
|
|||||||
assert response[1]["service_id"] == str(fixtures["service_with_letters"].id)
|
assert response[1]["service_id"] == str(fixtures["service_with_letters"].id)
|
||||||
assert response[1]["sms_cost"] == 0
|
assert response[1]["sms_cost"] == 0
|
||||||
assert response[1]["sms_fragments"] == 0
|
assert response[1]["sms_fragments"] == 0
|
||||||
|
assert response[1]["total_letters"] == 22
|
||||||
assert response[1]["letter_cost"] == 14
|
assert response[1]["letter_cost"] == 14
|
||||||
assert response[1]["letter_breakdown"] == "20 second class letters at 65p\n2 first class letters at 50p\n"
|
assert response[1]["letter_breakdown"] == "20 second class letters at 65p\n2 first class letters at 50p\n"
|
||||||
assert response[1]["purchase_order_number"] == "org3 purchase order number"
|
assert response[1]["purchase_order_number"] == "org3 purchase order number"
|
||||||
@@ -163,6 +165,7 @@ def test_get_data_for_billing_report(notify_db_session, admin_request):
|
|||||||
assert response[2]["service_id"] == str(fixtures["service_with_sms_without_org"].id)
|
assert response[2]["service_id"] == str(fixtures["service_with_sms_without_org"].id)
|
||||||
assert response[2]["sms_cost"] == 0.33
|
assert response[2]["sms_cost"] == 0.33
|
||||||
assert response[2]["sms_fragments"] == 3
|
assert response[2]["sms_fragments"] == 3
|
||||||
|
assert response[2]["total_letters"] == 0
|
||||||
assert response[2]["letter_cost"] == 0
|
assert response[2]["letter_cost"] == 0
|
||||||
assert response[2]["letter_breakdown"] == ""
|
assert response[2]["letter_breakdown"] == ""
|
||||||
assert response[2]["purchase_order_number"] == "sms purchase order number"
|
assert response[2]["purchase_order_number"] == "sms purchase order number"
|
||||||
@@ -174,6 +177,7 @@ def test_get_data_for_billing_report(notify_db_session, admin_request):
|
|||||||
assert response[3]["service_id"] == str(fixtures["service_with_letters_without_org"].id)
|
assert response[3]["service_id"] == str(fixtures["service_with_letters_without_org"].id)
|
||||||
assert response[3]["sms_cost"] == 0
|
assert response[3]["sms_cost"] == 0
|
||||||
assert response[3]["sms_fragments"] == 0
|
assert response[3]["sms_fragments"] == 0
|
||||||
|
assert response[3]["total_letters"] == 18
|
||||||
assert response[3]["letter_cost"] == 24.45
|
assert response[3]["letter_cost"] == 24.45
|
||||||
assert response[3]["letter_breakdown"] == (
|
assert response[3]["letter_breakdown"] == (
|
||||||
"2 second class letters at 35p\n1 first class letters at 50p\n15 international letters at £1.55\n"
|
"2 second class letters at 35p\n1 first class letters at 50p\n15 international letters at £1.55\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user