diff --git a/app/billing/billing_schemas.py b/app/billing/billing_schemas.py index d03fa68e4..d77f718d5 100644 --- a/app/billing/billing_schemas.py +++ b/app/billing/billing_schemas.py @@ -17,7 +17,9 @@ def serialize_ft_billing_remove_emails(rows): { "month": (datetime.strftime(row.month, "%B")), "notification_type": row.notification_type, + # TEMPORARY: while we migrate to "chargeable_units" in the Admin app "billing_units": row.billable_units, + "chargeable_units": row.chargeable_units, "rate": float(row.rate), "postage": row.postage, } diff --git a/app/dao/fact_billing_dao.py b/app/dao/fact_billing_dao.py index a35782c4d..df2012123 100644 --- a/app/dao/fact_billing_dao.py +++ b/app/dao/fact_billing_dao.py @@ -224,7 +224,7 @@ def fetch_billing_totals_for_year(service_id, year): def fetch_monthly_billing_for_year(service_id, year): - year_start, year_end = get_financial_year_dates(year) + _, year_end = get_financial_year_dates(year) today = convert_utc_to_bst(datetime.utcnow()).date() # if year end date is less than today, we are calculating for data in the past and have no need for deltas. @@ -233,57 +233,42 @@ def fetch_monthly_billing_for_year(service_id, year): for d in data: update_fact_billing(data=d, process_day=today) - email_and_letters = db.session.query( - func.date_trunc('month', FactBilling.bst_date).cast(Date).label("month"), - func.sum(FactBilling.notifications_sent).label("notifications_sent"), - func.sum(FactBilling.notifications_sent).label("billable_units"), - FactBilling.rate.label('rate'), - FactBilling.notification_type.label('notification_type'), - FactBilling.postage - ).filter( - FactBilling.service_id == service_id, - FactBilling.bst_date >= year_start, - FactBilling.bst_date <= year_end, - FactBilling.notification_type.in_([EMAIL_TYPE, LETTER_TYPE]) - ).group_by( - 'month', - FactBilling.rate, - FactBilling.notification_type, - FactBilling.postage - ) - - sms = db.session.query( - func.date_trunc('month', FactBilling.bst_date).cast(Date).label("month"), - func.sum(FactBilling.notifications_sent).label("notifications_sent"), - func.sum(FactBilling.billable_units * FactBilling.rate_multiplier).label("billable_units"), - FactBilling.rate, - FactBilling.notification_type, - FactBilling.postage - ).filter( - FactBilling.service_id == service_id, - FactBilling.bst_date >= year_start, - FactBilling.bst_date <= year_end, - FactBilling.notification_type == SMS_TYPE - ).group_by( - 'month', - FactBilling.rate, - FactBilling.notification_type, - FactBilling.postage - ) - - yearly_data = email_and_letters.union_all(sms).order_by( - 'month', - 'notification_type', - 'rate' + return db.session.query( + union(*[ + db.session.query( + func.date_trunc('month', query.c.bst_date).cast(Date).label("month"), + func.sum(query.c.notifications_sent).label("notifications_sent"), + # TEMPORARY: while we switch to "chargeable units" + func.sum(query.c.chargeable_units).label("billable_units"), + func.sum(query.c.chargeable_units).label("chargeable_units"), + query.c.rate.label("rate"), + query.c.postage.label("postage"), + query.c.notification_type.label("notification_type"), + ).group_by( + query.c.rate, + query.c.notification_type, + query.c.postage, + 'month', + ) + for query in [ + query_service_sms_usage_for_year(service_id, year).subquery(), + query_service_email_usage_for_year(service_id, year).subquery(), + query_service_letter_usage_for_year(service_id, year).subquery(), + ] + ]).subquery() + ).order_by( + "month", + "notification_type", + "rate", ).all() - return yearly_data - def query_service_email_usage_for_year(service_id, year): year_start, year_end = get_financial_year_dates(year) return db.session.query( + FactBilling.bst_date, + FactBilling.postage, # should always be "none" FactBilling.notifications_sent, FactBilling.notifications_sent.label("chargeable_units"), FactBilling.rate, @@ -301,6 +286,8 @@ def query_service_letter_usage_for_year(service_id, year): year_start, year_end = get_financial_year_dates(year) return db.session.query( + FactBilling.bst_date, + FactBilling.postage, FactBilling.notifications_sent, FactBilling.notifications_sent.label("chargeable_units"), FactBilling.rate, @@ -339,6 +326,8 @@ def query_service_sms_usage_for_year(service_id, year): ) return db.session.query( + FactBilling.bst_date, + FactBilling.postage, # should always be "none" FactBilling.notifications_sent, chargeable_units.label("chargeable_units"), FactBilling.rate, diff --git a/tests/app/billing/test_rest.py b/tests/app/billing/test_rest.py index 7da0a235b..e740d62c6 100644 --- a/tests/app/billing/test_rest.py +++ b/tests/app/billing/test_rest.py @@ -147,6 +147,8 @@ def set_up_monthly_data(): billable_unit=1, rate=0.33, postage='second') + + create_annual_billing(service_id=service.id, free_sms_fragment_limit=4, financial_year_start=2016) return service @@ -170,12 +172,14 @@ def test_get_yearly_usage_by_monthly_from_ft_billing(admin_request, notify_db_se assert letter_row["month"] == "April" assert letter_row["notification_type"] == "letter" assert letter_row["billing_units"] == 30 + assert letter_row["chargeable_units"] == 30 assert letter_row["rate"] == 0.33 assert letter_row["postage"] == "second" assert sms_row["month"] == "April" assert sms_row["notification_type"] == "sms" assert sms_row["billing_units"] == 30 + assert sms_row["chargeable_units"] == 30 assert sms_row["rate"] == 0.162 assert sms_row["postage"] == "none" diff --git a/tests/app/dao/test_ft_billing_dao.py b/tests/app/dao/test_ft_billing_dao.py index ae4284e8c..bede8a190 100644 --- a/tests/app/dao/test_ft_billing_dao.py +++ b/tests/app/dao/test_ft_billing_dao.py @@ -417,6 +417,7 @@ def test_get_rate_for_letters_when_page_count_is_zero(notify_db_session): def test_fetch_monthly_billing_for_year(notify_db_session): service = set_up_yearly_data() + create_annual_billing(service_id=service.id, free_sms_fragment_limit=10, financial_year_start=2016) results = fetch_monthly_billing_for_year(service.id, 2016) assert len(results) == 48 @@ -425,24 +426,28 @@ def test_fetch_monthly_billing_for_year(notify_db_session): assert results[0].notification_type == 'email' assert results[0].notifications_sent == 30 assert results[0].billable_units == 30 + assert results[0].chargeable_units == 30 assert results[0].rate == Decimal('0') assert str(results[1].month) == "2016-04-01" assert results[1].notification_type == 'letter' assert results[1].notifications_sent == 30 assert results[1].billable_units == 30 + assert results[1].chargeable_units == 30 assert results[1].rate == Decimal('0.30') assert str(results[1].month) == "2016-04-01" assert results[2].notification_type == 'letter' assert results[2].notifications_sent == 30 assert results[2].billable_units == 30 + assert results[2].chargeable_units == 30 assert results[2].rate == Decimal('0.33') assert str(results[3].month) == "2016-04-01" assert results[3].notification_type == 'sms' assert results[3].notifications_sent == 30 assert results[3].billable_units == 30 + assert results[3].chargeable_units == 30 assert results[3].rate == Decimal('0.162') assert str(results[4].month) == "2016-05-01" @@ -451,6 +456,7 @@ def test_fetch_monthly_billing_for_year(notify_db_session): def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): service = set_up_yearly_data_variable_rates() + create_annual_billing(service_id=service.id, free_sms_fragment_limit=6, financial_year_start=2018) results = fetch_monthly_billing_for_year(service.id, 2018) # Test data is only for the month of May @@ -460,24 +466,28 @@ def test_fetch_monthly_billing_for_year_variable_rates(notify_db_session): assert results[0].notification_type == 'letter' assert results[0].notifications_sent == 1 assert results[0].billable_units == 1 + assert results[0].chargeable_units == 1 assert results[0].rate == Decimal('0.33') assert str(results[1].month) == "2018-05-01" assert results[1].notification_type == 'letter' assert results[1].notifications_sent == 1 assert results[1].billable_units == 1 + assert results[1].chargeable_units == 1 assert results[1].rate == Decimal('0.36') assert str(results[2].month) == "2018-05-01" assert results[2].notification_type == 'sms' assert results[2].notifications_sent == 1 assert results[2].billable_units == 4 + assert results[2].chargeable_units == 4 assert results[2].rate == Decimal('0.015') assert str(results[3].month) == "2018-05-01" assert results[3].notification_type == 'sms' assert results[3].notifications_sent == 2 assert results[3].billable_units == 5 + assert results[3].chargeable_units == 5 assert results[3].rate == Decimal('0.162') @@ -487,6 +497,7 @@ def test_fetch_monthly_billing_for_year_adds_data_for_today(notify_db_session): template = create_template(service=service, template_type="sms") create_rate(start_date=datetime.utcnow() - timedelta(days=1), value=0.158, notification_type='sms') + create_annual_billing(service_id=service.id, free_sms_fragment_limit=1000, financial_year_start=2018) for i in range(1, 32): create_ft_billing(bst_date='2018-07-{}'.format(i), template=template)