Merge branch 'master' into remove-nasty-query-from-dashboard

Conflicts:
	app/service/rest.py
	tests/app/service/test_rest.py
This commit is contained in:
Martyn Inglis
2017-06-01 13:11:54 +01:00
64 changed files with 2012 additions and 648 deletions

View File

@@ -5,9 +5,17 @@ from datetime import (
date)
from flask import current_app
from notifications_utils.recipients import (
validate_and_format_phone_number,
validate_and_format_email_address,
InvalidPhoneError,
InvalidEmailError,
)
from werkzeug.datastructures import MultiDict
from sqlalchemy import (desc, func, or_, and_, asc)
from sqlalchemy.orm import joinedload
from notifications_utils.international_billing_rates import INTERNATIONAL_BILLING_RATES
from app import db, create_uuid
from app.dao import days_ago
@@ -27,7 +35,7 @@ from app.models import (
NOTIFICATION_PERMANENT_FAILURE,
KEY_TYPE_NORMAL, KEY_TYPE_TEST,
LETTER_TYPE,
NOTIFICATION_SENT)
NOTIFICATION_SENT, ScheduledNotification)
from app.dao.dao_utils import transactional
from app.statsd_decorators import statsd
@@ -163,6 +171,10 @@ def _decide_permanent_temporary_failure(current_status, status):
return status
def country_records_delivery(phone_prefix):
return INTERNATIONAL_BILLING_RATES[phone_prefix]['attributes']['dlr'].lower() == 'yes'
def _update_notification_status(notification, status):
status = _decide_permanent_temporary_failure(current_status=notification.status, status=status)
notification.status = status
@@ -182,7 +194,10 @@ def update_notification_status_by_id(notification_id, status):
Notification.status == NOTIFICATION_SENT
)).first()
if not notification or notification.status == NOTIFICATION_SENT:
if not notification:
return None
if notification.international and not country_records_delivery(notification.phone_prefix):
return None
return _update_notification_status(
@@ -351,11 +366,11 @@ def _filter_query(query, filter_dict=None):
@statsd(namespace="dao")
def delete_notifications_created_more_than_a_week_ago(status):
def delete_notifications_created_more_than_a_week_ago_by_type(notification_type):
seven_days_ago = date.today() - timedelta(days=7)
deleted = db.session.query(Notification).filter(
func.date(Notification.created_at) < seven_days_ago,
Notification.status == status,
Notification.notification_type == notification_type,
).delete(synchronize_session='fetch')
db.session.commit()
return deleted
@@ -459,7 +474,48 @@ def dao_update_notifications_sent_to_dvla(job_id, provider):
@statsd(namespace="dao")
def dao_get_notifications_by_to_field(service_id, search_term):
return Notification.query.filter(
def dao_get_notifications_by_to_field(service_id, search_term, statuses=None):
try:
normalised = validate_and_format_phone_number(search_term)
except InvalidPhoneError:
try:
normalised = validate_and_format_email_address(search_term)
except InvalidEmailError:
normalised = search_term
filters = [
Notification.service_id == service_id,
func.replace(func.lower(Notification.to), " ", "") == search_term.lower().replace(" ", "")).all()
Notification.normalised_to == normalised
]
if statuses:
filters.append(Notification.status.in_(statuses))
results = db.session.query(Notification).filter(*filters).all()
return results
@statsd(namespace="dao")
def dao_created_scheduled_notification(scheduled_notification):
db.session.add(scheduled_notification)
db.session.commit()
@statsd(namespace="dao")
def dao_get_scheduled_notifications():
notifications = Notification.query.join(
ScheduledNotification
).filter(
ScheduledNotification.scheduled_for < datetime.utcnow(),
ScheduledNotification.pending).all()
return notifications
def set_scheduled_notification_to_processed(notification_id):
db.session.query(ScheduledNotification).filter(
ScheduledNotification.notification_id == notification_id
).update(
{'pending': False}
)
db.session.commit()

View File

@@ -3,6 +3,7 @@ from datetime import date, datetime, timedelta
from sqlalchemy import asc, func
from sqlalchemy.orm import joinedload
from flask import current_app
from app import db
from app.dao.dao_utils import (
@@ -31,7 +32,9 @@ from app.models import (
TEMPLATE_TYPES,
JobStatistics,
SMS_TYPE,
EMAIL_TYPE
EMAIL_TYPE,
INTERNATIONAL_SMS_TYPE,
LETTER_TYPE
)
from app.service.statistics import format_monthly_template_notification_stats
from app.statsd_decorators import statsd
@@ -129,6 +132,12 @@ def dao_fetch_service_by_id_and_user(service_id, user_id):
@transactional
@version_class(Service)
def dao_create_service(service, user, service_id=None, service_permissions=[SMS_TYPE, EMAIL_TYPE]):
# the default property does not appear to work when there is a difference between the sqlalchemy schema and the
# db schema (ie: during a migration), so we have to set sms_sender manually here. After the GOVUK sms_sender
# migration is completed, this code should be able to be removed.
if not service.sms_sender:
service.sms_sender = current_app.config['FROM_NUMBER']
from app.dao.permissions_dao import permission_dao
service.users.append(user)
permission_dao.add_default_service_permissions_for_user(user, service)
@@ -136,10 +145,17 @@ def dao_create_service(service, user, service_id=None, service_permissions=[SMS_
service.active = True
service.research_mode = False
for permission in service_permissions:
service_permission = ServicePermission(service_id=service.id, permission=permission)
db.session.add(service_permission)
def deprecate_process_service_permissions():
for permission in service_permissions:
service_permission = ServicePermission(service_id=service.id, permission=permission)
service.permissions.append(service_permission)
if permission == INTERNATIONAL_SMS_TYPE:
service.can_send_international_sms = True
if permission == LETTER_TYPE:
service.can_send_letters = True
deprecate_process_service_permissions()
db.session.add(service)