Split out handling of BST queries for reuse

This commit is contained in:
Chris Hill-Scott
2017-01-30 16:46:47 +00:00
parent 8381a5e11c
commit 45b505f379
3 changed files with 22 additions and 17 deletions

View File

@@ -27,6 +27,7 @@ from app.models import (
from app.dao.dao_utils import transactional from app.dao.dao_utils import transactional
from app.statsd_decorators import statsd from app.statsd_decorators import statsd
from app.utils import get_london_month_from_utc_column
def dao_get_notification_statistics_for_service_and_day(service_id, day): def dao_get_notification_statistics_for_service_and_day(service_id, day):
@@ -225,16 +226,8 @@ def get_notifications_for_job(service_id, job_id, filter_dict=None, page=1, page
def get_notification_billable_unit_count_per_month(service_id, year): def get_notification_billable_unit_count_per_month(service_id, year):
start, end = get_financial_year(year) start, end = get_financial_year(year)
""" month = get_london_month_from_utc_column(NotificationHistory.created_at)
The query needs to sum the billable_units per month, but this needs to be the month in BST (British Standard Time).
The database stores all timestamps as UTC without the timezone.
- First set the timezone on created_at to UTC
- then convert the timezone to BST (or Europe/London)
- lastly truncate the datetime to month to group the sum of the billable_units
"""
month = func.date_trunc("month",
func.timezone("Europe/London", func.timezone("UTC",
NotificationHistory.created_at)))
notifications = db.session.query( notifications = db.session.query(
month, month,
func.sum(NotificationHistory.billable_units) func.sum(NotificationHistory.billable_units)

View File

@@ -30,6 +30,7 @@ from app.models import (
TEMPLATE_TYPES, TEMPLATE_TYPES,
) )
from app.statsd_decorators import statsd from app.statsd_decorators import statsd
from app.utils import get_london_month_from_utc_column
def dao_fetch_all_services(only_active=False): def dao_fetch_all_services(only_active=False):
@@ -247,13 +248,7 @@ def dao_fetch_monthly_historical_stats_for_service(service_id, year):
monday_of_notification_week = func.date_trunc('week', NotificationHistory.created_at).label('week_start') monday_of_notification_week = func.date_trunc('week', NotificationHistory.created_at).label('week_start')
start, end = get_financial_year(year) start, end = get_financial_year(year)
month = func.date_trunc( month = get_london_month_from_utc_column(NotificationHistory.created_at)
"month",
func.timezone(
"Europe/London",
func.timezone("UTC", NotificationHistory.created_at)
)
)
rows = db.session.query( rows = db.session.query(
NotificationHistory.notification_type, NotificationHistory.notification_type,

View File

@@ -2,6 +2,7 @@ from datetime import datetime, timedelta
import pytz import pytz
from flask import url_for from flask import url_for
from sqlalchemy import func
from notifications_utils.template import SMSMessageTemplate, PlainTextEmailTemplate from notifications_utils.template import SMSMessageTemplate, PlainTextEmailTemplate
@@ -46,3 +47,19 @@ def get_london_midnight_in_utc(date):
def get_midnight_for_day_before(date): def get_midnight_for_day_before(date):
day_before = date - timedelta(1) day_before = date - timedelta(1)
return get_london_midnight_in_utc(day_before) return get_london_midnight_in_utc(day_before)
def get_london_month_from_utc_column(column):
"""
Where queries need to count notifications by month it needs to be
the month in BST (British Summer Time).
The database stores all timestamps as UTC without the timezone.
- First set the timezone on created_at to UTC
- then convert the timezone to BST (or Europe/London)
- lastly truncate the datetime to month with which we can group
queries
"""
return func.date_trunc(
"month",
func.timezone("Europe/London", func.timezone("UTC", column))
)