mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-14 02:48:01 -04:00
Changed the scheduled_for datetime to only send and hour of a day to send.
Also expect the date being passed in is BST. The date is converted to UTC before saving. And converted to BST when returning a notification.
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import base64
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
|
||||
import requests
|
||||
from flask import current_app
|
||||
|
||||
from app.utils import get_midnight_for_day_before, get_london_midnight_in_utc, get_utc_time_in_bst
|
||||
from app.utils import get_midnight_for_day_before, get_london_midnight_in_utc, convert_utc_time_in_bst
|
||||
|
||||
|
||||
class PerformancePlatformClient:
|
||||
@@ -27,7 +27,7 @@ class PerformancePlatformClient:
|
||||
def send_performance_stats(self, date, channel, count, period):
|
||||
if self.active:
|
||||
payload = {
|
||||
'_timestamp': get_utc_time_in_bst(date).isoformat(),
|
||||
'_timestamp': convert_utc_time_in_bst(date).isoformat(),
|
||||
'service': 'govuk-notify',
|
||||
'channel': channel,
|
||||
'count': count,
|
||||
|
||||
@@ -29,7 +29,7 @@ from app import (
|
||||
)
|
||||
|
||||
from app.history_meta import Versioned
|
||||
from app.utils import get_utc_time_in_bst
|
||||
from app.utils import convert_utc_time_in_bst
|
||||
|
||||
SMS_TYPE = 'sms'
|
||||
EMAIL_TYPE = 'email'
|
||||
@@ -832,7 +832,7 @@ class Notification(db.Model):
|
||||
}[self.template.template_type].get(self.status, self.status)
|
||||
|
||||
def serialize_for_csv(self):
|
||||
created_at_in_bst = get_utc_time_in_bst(self.created_at)
|
||||
created_at_in_bst = convert_utc_time_in_bst(self.created_at)
|
||||
serialized = {
|
||||
"row_number": '' if self.job_row_number is None else self.job_row_number + 1,
|
||||
"recipient": self.to,
|
||||
@@ -873,7 +873,7 @@ class Notification(db.Model):
|
||||
"sent_at": self.sent_at.strftime(DATETIME_FORMAT) if self.sent_at else None,
|
||||
"completed_at": self.completed_at(),
|
||||
"scheduled_for": self.scheduled_notification.scheduled_for.strftime(
|
||||
DATETIME_FORMAT) if self.scheduled_notification else None
|
||||
"%Y-%m-%d %H") if self.scheduled_notification else None
|
||||
}
|
||||
|
||||
return serialized
|
||||
|
||||
@@ -15,7 +15,7 @@ from app.dao.notifications_dao import (dao_create_notification,
|
||||
dao_created_scheduled_notification)
|
||||
from app.models import SMS_TYPE, Notification, KEY_TYPE_TEST, EMAIL_TYPE, ScheduledNotification
|
||||
from app.v2.errors import BadRequestError, SendNotificationToQueueError
|
||||
from app.utils import get_template_instance, cache_key_for_service_template_counter
|
||||
from app.utils import get_template_instance, cache_key_for_service_template_counter, convert_bst_to_utc
|
||||
|
||||
|
||||
def create_content_for_notification(template, personalisation):
|
||||
@@ -125,6 +125,7 @@ def simulated_recipient(to_address, notification_type):
|
||||
|
||||
|
||||
def persist_scheduled_notification(notification_id, scheduled_for):
|
||||
scheduled_datetime = convert_bst_to_utc(datetime.strptime(scheduled_for, "%Y-%m-%d %H"))
|
||||
scheduled_notification = ScheduledNotification(notification_id=notification_id,
|
||||
scheduled_for=scheduled_for)
|
||||
scheduled_for=scheduled_datetime)
|
||||
dao_created_scheduled_notification(scheduled_notification)
|
||||
|
||||
@@ -22,13 +22,13 @@ def validate(json_to_validate, schema):
|
||||
return True
|
||||
|
||||
@format_checker.checks('datetime', raises=ValidationError)
|
||||
def validate_schema_datetime(instance):
|
||||
def validate_schema_date_with_hour(instance):
|
||||
if isinstance(instance, str):
|
||||
try:
|
||||
datetime.strptime(instance, "%Y-%m-%d %H:%M:%S")
|
||||
datetime.strptime(instance, "%Y-%m-%d %H")
|
||||
except ValueError as e:
|
||||
raise ValidationError("datetime format is invalid. Use the format: "
|
||||
"YYYY-MM-DD HH:MM:SS, for example 2017-05-30 13:00:00")
|
||||
"YYYY-MM-DD HH, for example 2017-05-30 13")
|
||||
return True
|
||||
|
||||
validator = Draft4Validator(schema, format_checker=format_checker)
|
||||
|
||||
@@ -51,10 +51,14 @@ def get_midnight_for_day_before(date):
|
||||
return get_london_midnight_in_utc(day_before)
|
||||
|
||||
|
||||
def get_utc_time_in_bst(utc_dt):
|
||||
def convert_utc_time_in_bst(utc_dt):
|
||||
return pytz.utc.localize(utc_dt).astimezone(local_timezone).replace(tzinfo=None)
|
||||
|
||||
|
||||
def convert_bst_to_utc(date):
|
||||
return local_timezone.localize(date).astimezone(pytz.UTC).replace(tzinfo=None)
|
||||
|
||||
|
||||
def get_london_month_from_utc_column(column):
|
||||
"""
|
||||
Where queries need to count notifications by month it needs to be
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
from datetime import datetime
|
||||
|
||||
from app import DATETIME_FORMAT
|
||||
from app.models import NOTIFICATION_STATUS_TYPES, TEMPLATE_TYPES
|
||||
from app.schema_validation.definitions import (uuid, personalisation)
|
||||
|
||||
# this may belong in a templates module
|
||||
|
||||
template = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "template schema",
|
||||
@@ -204,8 +201,7 @@ def create_post_sms_response_from_notification(notification, body, from_number,
|
||||
"template": __create_template_from_notification(notification=notification,
|
||||
url_root=url_root,
|
||||
service_id=service_id),
|
||||
"scheduled_for": datetime.strptime(scheduled_for,
|
||||
"%Y-%m-%d %H:%M:%S").strftime(DATETIME_FORMAT) if scheduled_for else None
|
||||
"scheduled_for": scheduled_for if scheduled_for else None
|
||||
}
|
||||
|
||||
|
||||
@@ -223,8 +219,7 @@ def create_post_email_response_from_notification(notification, content, subject,
|
||||
"template": __create_template_from_notification(notification=notification,
|
||||
url_root=url_root,
|
||||
service_id=service_id),
|
||||
"scheduled_for": datetime.strptime(scheduled_for,
|
||||
"%Y-%m-%d %H:%M:%S").strftime(DATETIME_FORMAT) if scheduled_for else None
|
||||
"scheduled_for": scheduled_for if scheduled_for else None
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -417,13 +417,13 @@ def test_should_send_all_scheduled_notifications_to_deliver_queue(notify_db,
|
||||
sample_template, mocker):
|
||||
mocked = mocker.patch('app.celery.provider_tasks.deliver_sms')
|
||||
message_to_deliver = sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template, scheduled_for="2017-05-01 13:50:00")
|
||||
template=sample_template, scheduled_for="2017-05-01 13")
|
||||
sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template, scheduled_for="2017-05-01 10:50:00", status='delivered')
|
||||
template=sample_template, scheduled_for="2017-05-01 10", status='delivered')
|
||||
sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template)
|
||||
sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template, scheduled_for="2017-05-01 14:30:00")
|
||||
template=sample_template, scheduled_for="2017-05-01 14")
|
||||
|
||||
send_scheduled_notifications()
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ def sample_notification(
|
||||
scheduled_notification = ScheduledNotification(id=uuid.uuid4(),
|
||||
notification_id=notification.id,
|
||||
scheduled_for=datetime.strptime(scheduled_for,
|
||||
"%Y-%m-%d %H:%M:%S"))
|
||||
"%Y-%m-%d %H"))
|
||||
db.session.add(scheduled_notification)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@@ -716,10 +716,10 @@ def test_save_notification_with_no_job(sample_template, mmg_provider):
|
||||
assert notification_from_db.status == 'created'
|
||||
|
||||
|
||||
def test_get_notification_by_id(notify_db, notify_db_session, client, sample_template):
|
||||
def test_get_notification_by_id(notify_db, notify_db_session, sample_template):
|
||||
notification = sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template,
|
||||
scheduled_for='2017-05-05 14:00:00',
|
||||
scheduled_for='2017-05-05 14',
|
||||
status='created')
|
||||
notification_from_db = get_notification_with_personalisation(
|
||||
sample_template.service.id,
|
||||
@@ -727,7 +727,7 @@ def test_get_notification_by_id(notify_db, notify_db_session, client, sample_tem
|
||||
key_type=None
|
||||
)
|
||||
assert notification == notification_from_db
|
||||
assert notification_from_db.scheduled_notification.scheduled_for == datetime(2017, 5, 5, 14, 0)
|
||||
assert notification_from_db.scheduled_notification.scheduled_for == datetime(2017, 5, 5, 14)
|
||||
|
||||
|
||||
def test_get_notifications_by_reference(notify_db, notify_db_session, sample_service):
|
||||
@@ -1702,8 +1702,9 @@ def test_dao_get_notifications_by_to_field_search_ignores_spaces(sample_template
|
||||
|
||||
|
||||
def test_dao_created_scheduled_notification(sample_notification):
|
||||
|
||||
scheduled_notification = ScheduledNotification(notification_id=sample_notification.id,
|
||||
scheduled_for="2017-01-05 14:00:00")
|
||||
scheduled_for=datetime.strptime("2017-01-05 14", "%Y-%m-%d %H"))
|
||||
dao_created_scheduled_notification(scheduled_notification)
|
||||
saved_notification = ScheduledNotification.query.all()
|
||||
assert len(saved_notification) == 1
|
||||
@@ -1713,10 +1714,10 @@ def test_dao_created_scheduled_notification(sample_notification):
|
||||
|
||||
def test_dao_get_scheduled_notifications(notify_db, notify_db_session, sample_template):
|
||||
notification_1 = sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template, scheduled_for='2017-05-05 14:00:00',
|
||||
template=sample_template, scheduled_for='2017-05-05 14',
|
||||
status='created')
|
||||
sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template, scheduled_for='2017-05-04 14:00:00', status='delivered')
|
||||
template=sample_template, scheduled_for='2017-05-04 14', status='delivered')
|
||||
sample_notification(notify_db=notify_db, notify_db_session=notify_db_session,
|
||||
template=sample_template, status='created')
|
||||
scheduled_notifications = dao_get_scheduled_notifications()
|
||||
|
||||
@@ -7,13 +7,14 @@ from sqlalchemy.exc import SQLAlchemyError
|
||||
from freezegun import freeze_time
|
||||
from collections import namedtuple
|
||||
|
||||
from app.models import Template, Notification, NotificationHistory
|
||||
from app.models import Template, Notification, NotificationHistory, ScheduledNotification
|
||||
from app.notifications import SendNotificationToQueueError
|
||||
from app.notifications.process_notifications import (
|
||||
create_content_for_notification,
|
||||
persist_notification,
|
||||
send_notification_to_queue,
|
||||
simulated_recipient
|
||||
simulated_recipient,
|
||||
persist_scheduled_notification
|
||||
)
|
||||
from notifications_utils.recipients import validate_and_format_phone_number, validate_and_format_email_address
|
||||
from app.utils import cache_key_for_service_template_counter
|
||||
@@ -358,3 +359,11 @@ def test_persist_notification_with_international_info_does_not_store_for_email(
|
||||
assert persisted_notification.international is False
|
||||
assert persisted_notification.phone_prefix is None
|
||||
assert persisted_notification.rate_multiplier is None
|
||||
|
||||
|
||||
def test_persist_scheduled_notification(sample_notification):
|
||||
persist_scheduled_notification(sample_notification.id, '2017-05-12 14')
|
||||
scheduled_notification = ScheduledNotification.query.all()
|
||||
assert len(scheduled_notification) == 1
|
||||
assert scheduled_notification[0].notification_id == sample_notification.id
|
||||
assert scheduled_notification[0].scheduled_for == datetime.datetime(2017, 5, 12, 13, 0)
|
||||
|
||||
@@ -4,8 +4,8 @@ import pytest
|
||||
from app.utils import (
|
||||
get_london_midnight_in_utc,
|
||||
get_midnight_for_day_before,
|
||||
get_utc_time_in_bst
|
||||
)
|
||||
convert_utc_time_in_bst,
|
||||
convert_bst_to_utc)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('date, expected_date', [
|
||||
@@ -32,7 +32,15 @@ def test_get_midnight_for_day_before_returns_expected_date(date, expected_date):
|
||||
(datetime(2017, 3, 28, 10, 0), datetime(2017, 3, 28, 11, 0)),
|
||||
(datetime(2017, 10, 28, 1, 0), datetime(2017, 10, 28, 2, 0)),
|
||||
(datetime(2017, 10, 29, 1, 0), datetime(2017, 10, 29, 1, 0)),
|
||||
(datetime(2017, 5, 12, 14), datetime(2017, 5, 12, 15, 0))
|
||||
])
|
||||
def test_get_utc_in_bst_returns_expected_date(date, expected_date):
|
||||
ret_date = get_utc_time_in_bst(date)
|
||||
ret_date = convert_utc_time_in_bst(date)
|
||||
assert ret_date == expected_date
|
||||
|
||||
|
||||
def test_convert_bst_to_utc():
|
||||
bst = "2017-05-12 13"
|
||||
bst_datetime = datetime.strptime(bst, "%Y-%m-%d %H")
|
||||
utc = convert_bst_to_utc(bst_datetime)
|
||||
assert utc == datetime(2017, 5, 12, 12, 0)
|
||||
|
||||
@@ -20,12 +20,12 @@ def test_get_notification_by_id_returns_200(
|
||||
):
|
||||
sample_notification = create_sample_notification(
|
||||
notify_db, notify_db_session, billable_units=billable_units, sent_by=provider,
|
||||
scheduled_for="2017-05-12 14:00:00"
|
||||
scheduled_for="2017-05-12 14"
|
||||
)
|
||||
|
||||
another = create_sample_notification(
|
||||
notify_db, notify_db_session, billable_units=billable_units, sent_by=provider,
|
||||
scheduled_for="2017-06-12 14:00:00"
|
||||
scheduled_for="2017-06-12 14"
|
||||
)
|
||||
auth_header = create_authorization_header(service_id=sample_notification.service_id)
|
||||
response = client.get(
|
||||
@@ -63,7 +63,7 @@ def test_get_notification_by_id_returns_200(
|
||||
"subject": None,
|
||||
'sent_at': sample_notification.sent_at,
|
||||
'completed_at': sample_notification.completed_at(),
|
||||
'scheduled_for': '2017-05-12T14:00:00.000000Z'
|
||||
'scheduled_for': '2017-05-12 14'
|
||||
}
|
||||
|
||||
assert json_response == expected_response
|
||||
@@ -139,7 +139,7 @@ def test_get_notification_by_reference_returns_200(client, notify_db, notify_db_
|
||||
|
||||
def test_get_notifications_returns_scheduled_for(client, notify_db, notify_db_session):
|
||||
sample_notification_with_reference = create_sample_notification(
|
||||
notify_db, notify_db_session, client_reference='some-client-reference', scheduled_for='2017-05-23 16:00:00')
|
||||
notify_db, notify_db_session, client_reference='some-client-reference', scheduled_for='2017-05-23 16')
|
||||
|
||||
auth_header = create_authorization_header(service_id=sample_notification_with_reference.service_id)
|
||||
response = client.get(
|
||||
@@ -153,7 +153,7 @@ def test_get_notifications_returns_scheduled_for(client, notify_db, notify_db_se
|
||||
assert len(json_response['notifications']) == 1
|
||||
|
||||
assert json_response['notifications'][0]['id'] == str(sample_notification_with_reference.id)
|
||||
assert json_response['notifications'][0]['scheduled_for'] == "2017-05-23T16:00:00.000000Z"
|
||||
assert json_response['notifications'][0]['scheduled_for'] == "2017-05-23 16"
|
||||
|
||||
|
||||
def test_get_notification_by_reference_nonexistent_reference_returns_no_notifications(client, sample_service):
|
||||
|
||||
@@ -360,7 +360,7 @@ def test_get_notifications_response_with_email_and_phone_number():
|
||||
def test_post_schema_valid_scheduled_for(schema):
|
||||
j = {"template_id": str(uuid.uuid4()),
|
||||
"email_address": "joe@gmail.com",
|
||||
"scheduled_for": "2017-05-12 13:00:00"}
|
||||
"scheduled_for": "2017-05-12 13"}
|
||||
if schema == post_email_request_schema:
|
||||
j.update({"email_address": "joe@gmail.com"})
|
||||
else:
|
||||
@@ -369,7 +369,7 @@ def test_post_schema_valid_scheduled_for(schema):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("invalid_datetime",
|
||||
["2017-05-12 13:00", "13:00:00 2017-01-01"])
|
||||
["2017-05-12 13:00:00", "13:00:00 2017-01-01"])
|
||||
@pytest.mark.parametrize("schema",
|
||||
[post_email_request_schema, post_sms_request_schema])
|
||||
def test_post_email_schema_invalid_scheduled_for(invalid_datetime, schema):
|
||||
@@ -385,4 +385,4 @@ def test_post_email_schema_invalid_scheduled_for(invalid_datetime, schema):
|
||||
assert error['status_code'] == 400
|
||||
assert error['errors'] == [{'error': 'ValidationError',
|
||||
'message': "scheduled_for datetime format is invalid. Use the format: "
|
||||
"YYYY-MM-DD HH:MM:SS, for example 2017-05-30 13:00:00"}]
|
||||
"YYYY-MM-DD HH, for example 2017-05-30 13"}]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
from flask import json
|
||||
|
||||
from app import DATETIME_FORMAT
|
||||
from app.models import Notification, ScheduledNotification
|
||||
from app.v2.errors import RateLimitError
|
||||
from tests import create_authorization_header
|
||||
@@ -358,7 +358,7 @@ def test_post_notification_with_scheduled_for(client, sample_template, sample_em
|
||||
data = {
|
||||
key_send_to: send_to,
|
||||
'template_id': str(sample_email_template.id) if notification_type == 'email' else str(sample_template.id),
|
||||
'scheduled_for': '2017-05-14 15:00:00'
|
||||
'scheduled_for': '2017-05-14 14'
|
||||
}
|
||||
auth_header = create_authorization_header(service_id=sample_template.service_id)
|
||||
|
||||
@@ -370,4 +370,4 @@ def test_post_notification_with_scheduled_for(client, sample_template, sample_em
|
||||
scheduled_notification = ScheduledNotification.query.all()
|
||||
assert len(scheduled_notification) == 1
|
||||
assert resp_json["id"] == str(scheduled_notification[0].notification_id)
|
||||
assert resp_json["scheduled_for"] == scheduled_notification[0].scheduled_for.strftime(DATETIME_FORMAT)
|
||||
assert resp_json["scheduled_for"] == '2017-05-14 14'
|
||||
|
||||
Reference in New Issue
Block a user