mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-02 17:31:14 -05:00
Merge pull request #3193 from alphagov/populate-annual-billing-2021
Populate annual billing for 2021
This commit is contained in:
@@ -12,6 +12,7 @@ from flask import current_app, json
|
||||
from notifications_utils.recipients import RecipientCSV
|
||||
from notifications_utils.statsd_decorators import statsd
|
||||
from notifications_utils.template import SMSMessageTemplate
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
@@ -29,6 +30,7 @@ from app.celery.tasks import process_row, record_daily_sorted_counts
|
||||
from app.config import QueueNames
|
||||
from app.dao.annual_billing_dao import (
|
||||
dao_create_or_update_annual_billing_for_year,
|
||||
set_default_free_allowance_for_service,
|
||||
)
|
||||
from app.dao.fact_billing_dao import (
|
||||
delete_billing_data_for_service_for_day,
|
||||
@@ -67,6 +69,7 @@ from app.models import (
|
||||
NOTIFICATION_CREATED,
|
||||
PROVIDERS,
|
||||
SMS_TYPE,
|
||||
AnnualBilling,
|
||||
Domain,
|
||||
EmailBranding,
|
||||
LetterBranding,
|
||||
@@ -234,36 +237,6 @@ def fix_notification_statuses_not_in_sync():
|
||||
result = db.session.execute(subq_hist).fetchall()
|
||||
|
||||
|
||||
@notify_command(name='populate-annual-billing')
|
||||
@click.option('-y', '--year', required=True, type=int,
|
||||
help="""The year to populate the annual billing data for, i.e. 2019""")
|
||||
def populate_annual_billing(year):
|
||||
"""
|
||||
add annual_billing for given year.
|
||||
"""
|
||||
sql = """
|
||||
Select id from services where active = true
|
||||
except
|
||||
select service_id
|
||||
from annual_billing
|
||||
where financial_year_start = :year
|
||||
"""
|
||||
services_without_annual_billing = db.session.execute(sql, {"year": year})
|
||||
for row in services_without_annual_billing:
|
||||
latest_annual_billing = """
|
||||
Select free_sms_fragment_limit
|
||||
from annual_billing
|
||||
where service_id = :service_id
|
||||
order by financial_year_start desc limit 1
|
||||
"""
|
||||
free_allowance_rows = db.session.execute(latest_annual_billing, {"service_id": row.id})
|
||||
free_allowance = [x[0]for x in free_allowance_rows]
|
||||
print("create free limit of {} for service: {}".format(free_allowance[0], row.id))
|
||||
dao_create_or_update_annual_billing_for_year(service_id=row.id,
|
||||
free_sms_fragment_limit=free_allowance[0],
|
||||
financial_year_start=int(year))
|
||||
|
||||
|
||||
@notify_command(name='list-routes')
|
||||
def list_routes():
|
||||
"""List URLs of all application routes."""
|
||||
@@ -877,3 +850,67 @@ def process_row_from_job(job_id, job_row_number):
|
||||
notification_id = process_row(row, template, job, job.service)
|
||||
current_app.logger.info("Process row {} for job {} created notification_id: {}".format(
|
||||
job_row_number, job_id, notification_id))
|
||||
|
||||
|
||||
@notify_command(name='populate-annual-billing-with-the-previous-years-allowance')
|
||||
@click.option('-y', '--year', required=True, type=int,
|
||||
help="""The year to populate the annual billing data for, i.e. 2019""")
|
||||
def populate_annual_billing_with_the_previous_years_allowance(year):
|
||||
"""
|
||||
add annual_billing for given year.
|
||||
"""
|
||||
sql = """
|
||||
Select id from services where active = true
|
||||
except
|
||||
select service_id
|
||||
from annual_billing
|
||||
where financial_year_start = :year
|
||||
"""
|
||||
services_without_annual_billing = db.session.execute(sql, {"year": year})
|
||||
for row in services_without_annual_billing:
|
||||
latest_annual_billing = """
|
||||
Select free_sms_fragment_limit
|
||||
from annual_billing
|
||||
where service_id = :service_id
|
||||
order by financial_year_start desc limit 1
|
||||
"""
|
||||
free_allowance_rows = db.session.execute(latest_annual_billing, {"service_id": row.id})
|
||||
free_allowance = [x[0]for x in free_allowance_rows]
|
||||
print("create free limit of {} for service: {}".format(free_allowance[0], row.id))
|
||||
dao_create_or_update_annual_billing_for_year(service_id=row.id,
|
||||
free_sms_fragment_limit=free_allowance[0],
|
||||
financial_year_start=int(year))
|
||||
|
||||
|
||||
@notify_command(name='populate-annual-billing-with-defaults')
|
||||
@click.option('-y', '--year', required=True, type=int,
|
||||
help="""The year to populate the annual billing data for, i.e. 2021""")
|
||||
@click.option('-m', '--missing-services-only', default=True, type=bool,
|
||||
help="""If true then only populate services missing from annual billing for the year.
|
||||
If false populate the default values for all active services.""")
|
||||
def populate_annual_billing_with_defaults(year, missing_services_only):
|
||||
"""
|
||||
Add or update annual billing with free allowance defaults for all active services.
|
||||
The default free allowance limits are in: app/dao/annual_billing_dao.py:57.
|
||||
|
||||
If missing_services_only is true then only add rows for services that do not have annual billing for that year yet.
|
||||
This is useful to prevent overriding any services that have a free allowance that is not the default.
|
||||
|
||||
If missing_services_only is false then add or update annual billing for all active services.
|
||||
This is useful to ensure all services start the new year with the correct annual billing.
|
||||
"""
|
||||
if missing_services_only:
|
||||
active_services = Service.query.filter(
|
||||
Service.active
|
||||
).outerjoin(
|
||||
AnnualBilling, and_(Service.id == AnnualBilling.service_id, AnnualBilling.financial_year_start == year)
|
||||
).filter(
|
||||
AnnualBilling.id == None # noqa
|
||||
).all()
|
||||
else:
|
||||
active_services = Service.query.filter(
|
||||
Service.active
|
||||
).all()
|
||||
|
||||
for service in active_services:
|
||||
set_default_free_allowance_for_service(service, year)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from flask import current_app
|
||||
|
||||
from app import db
|
||||
from app.dao.dao_utils import transactional
|
||||
from app.dao.date_util import get_current_financial_year_start_year
|
||||
@@ -49,3 +51,58 @@ def dao_get_all_free_sms_fragment_limit(service_id):
|
||||
return AnnualBilling.query.filter_by(
|
||||
service_id=service_id,
|
||||
).order_by(AnnualBilling.financial_year_start).all()
|
||||
|
||||
|
||||
def set_default_free_allowance_for_service(service, year_start=None):
|
||||
default_free_sms_fragment_limits = {
|
||||
'central': {
|
||||
2020: 250_000,
|
||||
2021: 150_000,
|
||||
},
|
||||
'local': {
|
||||
2020: 25_000,
|
||||
2021: 25_000,
|
||||
},
|
||||
'nhs_central': {
|
||||
2020: 250_000,
|
||||
2021: 150_000,
|
||||
},
|
||||
'nhs_local': {
|
||||
2020: 25_000,
|
||||
2021: 25_000,
|
||||
},
|
||||
'nhs_gp': {
|
||||
2020: 25_000,
|
||||
2021: 10_000,
|
||||
},
|
||||
'emergency_service': {
|
||||
2020: 25_000,
|
||||
2021: 25_000,
|
||||
},
|
||||
'school_or_college': {
|
||||
2020: 25_000,
|
||||
2021: 10_000,
|
||||
},
|
||||
'other': {
|
||||
2020: 25_000,
|
||||
2021: 10_000,
|
||||
},
|
||||
}
|
||||
if not year_start:
|
||||
year_start = get_current_financial_year_start_year()
|
||||
if year_start < 2020:
|
||||
year_start = 2020
|
||||
if year_start > 2021:
|
||||
year_start = 2021
|
||||
if service.organisation_type:
|
||||
free_allowance = default_free_sms_fragment_limits[service.organisation_type][year_start]
|
||||
else:
|
||||
current_app.logger.info(f"no organisation type for service {service.id}. Using other default of "
|
||||
f"{default_free_sms_fragment_limits['other'][year_start]}")
|
||||
free_allowance = default_free_sms_fragment_limits['other'][year_start]
|
||||
|
||||
dao_create_or_update_annual_billing_for_year(
|
||||
service.id,
|
||||
free_allowance,
|
||||
year_start
|
||||
)
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import pytest
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app.dao.annual_billing_dao import (
|
||||
dao_create_or_update_annual_billing_for_year,
|
||||
dao_get_free_sms_fragment_limit_for_year,
|
||||
dao_update_annual_billing_for_future_years,
|
||||
set_default_free_allowance_for_service,
|
||||
)
|
||||
from app.dao.date_util import get_current_financial_year_start_year
|
||||
from tests.app.db import create_annual_billing
|
||||
from app.models import AnnualBilling
|
||||
from tests.app.db import create_annual_billing, create_service
|
||||
|
||||
|
||||
def test_dao_update_free_sms_fragment_limit(notify_db_session, sample_service):
|
||||
@@ -40,3 +44,50 @@ def test_dao_update_annual_billing_for_future_years(notify_db_session, sample_se
|
||||
assert dao_get_free_sms_fragment_limit_for_year(sample_service.id, current_year) is None
|
||||
assert dao_get_free_sms_fragment_limit_for_year(sample_service.id, current_year + 1).free_sms_fragment_limit == 9999
|
||||
assert dao_get_free_sms_fragment_limit_for_year(sample_service.id, current_year + 2).free_sms_fragment_limit == 9999
|
||||
|
||||
|
||||
@pytest.mark.parametrize('org_type, year, expected_default',
|
||||
[('central', 2021, 150000),
|
||||
('local', 2021, 25000),
|
||||
('nhs_central', 2021, 150000),
|
||||
('nhs_local', 2021, 25000),
|
||||
('nhs_gp', 2021, 10000),
|
||||
('emergency_service', 2021, 25000),
|
||||
('school_or_college', 2021, 10000),
|
||||
('other', 2021, 10000),
|
||||
(None, 2021, 10000),
|
||||
('central', 2020, 250000),
|
||||
('local', 2020, 25000),
|
||||
('nhs_central', 2020, 250000),
|
||||
('nhs_local', 2020, 25000),
|
||||
('nhs_gp', 2020, 25000),
|
||||
('emergency_service', 2020, 25000),
|
||||
('school_or_college', 2020, 25000),
|
||||
('other', 2020, 25000),
|
||||
(None, 2020, 25000),
|
||||
('central', 2019, 250000),
|
||||
('school_or_college', 2022, 10000)
|
||||
])
|
||||
def test_set_default_free_allowance_for_service(notify_db_session, org_type, year, expected_default):
|
||||
|
||||
service = create_service(organisation_type=org_type)
|
||||
|
||||
set_default_free_allowance_for_service(service=service, year_start=year)
|
||||
|
||||
annual_billing = AnnualBilling.query.all()
|
||||
|
||||
assert len(annual_billing) == 1
|
||||
assert annual_billing[0].service_id == service.id
|
||||
assert annual_billing[0].free_sms_fragment_limit == expected_default
|
||||
|
||||
|
||||
@freeze_time('2021-03-29 14:02:00')
|
||||
def test_set_default_free_allowance_for_service_using_correct_year(sample_service, mocker):
|
||||
mock_dao = mocker.patch('app.dao.annual_billing_dao.dao_create_or_update_annual_billing_for_year')
|
||||
set_default_free_allowance_for_service(service=sample_service, year_start=None)
|
||||
|
||||
mock_dao.assert_called_once_with(
|
||||
sample_service.id,
|
||||
25000,
|
||||
2020
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user