mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-10 10:03:38 -04:00
Add dao method to get template stats per month in financial year for service
This commit is contained in:
@@ -29,6 +29,7 @@ from app.models import (
|
|||||||
NOTIFICATION_STATUS_TYPES,
|
NOTIFICATION_STATUS_TYPES,
|
||||||
TEMPLATE_TYPES,
|
TEMPLATE_TYPES,
|
||||||
)
|
)
|
||||||
|
from app.service.statistics import format_monthly_template_notification_stats
|
||||||
from app.statsd_decorators import statsd
|
from app.statsd_decorators import statsd
|
||||||
from app.utils import get_london_month_from_utc_column
|
from app.utils import get_london_month_from_utc_column
|
||||||
|
|
||||||
@@ -224,6 +225,38 @@ def _stats_for_service_query(service_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@statsd(namespace="dao")
|
||||||
|
def dao_fetch_monthly_historical_stats_by_template_for_service(service_id, year):
|
||||||
|
month = get_london_month_from_utc_column(NotificationHistory.created_at)
|
||||||
|
|
||||||
|
sq = db.session.query(
|
||||||
|
NotificationHistory.template_id,
|
||||||
|
NotificationHistory.status,
|
||||||
|
month.label('month'),
|
||||||
|
func.count().label('count')
|
||||||
|
).filter(
|
||||||
|
NotificationHistory.service_id == service_id,
|
||||||
|
NotificationHistory.created_at.between(*get_financial_year(year))
|
||||||
|
).group_by(
|
||||||
|
month,
|
||||||
|
NotificationHistory.template_id,
|
||||||
|
NotificationHistory.status
|
||||||
|
).subquery()
|
||||||
|
|
||||||
|
rows = db.session.query(
|
||||||
|
Template.id.label('template_id'),
|
||||||
|
Template.name,
|
||||||
|
sq.c.status,
|
||||||
|
sq.c.count.label('count'),
|
||||||
|
sq.c.month
|
||||||
|
).join(
|
||||||
|
sq,
|
||||||
|
sq.c.template_id == Template.id
|
||||||
|
).all()
|
||||||
|
|
||||||
|
return format_monthly_template_notification_stats(year, rows)
|
||||||
|
|
||||||
|
|
||||||
@statsd(namespace="dao")
|
@statsd(namespace="dao")
|
||||||
def dao_fetch_monthly_historical_stats_for_service(service_id, year):
|
def dao_fetch_monthly_historical_stats_for_service(service_id, year):
|
||||||
month = get_london_month_from_utc_column(NotificationHistory.created_at)
|
month = get_london_month_from_utc_column(NotificationHistory.created_at)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import itertools
|
import itertools
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from app.models import TEMPLATE_TYPES
|
from app.models import NOTIFICATION_STATUS_TYPES, TEMPLATE_TYPES
|
||||||
|
|
||||||
|
|
||||||
def format_statistics(statistics):
|
def format_statistics(statistics):
|
||||||
@@ -15,6 +15,28 @@ def format_statistics(statistics):
|
|||||||
return counts
|
return counts
|
||||||
|
|
||||||
|
|
||||||
|
def format_monthly_template_notification_stats(year, rows):
|
||||||
|
dict = {
|
||||||
|
datetime.strftime(date, '%Y-%m'): {}
|
||||||
|
for date in [
|
||||||
|
datetime(year, month, 1) for month in range(4, 13)
|
||||||
|
] + [
|
||||||
|
datetime(year + 1, month, 1) for month in range(1, 4)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
formatted_month = row.month.strftime('%Y-%m')
|
||||||
|
if str(row.template_id) not in dict[formatted_month]:
|
||||||
|
dict[formatted_month][str(row.template_id)] = {
|
||||||
|
"name": row.name,
|
||||||
|
"counts": dict.fromkeys(NOTIFICATION_STATUS_TYPES, 0)
|
||||||
|
}
|
||||||
|
dict[formatted_month][str(row.template_id)]["counts"][row.status] += row.count
|
||||||
|
|
||||||
|
return dict
|
||||||
|
|
||||||
|
|
||||||
def create_zeroed_stats_dicts():
|
def create_zeroed_stats_dicts():
|
||||||
return {
|
return {
|
||||||
template_type: {
|
template_type: {
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ from app.utils import get_london_midnight_in_utc
|
|||||||
from tests.app.db import create_notification, create_service, create_template
|
from tests.app.db import create_notification, create_service, create_template
|
||||||
from tests.app.conftest import (
|
from tests.app.conftest import (
|
||||||
sample_job as create_sample_job,
|
sample_job as create_sample_job,
|
||||||
sample_notification_history as create_notification_history
|
sample_notification_history as create_notification_history,
|
||||||
|
create_notify_template
|
||||||
)
|
)
|
||||||
from tests.conftest import set_config_values
|
from tests.conftest import set_config_values
|
||||||
from unittest.mock import call, patch, PropertyMock
|
from unittest.mock import call, patch, PropertyMock
|
||||||
@@ -43,13 +44,19 @@ def _create_slow_delivery_notification(provider='mmg'):
|
|||||||
service = create_service(
|
service = create_service(
|
||||||
service_id=current_app.config.get('FUNCTIONAL_TEST_PROVIDER_SERVICE_ID')
|
service_id=current_app.config.get('FUNCTIONAL_TEST_PROVIDER_SERVICE_ID')
|
||||||
)
|
)
|
||||||
|
|
||||||
template = Template.query.get(current_app.config['FUNCTIONAL_TEST_PROVIDER_SMS_TEMPLATE_ID'])
|
template = Template.query.get(current_app.config['FUNCTIONAL_TEST_PROVIDER_SMS_TEMPLATE_ID'])
|
||||||
if not template:
|
if not template:
|
||||||
template = create_template(
|
template = create_notify_template(
|
||||||
template_id=current_app.config.get('FUNCTIONAL_TEST_PROVIDER_SMS_TEMPLATE_ID'),
|
service=service,
|
||||||
service=service
|
user=service.users[0],
|
||||||
|
template_config_name='FUNCTIONAL_TEST_PROVIDER_SMS_TEMPLATE_ID',
|
||||||
|
content='',
|
||||||
|
template_type='sms'
|
||||||
)
|
)
|
||||||
|
# template = create_template(
|
||||||
|
# template_id=current_app.config.get('FUNCTIONAL_TEST_PROVIDER_SMS_TEMPLATE_ID'),
|
||||||
|
# service=service
|
||||||
|
# )
|
||||||
|
|
||||||
create_notification(
|
create_notification(
|
||||||
template=template,
|
template=template,
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ def sample_template(
|
|||||||
service = sample_service(notify_db, notify_db_session)
|
service = sample_service(notify_db, notify_db_session)
|
||||||
if created_by is None:
|
if created_by is None:
|
||||||
created_by = create_user()
|
created_by = create_user()
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'name': template_name,
|
'name': template_name,
|
||||||
'template_type': template_type,
|
'template_type': template_type,
|
||||||
@@ -870,6 +871,7 @@ def create_notify_template(service, user, template_config_name, content, templat
|
|||||||
}
|
}
|
||||||
template = Template(**data)
|
template = Template(**data)
|
||||||
db.session.add(template)
|
db.session.add(template)
|
||||||
|
db.session.commit()
|
||||||
return template
|
return template
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import pytest
|
|||||||
from sqlalchemy.orm.exc import FlushError, NoResultFound
|
from sqlalchemy.orm.exc import FlushError, NoResultFound
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.dao.services_dao import (
|
from app.dao.services_dao import (
|
||||||
dao_create_service,
|
dao_create_service,
|
||||||
@@ -20,11 +19,13 @@ from app.dao.services_dao import (
|
|||||||
dao_fetch_stats_for_service,
|
dao_fetch_stats_for_service,
|
||||||
dao_fetch_todays_stats_for_service,
|
dao_fetch_todays_stats_for_service,
|
||||||
dao_fetch_monthly_historical_stats_for_service,
|
dao_fetch_monthly_historical_stats_for_service,
|
||||||
|
dao_fetch_monthly_historical_stats_by_template_for_service,
|
||||||
fetch_todays_total_message_count,
|
fetch_todays_total_message_count,
|
||||||
dao_fetch_todays_stats_for_all_services,
|
dao_fetch_todays_stats_for_all_services,
|
||||||
fetch_stats_by_date_range_for_all_services,
|
fetch_stats_by_date_range_for_all_services,
|
||||||
dao_suspend_service,
|
dao_suspend_service,
|
||||||
dao_resume_service)
|
dao_resume_service
|
||||||
|
)
|
||||||
from app.dao.users_dao import save_model_user
|
from app.dao.users_dao import save_model_user
|
||||||
from app.models import (
|
from app.models import (
|
||||||
NotificationStatistics,
|
NotificationStatistics,
|
||||||
@@ -50,7 +51,8 @@ from app.models import (
|
|||||||
from tests.app.conftest import (
|
from tests.app.conftest import (
|
||||||
sample_notification as create_notification,
|
sample_notification as create_notification,
|
||||||
sample_notification_history as create_notification_history,
|
sample_notification_history as create_notification_history,
|
||||||
sample_email_template as create_email_template
|
sample_email_template as create_email_template,
|
||||||
|
sample_template as create_sample_template
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -655,3 +657,90 @@ def test_dao_resume_service_marks_service_as_active_and_api_keys_are_still_revok
|
|||||||
|
|
||||||
api_key = ApiKey.query.get(sample_api_key.id)
|
api_key = ApiKey.query.get(sample_api_key.id)
|
||||||
assert api_key.expiry_date == datetime(2001, 1, 1, 23, 59, 00)
|
assert api_key.expiry_date == datetime(2001, 1, 1, 23, 59, 00)
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_monthly_historical_template_stats_for_service_includes_financial_year_only(
|
||||||
|
notify_db,
|
||||||
|
notify_db_session,
|
||||||
|
sample_template
|
||||||
|
):
|
||||||
|
notification_history = functools.partial(
|
||||||
|
create_notification_history,
|
||||||
|
notify_db,
|
||||||
|
notify_db_session,
|
||||||
|
sample_template
|
||||||
|
)
|
||||||
|
|
||||||
|
notification_history(created_at=datetime(2016, 4, 1), status='sending') # Start of financial year
|
||||||
|
notification_history(created_at=datetime(2016, 5, 30), status='created')
|
||||||
|
notification_history(created_at=datetime(2016, 6, 1), status='created')
|
||||||
|
notification_history(created_at=datetime(2017, 3, 31), status='created') # End of financial year
|
||||||
|
notification_history(created_at=datetime(2017, 4, 1), status='created')
|
||||||
|
notification_history(created_at=datetime(2017, 5, 1), status='created')
|
||||||
|
|
||||||
|
result = dao_fetch_monthly_historical_stats_by_template_for_service(sample_template.service_id, 2016)
|
||||||
|
|
||||||
|
notifications_count = 0
|
||||||
|
for dict in result.values():
|
||||||
|
notifications_count += sum(dict.get(str(sample_template.id), {}).get("counts", {}).values())
|
||||||
|
|
||||||
|
assert '2017-04' not in result
|
||||||
|
assert '2017-05' not in result
|
||||||
|
assert notifications_count == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_monthly_historical_template_stats_for_service_separates_months(
|
||||||
|
notify_db,
|
||||||
|
notify_db_session,
|
||||||
|
sample_template
|
||||||
|
):
|
||||||
|
notification_history = functools.partial(
|
||||||
|
create_notification_history,
|
||||||
|
notify_db,
|
||||||
|
notify_db_session,
|
||||||
|
sample_template
|
||||||
|
)
|
||||||
|
|
||||||
|
notification_history(created_at=datetime(2016, 4, 1), status='sending') # Start of financial year
|
||||||
|
notification_history(created_at=datetime(2016, 5, 30), status='created')
|
||||||
|
notification_history(created_at=datetime(2016, 6, 1), status='delivered')
|
||||||
|
notification_history(created_at=datetime(2016, 6, 1), status='created')
|
||||||
|
notification_history(created_at=datetime(2016, 12, 1), status='created')
|
||||||
|
notification_history(created_at=datetime(2017, 3, 30), status='sending')
|
||||||
|
notification_history(created_at=datetime(2017, 3, 31), status='sending')
|
||||||
|
|
||||||
|
result = dao_fetch_monthly_historical_stats_by_template_for_service(sample_template.service_id, 2016)
|
||||||
|
|
||||||
|
financial_year_month_keys = \
|
||||||
|
['2016-{:02}'.format(month) for month in range(4, 13)] + ['2017-{:02}'.format(month) for month in range(1, 4)]
|
||||||
|
|
||||||
|
assert set(financial_year_month_keys) == set(result.keys())
|
||||||
|
assert sum(result["2016-04"][str(sample_template.id)]["counts"].values()) == 1
|
||||||
|
assert sum(result["2016-05"][str(sample_template.id)]["counts"].values()) == 1
|
||||||
|
assert sum(result["2016-06"][str(sample_template.id)]["counts"].values()) == 2
|
||||||
|
assert sum(result["2016-12"][str(sample_template.id)]["counts"].values()) == 1
|
||||||
|
assert sum(result["2017-03"][str(sample_template.id)]["counts"].values()) == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_monthly_historical_template_stats_for_service_separates_templates(
|
||||||
|
notify_db,
|
||||||
|
notify_db_session
|
||||||
|
):
|
||||||
|
notification_history = functools.partial(
|
||||||
|
create_notification_history,
|
||||||
|
notify_db,
|
||||||
|
notify_db_session,
|
||||||
|
status='delivered'
|
||||||
|
)
|
||||||
|
|
||||||
|
template_one = create_sample_template(notify_db, notify_db_session)
|
||||||
|
template_two = create_sample_template(notify_db, notify_db_session)
|
||||||
|
|
||||||
|
notification_history(created_at=datetime(2016, 4, 1), sample_template=template_one)
|
||||||
|
notification_history(created_at=datetime(2016, 4, 1), sample_template=template_two)
|
||||||
|
|
||||||
|
result = dao_fetch_monthly_historical_stats_by_template_for_service(template_one.service_id, 2016)
|
||||||
|
|
||||||
|
assert len(result.get('2016-04').keys()) == 2
|
||||||
|
assert str(template_one.id) in result.get('2016-04').keys()
|
||||||
|
assert str(template_two.id) in result.get('2016-04').keys()
|
||||||
|
|||||||
Reference in New Issue
Block a user