Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions app/celery/nightly_tasks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime, timedelta

from flask import current_app
from notifications_utils.timezones import convert_utc_to_local_timezone
from sqlalchemy.exc import SQLAlchemyError

from app import notify_celery
Expand All @@ -27,7 +26,7 @@
fetch_service_data_retention_for_all_services_by_notification_type,
)
from app.models import EMAIL_TYPE, SMS_TYPE, FactProcessingTime
from app.utils import get_local_midnight_in_utc
from app.utils import get_midnight_in_utc


@notify_celery.task(name="remove_sms_email_jobs")
Expand Down Expand Up @@ -79,19 +78,17 @@ def _delete_notifications_older_than_retention_by_type(notification_type):
flexible_data_retention = fetch_service_data_retention_for_all_services_by_notification_type(notification_type)

for f in flexible_data_retention:
day_to_delete_backwards_from = get_local_midnight_in_utc(
convert_utc_to_local_timezone(datetime.utcnow()).date() - timedelta(days=f.days_of_retention)
)
day_to_delete_backwards_from = get_midnight_in_utc(datetime.utcnow()).date() \
- timedelta(days=f.days_of_retention)

delete_notifications_for_service_and_type.apply_async(queue=QueueNames.REPORTING, kwargs={
'service_id': f.service_id,
'notification_type': notification_type,
'datetime_to_delete_before': day_to_delete_backwards_from
})

seven_days_ago = get_local_midnight_in_utc(
convert_utc_to_local_timezone(datetime.utcnow()).date() - timedelta(days=7)
)
seven_days_ago = get_midnight_in_utc(datetime.utcnow()).date() - timedelta(days=7)

service_ids_with_data_retention = {x.service_id for x in flexible_data_retention}

# get a list of all service ids that we'll need to delete for. Typically that might only be 5% of services.
Expand Down Expand Up @@ -184,8 +181,8 @@ def save_daily_notification_processing_time(local_date=None):
else:
local_date = datetime.strptime(local_date, "%Y-%m-%d").date()

start_time = get_local_midnight_in_utc(local_date)
end_time = get_local_midnight_in_utc(local_date + timedelta(days=1))
start_time = get_midnight_in_utc(local_date)
end_time = get_midnight_in_utc(local_date + timedelta(days=1))
result = dao_get_notifications_processing_time_stats(start_time, end_time)
insert_update_processing_time(
FactProcessingTime(
Expand Down
5 changes: 2 additions & 3 deletions app/celery/reporting_tasks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime, timedelta

from flask import current_app
from notifications_utils.timezones import convert_utc_to_local_timezone

from app import notify_celery
from app.config import QueueNames
Expand All @@ -21,7 +20,7 @@ def create_nightly_billing(day_start=None):
# day_start is a datetime.date() object. e.g.
# up to 4 days of data counting back from day_start is consolidated
if day_start is None:
day_start = convert_utc_to_local_timezone(datetime.utcnow()).date() - timedelta(days=1)
day_start = datetime.utcnow().date() - timedelta(days=1)
else:
# When calling the task its a string in the format of "YYYY-MM-DD"
day_start = datetime.strptime(day_start, "%Y-%m-%d").date()
Expand Down Expand Up @@ -83,7 +82,7 @@ def create_nightly_notification_status():
mean the aggregated results are temporarily incorrect.
"""

yesterday = convert_utc_to_local_timezone(datetime.utcnow()).date() - timedelta(days=1)
yesterday = datetime.utcnow().date() - timedelta(days=1)

for notification_type in [SMS_TYPE, EMAIL_TYPE]:
days = 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import requests
from flask import current_app
from notifications_utils.timezones import convert_utc_to_local_timezone


class PerformancePlatformClient:
Expand Down Expand Up @@ -55,7 +54,7 @@ def format_payload(*, dataset, start_time, group_name, group_value, count, perio
:param period - the period that this data covers - "day", "week", "month", "quarter".
"""
payload = {
'_timestamp': convert_utc_to_local_timezone(start_time).isoformat(),
'_timestamp': start_time,
'service': 'govuk-notify',
'dataType': dataset,
'period': period,
Expand Down
6 changes: 3 additions & 3 deletions app/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
TemplateHistory,
User,
)
from app.utils import get_local_midnight_in_utc
from app.utils import get_midnight_in_utc


@click.group(name='command', help='Additional commands')
Expand Down Expand Up @@ -193,8 +193,8 @@ def rebuild_ft_data(process_day, service):
rebuild_ft_data(day, service_id)
else:
services = get_service_ids_that_need_billing_populated(
get_local_midnight_in_utc(day),
get_local_midnight_in_utc(day + timedelta(days=1))
get_midnight_in_utc(day),
get_midnight_in_utc(day + timedelta(days=1))
)
for row in services:
rebuild_ft_data(day, row.service_id)
Expand Down
6 changes: 3 additions & 3 deletions app/dao/complaint_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from app import db
from app.dao.dao_utils import autocommit
from app.models import Complaint
from app.utils import get_local_midnight_in_utc
from app.utils import get_midnight_in_utc


@autocommit
Expand All @@ -28,7 +28,7 @@ def fetch_complaints_by_service(service_id):


def fetch_count_of_complaints(start_date, end_date):
start_date = get_local_midnight_in_utc(start_date)
end_date = get_local_midnight_in_utc(end_date + timedelta(days=1))
start_date = get_midnight_in_utc(start_date)
end_date = get_midnight_in_utc(end_date + timedelta(days=1))

return Complaint.query.filter(Complaint.created_at >= start_date, Complaint.created_at < end_date).count()
26 changes: 6 additions & 20 deletions app/dao/date_util.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
from datetime import date, datetime, time, timedelta

import pytz
from notifications_utils.timezones import (
convert_local_timezone_to_utc,
convert_utc_to_local_timezone,
local_timezone,
)


def get_months_for_financial_year(year):
return [
convert_local_timezone_to_utc(month) for month in (
month for month in (
get_months_for_year(4, 13, year)
+ get_months_for_year(1, 4, year + 1)
)
if convert_local_timezone_to_utc(month) < datetime.now()
if month < datetime.now()
]


Expand All @@ -30,8 +23,8 @@ def get_financial_year_dates(year):
year_start_datetime, year_end_datetime = get_financial_year(year)

return (
convert_utc_to_local_timezone(year_start_datetime).date(),
convert_utc_to_local_timezone(year_end_datetime).date()
year_start_datetime.date(),
year_end_datetime.date()
)


Expand All @@ -44,14 +37,7 @@ def get_current_financial_year():


def get_april_fools(year):
"""
This function converts the start of the financial year April 1, 00:00 as BST (British Standard Time) to UTC,
the tzinfo is lastly removed from the datetime because the database stores the timestamps without timezone.
:param year: the year to calculate the April 1, 00:00 BST for
:return: the datetime of April 1 for the given year, for example 2016 = 2016-03-31 23:00:00
"""
return local_timezone.localize(
datetime(year, 4, 1, 0, 0, 0)).astimezone(pytz.UTC).replace(tzinfo=None)
return datetime(year, 4, 1, 0, 0, 0)


def get_month_start_and_end_date_in_utc(month_year):
Expand All @@ -64,7 +50,7 @@ def get_month_start_and_end_date_in_utc(month_year):
_, num_days = calendar.monthrange(month_year.year, month_year.month)
first_day = datetime(month_year.year, month_year.month, 1, 0, 0, 0)
last_day = datetime(month_year.year, month_year.month, num_days, 23, 59, 59, 99999)
return convert_local_timezone_to_utc(first_day), convert_local_timezone_to_utc(last_day)
return first_day, last_day


def get_current_financial_year_start_year():
Expand Down
13 changes: 6 additions & 7 deletions app/dao/fact_billing_dao.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import date, datetime, timedelta

from flask import current_app
from notifications_utils.timezones import convert_utc_to_local_timezone
from sqlalchemy import Date, Integer, and_, desc, func, union
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.sql.expression import case, literal
Expand All @@ -27,7 +26,7 @@
Rate,
Service,
)
from app.utils import get_local_midnight_in_utc
from app.utils import get_midnight_in_utc


def fetch_sms_free_allowance_remainder_until_date(end_date):
Expand Down Expand Up @@ -179,7 +178,7 @@ def fetch_monthly_billing_for_year(service_id, year):
we also update the table on-the-fly if we need accurate data for this year.
"""
_, year_end = get_financial_year_dates(year)
today = convert_utc_to_local_timezone(datetime.utcnow()).date()
today = 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.
if year_end >= today:
Expand Down Expand Up @@ -330,8 +329,8 @@ def delete_billing_data_for_service_for_day(process_day, service_id):


def fetch_billing_data_for_day(process_day, service_id=None, check_permissions=False):
start_date = get_local_midnight_in_utc(process_day)
end_date = get_local_midnight_in_utc(process_day + timedelta(days=1))
start_date = get_midnight_in_utc(process_day)
end_date = get_midnight_in_utc(process_day + timedelta(days=1))
current_app.logger.info("Populate ft_billing for {} to {}".format(start_date, end_date))
transit_data = []
if not service_id:
Expand Down Expand Up @@ -430,7 +429,7 @@ def get_service_ids_that_need_billing_populated(start_date, end_date):
def get_rate(
rates, notification_type, date
):
start_of_day = get_local_midnight_in_utc(date)
start_of_day = get_midnight_in_utc(date)

if notification_type == SMS_TYPE:
return next(
Expand Down Expand Up @@ -624,7 +623,7 @@ def query_organisation_sms_usage_for_year(organisation_id, year):

def fetch_usage_year_for_organisation(organisation_id, year):
year_start, year_end = get_financial_year_dates(year)
today = convert_utc_to_local_timezone(datetime.utcnow()).date()
today = datetime.utcnow().date()
services = dao_get_organisation_live_services(organisation_id)

# if year end date is less than today, we are calculating for data in the past and have no need for deltas.
Expand Down
26 changes: 13 additions & 13 deletions app/dao/fact_notification_status_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@
Template,
)
from app.utils import (
get_local_midnight_in_utc,
get_local_month_from_utc_column,
get_midnight_in_utc,
get_month_from_utc_column,
midnight_n_days_ago,
)


@autocommit
def update_fact_notification_status(process_day, notification_type, service_id):
start_date = get_local_midnight_in_utc(process_day)
end_date = get_local_midnight_in_utc(process_day + timedelta(days=1))
start_date = get_midnight_in_utc(process_day)
end_date = get_midnight_in_utc(process_day + timedelta(days=1))

# delete any existing rows in case some no longer exist e.g. if all messages are sent
FactNotificationStatus.query.filter(
Expand Down Expand Up @@ -104,16 +104,16 @@ def fetch_notification_status_for_service_by_month(start_date, end_date, service
).all()


def fetch_notification_status_for_service_for_day(bst_day, service_id):
def fetch_notification_status_for_service_for_day(fetch_day, service_id):
return db.session.query(
# return current month as a datetime so the data has the same shape as the ft_notification_status query
literal(bst_day.replace(day=1), type_=DateTime).label('month'),
literal(fetch_day.replace(day=1), type_=DateTime).label('month'),
Notification.notification_type,
Notification.status.label('notification_status'),
func.count().label('count')
).filter(
Notification.created_at >= get_local_midnight_in_utc(bst_day),
Notification.created_at < get_local_midnight_in_utc(bst_day + timedelta(days=1)),
Notification.created_at >= get_midnight_in_utc(fetch_day),
Notification.created_at < get_midnight_in_utc(fetch_day + timedelta(days=1)),
Notification.service_id == service_id,
Notification.key_type != KEY_TYPE_TEST
).group_by(
Expand Down Expand Up @@ -142,7 +142,7 @@ def fetch_notification_status_for_service_for_today_and_7_previous_days(service_
*([Notification.template_id] if by_template else []),
func.count().label('count')
).filter(
Notification.created_at >= get_local_midnight_in_utc(now),
Notification.created_at >= get_midnight_in_utc(now),
Notification.service_id == service_id,
Notification.key_type != KEY_TYPE_TEST
).group_by(
Expand Down Expand Up @@ -188,7 +188,7 @@ def fetch_notification_status_totals_for_all_services(start_date, end_date):
FactNotificationStatus.notification_status,
FactNotificationStatus.key_type,
)
today = get_local_midnight_in_utc(datetime.utcnow())
today = get_midnight_in_utc(datetime.utcnow())
if start_date <= datetime.utcnow().date() <= end_date:
stats_for_today = db.session.query(
Notification.notification_type.cast(db.Text).label('notification_type'),
Expand Down Expand Up @@ -265,7 +265,7 @@ def fetch_stats_for_all_services_by_date_range(start_date, end_date, include_fro
stats = stats.filter(FactNotificationStatus.key_type != KEY_TYPE_TEST)

if start_date <= datetime.utcnow().date() <= end_date:
today = get_local_midnight_in_utc(datetime.utcnow())
today = get_midnight_in_utc(datetime.utcnow())
subquery = db.session.query(
Notification.notification_type.cast(db.Text).label('notification_type'),
Notification.status.label('status'),
Expand Down Expand Up @@ -357,8 +357,8 @@ def fetch_monthly_template_usage_for_service(start_date, end_date, service_id):
)

if start_date <= datetime.utcnow() <= end_date:
today = get_local_midnight_in_utc(datetime.utcnow())
month = get_local_month_from_utc_column(Notification.created_at)
today = get_midnight_in_utc(datetime.utcnow())
month = get_month_from_utc_column(Notification.created_at)

stats_for_today = db.session.query(
Notification.template_id.label('template_id'),
Expand Down
6 changes: 3 additions & 3 deletions app/dao/notifications_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
)
from app.utils import (
escape_special_characters,
get_local_midnight_in_utc,
get_midnight_in_utc,
midnight_n_days_ago,
)

Expand Down Expand Up @@ -612,8 +612,8 @@ def get_service_ids_with_notifications_before(notification_type, timestamp):


def get_service_ids_with_notifications_on_date(notification_type, date):
start_date = get_local_midnight_in_utc(date)
end_date = get_local_midnight_in_utc(date + timedelta(days=1))
start_date = get_midnight_in_utc(date)
end_date = get_midnight_in_utc(date + timedelta(days=1))

notification_table_query = db.session.query(
Notification.service_id.label('service_id')
Expand Down
5 changes: 2 additions & 3 deletions app/dao/provider_details_dao.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime, timedelta

from flask import current_app
from notifications_utils.timezones import convert_utc_to_local_timezone
from sqlalchemy import asc, desc, func

from app import db
Expand Down Expand Up @@ -155,8 +154,8 @@ def _update_provider_details_without_commit(provider_details):
def dao_get_provider_stats():
# this query does not include the current day since the task to populate ft_billing runs overnight

current_local_datetime = convert_utc_to_local_timezone(datetime.utcnow())
first_day_of_the_month = current_local_datetime.date().replace(day=1)
current_datetime = datetime.utcnow()
first_day_of_the_month = current_datetime.date().replace(day=1)

subquery = db.session.query(
FactBilling.provider,
Expand Down
Loading