Merge branch 'master' into remove-stats-from-send

This commit is contained in:
Leo Hemsted
2016-08-09 14:41:00 +01:00
55 changed files with 408 additions and 293 deletions

View File

@@ -1,7 +1,8 @@
from datetime import datetime, date, timedelta
from datetime import datetime, timedelta
from collections import namedtuple
from itertools import groupby
import dateutil
from flask import (
render_template,
url_for,
@@ -9,13 +10,11 @@ from flask import (
jsonify,
current_app
)
from flask_login import login_required
from app.main import main
from app import (
job_api_client,
statistics_api_client,
service_api_client,
template_statistics_client
)
@@ -90,20 +89,10 @@ def usage(service_id):
@login_required
@user_has_permissions('manage_settings', admin_override=True)
def weekly(service_id):
earliest_date = date(2016, 4, 1) # start of tax year
while earliest_date.weekday() != 0: # 0 for monday
earliest_date -= timedelta(days=1)
stats = service_api_client.get_weekly_notification_stats(service_id)['data']
return render_template(
'views/weekly.html',
days=(
add_rates_to(day) for day in
statistics_api_client.get_7_day_aggregate_for_service(
service_id,
date_from=earliest_date
)['data']
),
days=format_weekly_stats_to_list(stats),
now=datetime.utcnow()
)
@@ -199,3 +188,21 @@ def calculate_usage(usage):
'sms_chargeable': max(0, sms_sent - sms_free_allowance),
'sms_rate': sms_rate
}
def format_weekly_stats_to_list(historical_stats):
out = []
for week, weekly_stats in historical_stats.items():
for stats in weekly_stats.values():
stats['failure_rate'] = get_formatted_percentage(stats['failed'], stats['requested'])
week_start = dateutil.parser.parse(week)
week_end = week_start + timedelta(days=6)
weekly_stats.update({
'week_start': week,
'week_end': week_end.date().isoformat(),
'week_end_datetime': week_end,
})
out.append(weekly_stats)
return sorted(out, key=lambda x: x['week_start'], reverse=True)

View File

@@ -8,17 +8,19 @@ from app.main.forms import Feedback
def feedback():
form = Feedback()
if form.validate_on_submit():
user_supplied_email = form.email_address.data != ''
feedback_msg = 'Environment: {}\n{}\n{}'.format(
url_for('main.index', _external=True),
'' if user_supplied_email else '{} (no email address supplied)'.format(form.name.data),
form.feedback.data
)
data = {
'person_email': current_app.config.get('DESKPRO_PERSON_EMAIL'),
'person_email': form.email_address.data or current_app.config.get('DESKPRO_PERSON_EMAIL'),
'person_name': form.name.data or None,
'department_id': current_app.config.get('DESKPRO_DEPT_ID'),
'agent_team_id': current_app.config.get('DESKPRO_ASSIGNED_AGENT_TEAM_ID'),
'subject': 'Notify feedback',
'message': 'Environment: {}\n\n{}\n{}\n{}'.format(
url_for('main.index', _external=True),
form.name.data,
form.email_address.data,
form.feedback.data
)
'message': feedback_msg
}
headers = {
"X-DeskPRO-API-Key": current_app.config.get('DESKPRO_API_KEY'),

View File

@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
import ago
import time
import dateutil
from orderedset import OrderedSet
from datetime import datetime, timedelta, timezone
import ago
from itertools import chain
from flask import (
render_template,
@@ -47,15 +49,14 @@ def _parse_filter_args(filter_dict):
def _set_status_filters(filter_args):
status_filters = filter_args.get('status', [])
all_failure_statuses = ['failed', 'temporary-failure', 'permanent-failure', 'technical-failure']
all_statuses = ['sending', 'delivered'] + all_failure_statuses
if filter_args.get('status'):
if 'processed' in filter_args.get('status') or not filter_args.get('status'):
filter_args['status'] = all_statuses
elif 'failed' in filter_args.get('status'):
filter_args['status'].extend(all_failure_statuses[1:])
else:
filter_args['status'] = all_statuses
all_sending_statuses = ['created', 'sending']
return list(OrderedSet(chain(
(status_filters or all_sending_statuses + ['delivered'] + all_failure_statuses),
all_sending_statuses if 'sending' in status_filters else [],
all_failure_statuses if 'failed' in status_filters else []
)))
@main.route("/services/<service_id>/jobs")
@@ -75,7 +76,7 @@ def view_job(service_id, job_id):
job = job_api_client.get_job(service_id, job_id)['data']
filter_args = _parse_filter_args(request.args)
_set_status_filters(filter_args)
filter_args['status'] = _set_status_filters(filter_args)
return render_template(
'views/jobs/job.html',
@@ -117,7 +118,7 @@ def view_job_csv(service_id, job_id):
version=job['template_version']
)['data']
filter_args = _parse_filter_args(request.args)
_set_status_filters(filter_args)
filter_args['status'] = _set_status_filters(filter_args)
return (
generate_notifications_csv(
@@ -161,7 +162,7 @@ def view_notifications(service_id, message_type):
abort(404)
filter_args = _parse_filter_args(request.args)
_set_status_filters(filter_args)
filter_args['status'] = _set_status_filters(filter_args)
notifications = notification_api_client.get_notifications_for_service(
service_id=service_id,
@@ -210,7 +211,7 @@ def view_notifications(service_id, message_type):
page=page,
prev_page=prev_page,
next_page=next_page,
request_args=request.args,
status=request.args.get('status'),
message_type=message_type,
download_link=url_for(
'.view_notifications_csv',
@@ -250,7 +251,7 @@ def get_status_filters(service, message_type, statistics):
filters = [
# key, label, option
('requested', 'processed', 'sending,delivered,failed'),
('requested', 'total', 'sending,delivered,failed'),
('sending', 'sending', 'sending'),
('delivered', 'delivered', 'delivered'),
('failed', 'failed', 'failed'),
@@ -287,24 +288,22 @@ def _get_job_counts(job, help_argument):
count
) for label, query_param, count in [
[
'Processed', '',
job.get('notifications_sent', 0)
'total', '',
job.get('notification_count', 0)
],
[
'Sending', 'sending',
(
job.get('notifications_sent', 0) -
job.get('notifications_delivered', 0) -
job.get('notifications_failed', 0)
)
'sending', 'sending',
job.get('notification_count', 0) -
job.get('notifications_delivered', 0) -
job.get('notifications_failed', 0)
],
[
'Delivered', 'delivered',
'delivered', 'delivered',
job.get('notifications_delivered', 0)
],
[
'Failed', 'failed',
job.get('notifications_failed')
'failed', 'failed',
job.get('notifications_failed', 0)
]
]
]
@@ -312,24 +311,27 @@ def _get_job_counts(job, help_argument):
def get_job_partials(job):
filter_args = _parse_filter_args(request.args)
_set_status_filters(filter_args)
filter_args['status'] = _set_status_filters(filter_args)
notifications = notification_api_client.get_notifications_for_service(
job['service'], job['id'], status=filter_args['status']
)
return {
'counts': render_template(
'partials/jobs/count.html',
job=job,
counts=_get_job_counts(job, request.args.get('help', 0)),
status=request.args.get('status', '')
status=filter_args['status']
),
'notifications': render_template(
'partials/jobs/notifications.html',
notifications=notification_api_client.get_notifications_for_service(
job['service'], job['id'], status=filter_args.get('status')
)['notifications'],
notifications=notifications['notifications'],
more_than_one_page=bool(notifications.get('links', {}).get('next')),
percentage_complete=(job['notifications_sent'] / job['notification_count'] * 100),
download_link=url_for(
'.view_job_csv',
service_id=current_service['id'],
job_id=job['id'],
status=request.args.get('status', '')
status=request.args.get('status')
),
help=get_help_argument(),
time_left=get_time_left(job['created_at'])

View File

@@ -103,13 +103,12 @@ def service_request_to_go_live(service_id):
if form.validate_on_submit():
data = {
'person_email': current_app.config.get('DESKPRO_PERSON_EMAIL'),
'person_email': current_user.email_address,
'person_name': current_user.name,
'department_id': current_app.config.get('DESKPRO_DEPT_ID'),
'agent_team_id': current_app.config.get('DESKPRO_ASSIGNED_AGENT_TEAM_ID'),
'subject': 'Request to go live',
'message': "From {} <{}> on behalf of {} ({})\n\nUsage estimate\n---\n\n{}".format(
current_user.name,
current_user.email_address,
'message': "On behalf of {} ({})\n\nUsage estimate\n---\n\n{}".format(
current_service['name'],
url_for('main.service_dashboard', service_id=current_service['id'], _external=True),
form.usage.data