2016-04-14 15:09:59 +01:00
|
|
|
import uuid
|
2017-11-09 10:32:39 +00:00
|
|
|
from datetime import date, datetime, timedelta, time
|
2016-04-14 15:09:59 +01:00
|
|
|
|
2018-02-06 09:35:33 +00:00
|
|
|
from notifications_utils.statsd_decorators import statsd
|
2017-11-09 10:32:39 +00:00
|
|
|
from sqlalchemy import asc, func, extract
|
2017-09-25 09:44:16 +01:00
|
|
|
from sqlalchemy.orm import joinedload
|
2017-05-31 17:31:06 +01:00
|
|
|
from flask import current_app
|
2016-02-19 15:53:15 +00:00
|
|
|
|
2016-07-18 12:03:44 +01:00
|
|
|
from app import db
|
2016-04-14 15:09:59 +01:00
|
|
|
from app.dao.dao_utils import (
|
|
|
|
|
transactional,
|
2016-04-21 18:10:57 +01:00
|
|
|
version_class
|
2016-04-14 15:09:59 +01:00
|
|
|
)
|
2017-10-30 15:17:01 +00:00
|
|
|
from app.dao.date_util import get_financial_year
|
2017-09-11 17:40:37 +01:00
|
|
|
from app.dao.service_sms_sender_dao import insert_service_sms_sender
|
2017-11-14 14:32:34 +00:00
|
|
|
from app.dao.stats_template_usage_by_month_dao import dao_get_template_usage_stats_by_service
|
2016-05-06 11:07:11 +01:00
|
|
|
from app.models import (
|
2017-11-14 14:32:34 +00:00
|
|
|
AnnualBilling,
|
2016-05-06 11:07:11 +01:00
|
|
|
ApiKey,
|
2017-08-16 12:27:42 +01:00
|
|
|
InboundNumber,
|
2017-11-14 14:32:34 +00:00
|
|
|
InvitedUser,
|
2016-05-06 11:07:11 +01:00
|
|
|
Job,
|
|
|
|
|
Notification,
|
2017-11-14 14:32:34 +00:00
|
|
|
NotificationHistory,
|
2016-05-06 11:07:11 +01:00
|
|
|
Permission,
|
2016-09-16 13:47:09 +01:00
|
|
|
Service,
|
2017-05-17 14:09:18 +01:00
|
|
|
ServicePermission,
|
2017-11-14 14:32:34 +00:00
|
|
|
ServiceSmsSender,
|
|
|
|
|
Template,
|
|
|
|
|
TemplateHistory,
|
|
|
|
|
TemplateRedacted,
|
|
|
|
|
User,
|
|
|
|
|
VerifyCode,
|
|
|
|
|
EMAIL_TYPE,
|
|
|
|
|
INTERNATIONAL_SMS_TYPE,
|
2017-01-30 15:17:26 +00:00
|
|
|
KEY_TYPE_TEST,
|
2017-05-17 14:09:18 +01:00
|
|
|
SMS_TYPE,
|
2018-01-24 11:53:22 +00:00
|
|
|
LETTER_TYPE,
|
2017-10-19 11:06:28 +01:00
|
|
|
)
|
2017-03-29 11:47:41 +01:00
|
|
|
from app.utils import get_london_month_from_utc_column, get_london_midnight_in_utc
|
2016-05-06 11:07:11 +01:00
|
|
|
|
2017-10-19 11:06:28 +01:00
|
|
|
DEFAULT_SERVICE_PERMISSIONS = [
|
|
|
|
|
SMS_TYPE,
|
|
|
|
|
EMAIL_TYPE,
|
2018-01-24 11:53:22 +00:00
|
|
|
LETTER_TYPE,
|
2017-10-19 11:06:28 +01:00
|
|
|
INTERNATIONAL_SMS_TYPE,
|
|
|
|
|
]
|
|
|
|
|
|
2016-02-19 15:53:15 +00:00
|
|
|
|
2016-11-09 11:45:39 +00:00
|
|
|
def dao_fetch_all_services(only_active=False):
|
|
|
|
|
query = Service.query.order_by(
|
2016-07-15 11:34:59 +01:00
|
|
|
asc(Service.created_at)
|
|
|
|
|
).options(
|
|
|
|
|
joinedload('users')
|
2016-11-09 11:45:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if only_active:
|
|
|
|
|
query = query.filter(Service.active)
|
|
|
|
|
|
|
|
|
|
return query.all()
|
2016-02-19 15:53:15 +00:00
|
|
|
|
|
|
|
|
|
2016-11-09 15:07:23 +00:00
|
|
|
def dao_fetch_service_by_id(service_id, only_active=False):
|
|
|
|
|
query = Service.query.filter_by(
|
2016-07-15 11:34:59 +01:00
|
|
|
id=service_id
|
|
|
|
|
).options(
|
|
|
|
|
joinedload('users')
|
2016-11-09 15:07:23 +00:00
|
|
|
)
|
2016-02-19 15:53:15 +00:00
|
|
|
|
2016-11-09 15:07:23 +00:00
|
|
|
if only_active:
|
|
|
|
|
query = query.filter(Service.active)
|
2016-02-19 15:53:15 +00:00
|
|
|
|
2016-11-09 15:07:23 +00:00
|
|
|
return query.one()
|
|
|
|
|
|
|
|
|
|
|
2017-08-23 13:03:52 +01:00
|
|
|
def dao_fetch_service_by_inbound_number(number):
|
2017-08-16 12:27:42 +01:00
|
|
|
inbound_number = InboundNumber.query.filter(
|
2017-08-23 13:03:52 +01:00
|
|
|
InboundNumber.number == number,
|
2017-08-16 16:27:42 +01:00
|
|
|
InboundNumber.active
|
2017-08-16 12:27:42 +01:00
|
|
|
).first()
|
|
|
|
|
|
|
|
|
|
if not inbound_number:
|
2017-08-23 13:03:52 +01:00
|
|
|
return None
|
2017-08-16 12:27:42 +01:00
|
|
|
|
2017-05-22 11:26:47 +01:00
|
|
|
return Service.query.filter(
|
2017-08-23 13:03:52 +01:00
|
|
|
Service.id == inbound_number.service_id
|
|
|
|
|
).first()
|
2017-05-22 11:26:47 +01:00
|
|
|
|
|
|
|
|
|
2017-05-05 15:22:21 +01:00
|
|
|
def dao_fetch_service_by_id_with_api_keys(service_id, only_active=False):
|
|
|
|
|
query = Service.query.filter_by(
|
|
|
|
|
id=service_id
|
|
|
|
|
).options(
|
|
|
|
|
joinedload('api_keys')
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if only_active:
|
|
|
|
|
query = query.filter(Service.active)
|
|
|
|
|
|
|
|
|
|
return query.one()
|
|
|
|
|
|
|
|
|
|
|
2016-11-09 15:07:23 +00:00
|
|
|
def dao_fetch_all_services_by_user(user_id, only_active=False):
|
|
|
|
|
query = Service.query.filter(
|
2016-07-15 11:34:59 +01:00
|
|
|
Service.users.any(id=user_id)
|
|
|
|
|
).order_by(
|
|
|
|
|
asc(Service.created_at)
|
|
|
|
|
).options(
|
|
|
|
|
joinedload('users')
|
2016-11-09 15:07:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if only_active:
|
|
|
|
|
query = query.filter(Service.active)
|
|
|
|
|
|
|
|
|
|
return query.all()
|
2016-02-19 15:53:15 +00:00
|
|
|
|
|
|
|
|
|
2016-11-10 17:07:02 +00:00
|
|
|
@transactional
|
|
|
|
|
@version_class(Service)
|
|
|
|
|
@version_class(Template, TemplateHistory)
|
|
|
|
|
@version_class(ApiKey)
|
2017-01-30 16:32:44 +00:00
|
|
|
def dao_archive_service(service_id):
|
2016-11-10 17:07:02 +00:00
|
|
|
# have to eager load templates and api keys so that we don't flush when we loop through them
|
2016-11-11 12:43:51 +00:00
|
|
|
# to ensure that db.session still contains the models when it comes to creating history objects
|
2016-11-10 17:07:02 +00:00
|
|
|
service = Service.query.options(
|
|
|
|
|
joinedload('templates'),
|
2017-06-29 10:34:38 +01:00
|
|
|
joinedload('templates.template_redacted'),
|
2016-11-10 17:07:02 +00:00
|
|
|
joinedload('api_keys'),
|
|
|
|
|
).filter(Service.id == service_id).one()
|
|
|
|
|
|
|
|
|
|
service.active = False
|
|
|
|
|
service.name = '_archived_' + service.name
|
|
|
|
|
service.email_from = '_archived_' + service.email_from
|
|
|
|
|
|
|
|
|
|
for template in service.templates:
|
2016-11-14 14:10:40 +00:00
|
|
|
if not template.archived:
|
|
|
|
|
template.archived = True
|
2016-11-10 17:07:02 +00:00
|
|
|
|
|
|
|
|
for api_key in service.api_keys:
|
2016-11-14 14:10:40 +00:00
|
|
|
if not api_key.expiry_date:
|
|
|
|
|
api_key.expiry_date = datetime.utcnow()
|
2016-11-10 17:07:02 +00:00
|
|
|
|
|
|
|
|
|
2016-02-19 15:53:15 +00:00
|
|
|
def dao_fetch_service_by_id_and_user(service_id, user_id):
|
2016-07-15 11:34:59 +01:00
|
|
|
return Service.query.filter(
|
|
|
|
|
Service.users.any(id=user_id),
|
|
|
|
|
Service.id == service_id
|
|
|
|
|
).options(
|
|
|
|
|
joinedload('users')
|
|
|
|
|
).one()
|
2016-02-19 15:53:15 +00:00
|
|
|
|
|
|
|
|
|
2016-04-14 15:09:59 +01:00
|
|
|
@transactional
|
2016-04-21 18:10:57 +01:00
|
|
|
@version_class(Service)
|
2017-12-06 11:01:18 +00:00
|
|
|
def dao_create_service(service, user, service_id=None, service_permissions=None):
|
2017-05-31 17:31:06 +01:00
|
|
|
# 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.
|
|
|
|
|
|
2017-10-19 11:06:28 +01:00
|
|
|
if service_permissions is None:
|
|
|
|
|
service_permissions = DEFAULT_SERVICE_PERMISSIONS
|
|
|
|
|
|
2016-04-14 15:09:59 +01:00
|
|
|
from app.dao.permissions_dao import permission_dao
|
|
|
|
|
service.users.append(user)
|
|
|
|
|
permission_dao.add_default_service_permissions_for_user(user, service)
|
2017-02-13 15:46:06 +00:00
|
|
|
service.id = service_id or uuid.uuid4() # must be set now so version history model can use same id
|
2016-11-08 13:49:47 +00:00
|
|
|
service.active = True
|
2016-05-31 12:49:06 +01:00
|
|
|
service.research_mode = False
|
2017-12-04 13:24:53 +00:00
|
|
|
service.crown = service.organisation_type == 'central'
|
2017-05-17 14:09:18 +01:00
|
|
|
|
2017-06-23 17:06:09 +01:00
|
|
|
for permission in service_permissions:
|
|
|
|
|
service_permission = ServicePermission(service_id=service.id, permission=permission)
|
|
|
|
|
service.permissions.append(service_permission)
|
2017-05-17 14:09:18 +01:00
|
|
|
|
2017-11-07 14:26:18 +00:00
|
|
|
# do we just add the default - or will we get a value from FE?
|
|
|
|
|
insert_service_sms_sender(service, current_app.config['FROM_NUMBER'])
|
2016-04-14 15:09:59 +01:00
|
|
|
db.session.add(service)
|
2016-01-07 17:31:17 +00:00
|
|
|
|
|
|
|
|
|
2016-04-14 15:09:59 +01:00
|
|
|
@transactional
|
2016-04-21 18:10:57 +01:00
|
|
|
@version_class(Service)
|
2016-02-19 15:53:15 +00:00
|
|
|
def dao_update_service(service):
|
|
|
|
|
db.session.add(service)
|
2016-01-12 10:39:49 +00:00
|
|
|
|
|
|
|
|
|
2017-05-04 17:09:04 +01:00
|
|
|
def dao_add_user_to_service(service, user, permissions=None):
|
|
|
|
|
permissions = permissions or []
|
2016-03-23 16:30:47 +00:00
|
|
|
try:
|
|
|
|
|
from app.dao.permissions_dao import permission_dao
|
|
|
|
|
service.users.append(user)
|
|
|
|
|
permission_dao.set_user_service_permission(user, service, permissions, _commit=False)
|
|
|
|
|
db.session.add(service)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
db.session.rollback()
|
|
|
|
|
raise e
|
|
|
|
|
else:
|
|
|
|
|
db.session.commit()
|
2016-02-19 15:53:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def dao_remove_user_from_service(service, user):
|
2016-03-22 13:14:23 +00:00
|
|
|
try:
|
|
|
|
|
from app.dao.permissions_dao import permission_dao
|
|
|
|
|
permission_dao.remove_user_service_permissions(user, service)
|
|
|
|
|
service.users.remove(user)
|
|
|
|
|
db.session.add(service)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
db.session.rollback()
|
|
|
|
|
raise e
|
|
|
|
|
else:
|
|
|
|
|
db.session.commit()
|
2016-05-06 11:07:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def delete_service_and_all_associated_db_objects(service):
|
|
|
|
|
|
|
|
|
|
def _delete_commit(query):
|
2017-06-28 17:19:53 +01:00
|
|
|
query.delete(synchronize_session=False)
|
2016-05-06 11:07:11 +01:00
|
|
|
db.session.commit()
|
|
|
|
|
|
2017-06-28 17:19:53 +01:00
|
|
|
subq = db.session.query(Template.id).filter_by(service=service).subquery()
|
|
|
|
|
_delete_commit(TemplateRedacted.query.filter(TemplateRedacted.template_id.in_(subq)))
|
|
|
|
|
|
2017-09-11 17:40:37 +01:00
|
|
|
_delete_commit(ServiceSmsSender.query.filter_by(service=service))
|
2016-05-06 11:07:11 +01:00
|
|
|
_delete_commit(InvitedUser.query.filter_by(service=service))
|
|
|
|
|
_delete_commit(Permission.query.filter_by(service=service))
|
2016-07-11 16:48:32 +01:00
|
|
|
_delete_commit(NotificationHistory.query.filter_by(service=service))
|
2016-05-06 11:07:11 +01:00
|
|
|
_delete_commit(Notification.query.filter_by(service=service))
|
2017-07-03 13:40:13 +01:00
|
|
|
_delete_commit(Job.query.filter_by(service=service))
|
2016-05-06 11:07:11 +01:00
|
|
|
_delete_commit(Template.query.filter_by(service=service))
|
2016-08-02 16:23:14 +01:00
|
|
|
_delete_commit(TemplateHistory.query.filter_by(service_id=service.id))
|
2017-05-17 14:09:18 +01:00
|
|
|
_delete_commit(ServicePermission.query.filter_by(service_id=service.id))
|
2017-08-02 15:35:56 +01:00
|
|
|
_delete_commit(ApiKey.query.filter_by(service=service))
|
|
|
|
|
_delete_commit(ApiKey.get_history_model().query.filter_by(service_id=service.id))
|
2017-10-25 11:35:13 +01:00
|
|
|
_delete_commit(AnnualBilling.query.filter_by(service_id=service.id))
|
2016-05-06 11:07:11 +01:00
|
|
|
|
|
|
|
|
verify_codes = VerifyCode.query.join(User).filter(User.id.in_([x.id for x in service.users]))
|
|
|
|
|
list(map(db.session.delete, verify_codes))
|
|
|
|
|
db.session.commit()
|
|
|
|
|
users = [x for x in service.users]
|
|
|
|
|
map(service.users.remove, users)
|
|
|
|
|
[service.users.remove(x) for x in users]
|
2016-05-11 15:52:49 +01:00
|
|
|
_delete_commit(Service.get_history_model().query.filter_by(id=service.id))
|
2016-05-06 11:07:11 +01:00
|
|
|
db.session.delete(service)
|
|
|
|
|
db.session.commit()
|
|
|
|
|
list(map(db.session.delete, users))
|
|
|
|
|
db.session.commit()
|
2016-07-18 12:03:44 +01:00
|
|
|
|
|
|
|
|
|
2016-08-05 10:44:43 +01:00
|
|
|
@statsd(namespace="dao")
|
2016-07-18 12:03:44 +01:00
|
|
|
def dao_fetch_stats_for_service(service_id):
|
2018-05-01 10:47:47 +01:00
|
|
|
# We want 7 days inclusive
|
|
|
|
|
start_date = get_london_midnight_in_utc(date.today() - timedelta(days=6))
|
2018-04-24 14:05:48 +01:00
|
|
|
return _stats_for_service_query(service_id).filter(
|
2018-05-01 16:48:34 +01:00
|
|
|
Notification.created_at >= start_date
|
2018-04-24 14:05:48 +01:00
|
|
|
).all()
|
2016-07-22 15:16:24 +01:00
|
|
|
|
|
|
|
|
|
2016-08-05 10:44:43 +01:00
|
|
|
@statsd(namespace="dao")
|
2016-07-22 15:16:24 +01:00
|
|
|
def dao_fetch_todays_stats_for_service(service_id):
|
|
|
|
|
return _stats_for_service_query(service_id).filter(
|
|
|
|
|
func.date(Notification.created_at) == date.today()
|
|
|
|
|
).all()
|
|
|
|
|
|
|
|
|
|
|
2016-10-03 10:57:10 +01:00
|
|
|
def fetch_todays_total_message_count(service_id):
|
|
|
|
|
result = db.session.query(
|
|
|
|
|
func.count(Notification.id).label('count')
|
|
|
|
|
).filter(
|
|
|
|
|
Notification.service_id == service_id,
|
|
|
|
|
Notification.key_type != KEY_TYPE_TEST,
|
|
|
|
|
func.date(Notification.created_at) == date.today()
|
|
|
|
|
).group_by(
|
|
|
|
|
Notification.notification_type,
|
|
|
|
|
Notification.status,
|
|
|
|
|
).first()
|
|
|
|
|
return 0 if result is None else result.count
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 15:16:24 +01:00
|
|
|
def _stats_for_service_query(service_id):
|
2016-07-18 12:03:44 +01:00
|
|
|
return db.session.query(
|
|
|
|
|
Notification.notification_type,
|
2017-07-06 14:20:24 +01:00
|
|
|
Notification.status,
|
2016-07-18 12:03:44 +01:00
|
|
|
func.count(Notification.id).label('count')
|
|
|
|
|
).filter(
|
2016-09-16 13:47:09 +01:00
|
|
|
Notification.service_id == service_id,
|
|
|
|
|
Notification.key_type != KEY_TYPE_TEST
|
2016-07-18 12:03:44 +01:00
|
|
|
).group_by(
|
|
|
|
|
Notification.notification_type,
|
|
|
|
|
Notification.status,
|
2016-07-22 15:16:24 +01:00
|
|
|
)
|
2016-07-26 11:00:03 +01:00
|
|
|
|
|
|
|
|
|
2016-08-11 17:24:44 +01:00
|
|
|
@statsd(namespace='dao')
|
2017-10-26 12:15:52 +01:00
|
|
|
def dao_fetch_todays_stats_for_all_services(include_from_test_key=True, only_active=True):
|
2018-03-20 15:48:32 +00:00
|
|
|
today = date.today()
|
|
|
|
|
start_date = get_london_midnight_in_utc(today)
|
|
|
|
|
end_date = get_london_midnight_in_utc(today + timedelta(days=1))
|
2017-09-15 14:40:56 +01:00
|
|
|
|
2017-10-25 10:40:02 +01:00
|
|
|
subquery = db.session.query(
|
2016-08-11 17:24:44 +01:00
|
|
|
Notification.notification_type,
|
2017-07-06 14:20:24 +01:00
|
|
|
Notification.status,
|
2016-08-19 16:36:20 +01:00
|
|
|
Notification.service_id,
|
2016-08-11 17:24:44 +01:00
|
|
|
func.count(Notification.id).label('count')
|
|
|
|
|
).filter(
|
2018-03-20 15:48:32 +00:00
|
|
|
Notification.created_at >= start_date,
|
|
|
|
|
Notification.created_at < end_date
|
2016-08-11 17:24:44 +01:00
|
|
|
).group_by(
|
|
|
|
|
Notification.notification_type,
|
|
|
|
|
Notification.status,
|
|
|
|
|
Notification.service_id
|
|
|
|
|
)
|
2016-12-02 16:43:24 +00:00
|
|
|
|
|
|
|
|
if not include_from_test_key:
|
2017-10-25 10:40:02 +01:00
|
|
|
subquery = subquery.filter(Notification.key_type != KEY_TYPE_TEST)
|
|
|
|
|
|
|
|
|
|
subquery = subquery.subquery()
|
|
|
|
|
|
|
|
|
|
query = db.session.query(
|
|
|
|
|
Service.id.label('service_id'),
|
|
|
|
|
Service.name,
|
|
|
|
|
Service.restricted,
|
|
|
|
|
Service.research_mode,
|
2017-10-26 12:15:52 +01:00
|
|
|
Service.active,
|
|
|
|
|
Service.created_at,
|
2017-10-25 10:40:02 +01:00
|
|
|
subquery.c.notification_type,
|
|
|
|
|
subquery.c.status,
|
|
|
|
|
subquery.c.count
|
2017-10-26 12:15:52 +01:00
|
|
|
).outerjoin(
|
2017-10-25 10:40:02 +01:00
|
|
|
subquery,
|
|
|
|
|
subquery.c.service_id == Service.id
|
|
|
|
|
).order_by(Service.id)
|
2016-12-02 16:43:24 +00:00
|
|
|
|
2017-10-26 12:15:52 +01:00
|
|
|
if only_active:
|
|
|
|
|
query = query.filter(Service.active)
|
|
|
|
|
|
2016-12-29 13:28:55 +00:00
|
|
|
return query.all()
|
2016-12-28 15:39:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@statsd(namespace='dao')
|
2017-10-26 12:15:52 +01:00
|
|
|
def fetch_stats_by_date_range_for_all_services(start_date, end_date, include_from_test_key=True, only_active=True):
|
2017-03-29 11:47:41 +01:00
|
|
|
start_date = get_london_midnight_in_utc(start_date)
|
2017-04-03 15:52:52 +01:00
|
|
|
end_date = get_london_midnight_in_utc(end_date + timedelta(days=1))
|
2017-04-06 11:18:21 +01:00
|
|
|
table = NotificationHistory
|
2017-03-28 13:30:04 +01:00
|
|
|
|
2017-04-04 16:34:20 +01:00
|
|
|
if start_date >= datetime.utcnow() - timedelta(days=7):
|
2017-04-06 11:18:21 +01:00
|
|
|
table = Notification
|
2017-10-25 16:47:39 +01:00
|
|
|
subquery = db.session.query(
|
2017-04-06 11:18:21 +01:00
|
|
|
table.notification_type,
|
2017-07-06 14:20:24 +01:00
|
|
|
table.status,
|
2017-04-06 11:18:21 +01:00
|
|
|
table.service_id,
|
|
|
|
|
func.count(table.id).label('count')
|
|
|
|
|
).filter(
|
|
|
|
|
table.created_at >= start_date,
|
|
|
|
|
table.created_at < end_date
|
|
|
|
|
).group_by(
|
|
|
|
|
table.notification_type,
|
|
|
|
|
table.status,
|
|
|
|
|
table.service_id
|
|
|
|
|
)
|
|
|
|
|
if not include_from_test_key:
|
2017-10-25 16:47:39 +01:00
|
|
|
subquery = subquery.filter(table.key_type != KEY_TYPE_TEST)
|
|
|
|
|
subquery = subquery.subquery()
|
|
|
|
|
|
|
|
|
|
query = db.session.query(
|
|
|
|
|
Service.id.label('service_id'),
|
|
|
|
|
Service.name,
|
|
|
|
|
Service.restricted,
|
|
|
|
|
Service.research_mode,
|
2017-10-26 12:15:52 +01:00
|
|
|
Service.active,
|
|
|
|
|
Service.created_at,
|
2017-10-25 16:47:39 +01:00
|
|
|
subquery.c.notification_type,
|
|
|
|
|
subquery.c.status,
|
|
|
|
|
subquery.c.count
|
2017-10-26 12:15:52 +01:00
|
|
|
).outerjoin(
|
2017-10-25 16:47:39 +01:00
|
|
|
subquery,
|
|
|
|
|
subquery.c.service_id == Service.id
|
|
|
|
|
).order_by(Service.id)
|
2017-10-26 12:15:52 +01:00
|
|
|
if only_active:
|
|
|
|
|
query = query.filter(Service.active)
|
2016-12-28 15:39:55 +00:00
|
|
|
|
2016-12-29 13:28:55 +00:00
|
|
|
return query.all()
|
2017-01-30 16:32:44 +00:00
|
|
|
|
|
|
|
|
|
2017-10-23 10:58:06 +01:00
|
|
|
@statsd(namespace='dao')
|
|
|
|
|
def fetch_aggregate_stats_by_date_range_for_all_services(start_date, end_date, include_from_test_key=True):
|
|
|
|
|
start_date = get_london_midnight_in_utc(start_date)
|
|
|
|
|
end_date = get_london_midnight_in_utc(end_date + timedelta(days=1))
|
|
|
|
|
table = NotificationHistory
|
|
|
|
|
|
|
|
|
|
if start_date >= datetime.utcnow() - timedelta(days=7):
|
|
|
|
|
table = Notification
|
|
|
|
|
|
|
|
|
|
query = db.session.query(
|
|
|
|
|
table.notification_type,
|
|
|
|
|
table.status,
|
|
|
|
|
func.count(table.id).label('count')
|
|
|
|
|
).filter(
|
|
|
|
|
table.created_at >= start_date,
|
|
|
|
|
table.created_at < end_date
|
|
|
|
|
).group_by(
|
|
|
|
|
table.notification_type,
|
|
|
|
|
table.status
|
|
|
|
|
).order_by(
|
|
|
|
|
table.notification_type
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if not include_from_test_key:
|
|
|
|
|
query = query.filter(table.key_type != KEY_TYPE_TEST)
|
|
|
|
|
|
|
|
|
|
return query.all()
|
|
|
|
|
|
|
|
|
|
|
2017-01-30 16:32:44 +00:00
|
|
|
@transactional
|
|
|
|
|
@version_class(Service)
|
|
|
|
|
@version_class(ApiKey)
|
|
|
|
|
def dao_suspend_service(service_id):
|
|
|
|
|
# have to eager load api keys so that we don't flush when we loop through them
|
|
|
|
|
# to ensure that db.session still contains the models when it comes to creating history objects
|
|
|
|
|
service = Service.query.options(
|
|
|
|
|
joinedload('api_keys'),
|
|
|
|
|
).filter(Service.id == service_id).one()
|
|
|
|
|
|
|
|
|
|
service.active = False
|
|
|
|
|
|
|
|
|
|
for api_key in service.api_keys:
|
|
|
|
|
if not api_key.expiry_date:
|
|
|
|
|
api_key.expiry_date = datetime.utcnow()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@transactional
|
|
|
|
|
@version_class(Service)
|
|
|
|
|
def dao_resume_service(service_id):
|
|
|
|
|
service = Service.query.get(service_id)
|
|
|
|
|
service.active = True
|
2017-05-10 15:58:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def dao_fetch_active_users_for_service(service_id):
|
|
|
|
|
query = User.query.filter(
|
|
|
|
|
User.user_to_service.any(id=service_id),
|
|
|
|
|
User.state == 'active'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return query.all()
|
2017-11-09 10:32:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@statsd(namespace="dao")
|
|
|
|
|
def dao_fetch_monthly_historical_stats_by_template():
|
|
|
|
|
month = get_london_month_from_utc_column(NotificationHistory.created_at)
|
2017-11-09 14:13:42 +00:00
|
|
|
year = func.date_trunc("year", NotificationHistory.created_at)
|
2017-11-09 10:32:39 +00:00
|
|
|
end_date = datetime.combine(date.today(), time.min)
|
|
|
|
|
|
|
|
|
|
return db.session.query(
|
|
|
|
|
NotificationHistory.template_id,
|
2017-11-09 14:13:42 +00:00
|
|
|
extract('month', month).label('month'),
|
|
|
|
|
extract('year', year).label('year'),
|
2017-11-09 10:32:39 +00:00
|
|
|
func.count().label('count')
|
|
|
|
|
).filter(
|
|
|
|
|
NotificationHistory.created_at < end_date
|
|
|
|
|
).group_by(
|
|
|
|
|
NotificationHistory.template_id,
|
|
|
|
|
month,
|
|
|
|
|
year
|
|
|
|
|
).order_by(
|
2017-11-14 14:32:34 +00:00
|
|
|
year,
|
|
|
|
|
month
|
2017-11-09 10:32:39 +00:00
|
|
|
).all()
|
2017-11-14 14:32:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@statsd(namespace="dao")
|
2017-11-15 15:55:00 +00:00
|
|
|
def dao_fetch_monthly_historical_usage_by_template_for_service(service_id, year):
|
2017-11-14 14:32:34 +00:00
|
|
|
|
2017-11-15 15:55:00 +00:00
|
|
|
results = dao_get_template_usage_stats_by_service(service_id, year)
|
2017-11-14 14:32:34 +00:00
|
|
|
|
2017-11-20 10:01:45 +00:00
|
|
|
stats = []
|
2017-11-14 14:32:34 +00:00
|
|
|
for result in results:
|
2017-11-15 15:55:00 +00:00
|
|
|
stat = type("", (), {})()
|
|
|
|
|
stat.template_id = result.template_id
|
2017-11-16 14:41:07 +00:00
|
|
|
stat.template_type = result.template_type
|
2017-11-15 15:55:00 +00:00
|
|
|
stat.name = str(result.name)
|
|
|
|
|
stat.month = result.month
|
|
|
|
|
stat.year = result.year
|
|
|
|
|
stat.count = result.count
|
2018-03-07 15:42:59 +00:00
|
|
|
stat.is_precompiled_letter = result.is_precompiled_letter
|
2017-11-14 14:32:34 +00:00
|
|
|
stats.append(stat)
|
|
|
|
|
|
|
|
|
|
month = get_london_month_from_utc_column(Notification.created_at)
|
2017-11-21 16:29:20 +00:00
|
|
|
year_func = func.date_trunc("year", Notification.created_at)
|
2017-11-14 14:32:34 +00:00
|
|
|
start_date = datetime.combine(date.today(), time.min)
|
|
|
|
|
|
2017-11-21 16:29:20 +00:00
|
|
|
fy_start, fy_end = get_financial_year(year)
|
|
|
|
|
|
|
|
|
|
if fy_start < datetime.now() < fy_end:
|
|
|
|
|
today_results = db.session.query(
|
|
|
|
|
Notification.template_id,
|
2018-03-07 15:42:59 +00:00
|
|
|
Template.is_precompiled_letter,
|
2017-11-21 16:29:20 +00:00
|
|
|
Template.name,
|
|
|
|
|
Template.template_type,
|
|
|
|
|
extract('month', month).label('month'),
|
|
|
|
|
extract('year', year_func).label('year'),
|
|
|
|
|
func.count().label('count')
|
|
|
|
|
).join(
|
|
|
|
|
Template, Notification.template_id == Template.id,
|
|
|
|
|
).filter(
|
|
|
|
|
Notification.created_at >= start_date,
|
2018-02-06 14:31:12 +00:00
|
|
|
Notification.service_id == service_id,
|
|
|
|
|
# we don't want to include test keys
|
|
|
|
|
Notification.key_type != KEY_TYPE_TEST
|
2017-11-21 16:29:20 +00:00
|
|
|
).group_by(
|
|
|
|
|
Notification.template_id,
|
2018-03-05 13:38:41 +00:00
|
|
|
Template.hidden,
|
2017-11-21 16:29:20 +00:00
|
|
|
Template.name,
|
|
|
|
|
Template.template_type,
|
|
|
|
|
month,
|
|
|
|
|
year_func
|
|
|
|
|
).order_by(
|
|
|
|
|
Notification.template_id
|
|
|
|
|
).all()
|
|
|
|
|
|
|
|
|
|
for today_result in today_results:
|
|
|
|
|
add_to_stats = True
|
|
|
|
|
for stat in stats:
|
|
|
|
|
if today_result.template_id == stat.template_id and today_result.month == stat.month \
|
|
|
|
|
and today_result.year == stat.year:
|
|
|
|
|
stat.count = stat.count + today_result.count
|
|
|
|
|
add_to_stats = False
|
|
|
|
|
|
|
|
|
|
if add_to_stats:
|
2018-02-06 14:31:12 +00:00
|
|
|
new_stat = type("StatsTemplateUsageByMonth", (), {})()
|
2017-11-21 16:29:20 +00:00
|
|
|
new_stat.template_id = today_result.template_id
|
|
|
|
|
new_stat.template_type = today_result.template_type
|
|
|
|
|
new_stat.name = today_result.name
|
|
|
|
|
new_stat.month = int(today_result.month)
|
|
|
|
|
new_stat.year = int(today_result.year)
|
|
|
|
|
new_stat.count = today_result.count
|
2018-03-07 15:42:59 +00:00
|
|
|
new_stat.is_precompiled_letter = today_result.is_precompiled_letter
|
2017-11-21 16:29:20 +00:00
|
|
|
stats.append(new_stat)
|
2017-11-14 14:32:34 +00:00
|
|
|
|
|
|
|
|
return stats
|