2016-04-26 10:32:26 +01:00
|
|
|
import requests
|
2016-12-12 11:44:11 +00:00
|
|
|
import pytz
|
2016-12-12 14:11:34 +00:00
|
|
|
from flask import render_template, url_for, redirect, flash, current_app, abort, request, session
|
2016-12-12 11:31:26 +00:00
|
|
|
from flask_login import current_user
|
2016-12-12 11:44:11 +00:00
|
|
|
from app import convert_to_boolean, current_service, service_api_client
|
2016-04-26 10:32:26 +01:00
|
|
|
from app.main import main
|
2016-12-12 11:44:11 +00:00
|
|
|
from app.main.forms import SupportType, Support, Triage
|
|
|
|
|
from datetime import datetime
|
2016-04-26 10:32:26 +01:00
|
|
|
|
|
|
|
|
|
2016-12-12 11:18:25 +00:00
|
|
|
@main.route('/support', methods=['GET', 'POST'])
|
|
|
|
|
def support():
|
2016-12-12 11:25:43 +00:00
|
|
|
form = SupportType()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
return redirect(url_for(
|
|
|
|
|
'.feedback',
|
|
|
|
|
ticket_type=form.support_type.data,
|
|
|
|
|
))
|
|
|
|
|
return render_template('views/support/index.html', form=form)
|
2016-12-12 11:18:25 +00:00
|
|
|
|
|
|
|
|
|
2016-12-12 11:44:11 +00:00
|
|
|
@main.route('/support/triage', methods=['GET', 'POST'])
|
|
|
|
|
def triage():
|
|
|
|
|
form = Triage()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
return redirect(url_for(
|
|
|
|
|
'.feedback',
|
|
|
|
|
ticket_type='problem',
|
|
|
|
|
severe=(form.severe.data == 'yes')
|
|
|
|
|
))
|
|
|
|
|
return render_template(
|
|
|
|
|
'views/support/triage.html',
|
|
|
|
|
form=form
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@main.route('/support/submit/<ticket_type>', methods=['GET', 'POST'])
|
2016-12-12 11:25:43 +00:00
|
|
|
def feedback(ticket_type):
|
2016-12-12 11:44:11 +00:00
|
|
|
|
|
|
|
|
if ticket_type not in ['question', 'problem']:
|
2016-12-12 11:25:43 +00:00
|
|
|
abort(404)
|
2016-12-12 11:44:11 +00:00
|
|
|
|
2016-12-12 11:35:23 +00:00
|
|
|
form = Support()
|
2016-12-12 14:11:34 +00:00
|
|
|
if not form.feedback.data:
|
|
|
|
|
form.feedback.data = session.pop('feedback_message', '')
|
|
|
|
|
|
2016-12-12 11:44:11 +00:00
|
|
|
severe = request.args.get('severe')
|
|
|
|
|
|
|
|
|
|
urgent = any((
|
|
|
|
|
in_business_hours(),
|
|
|
|
|
(ticket_type == 'problem' and convert_to_boolean(severe))
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
anonymous = all((
|
|
|
|
|
(not form.email_address.data),
|
|
|
|
|
(not current_user.is_authenticated),
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
if needs_triage(ticket_type, severe):
|
2016-12-12 14:11:34 +00:00
|
|
|
session['feedback_message'] = form.feedback.data
|
2016-12-12 11:44:11 +00:00
|
|
|
return redirect(url_for('.triage'))
|
|
|
|
|
|
|
|
|
|
if needs_escalation(ticket_type, severe):
|
|
|
|
|
return redirect(url_for('.bat_phone'))
|
|
|
|
|
|
2016-04-26 10:32:26 +01:00
|
|
|
if form.validate_on_submit():
|
2016-12-12 11:31:26 +00:00
|
|
|
if current_user.is_authenticated:
|
|
|
|
|
user_email = current_user.email_address
|
|
|
|
|
user_name = current_user.name
|
|
|
|
|
else:
|
|
|
|
|
user_email = form.email_address.data
|
|
|
|
|
user_name = form.name.data or None
|
2016-08-04 18:01:08 +01:00
|
|
|
feedback_msg = 'Environment: {}\n{}\n{}'.format(
|
|
|
|
|
url_for('main.index', _external=True),
|
2016-12-12 11:31:26 +00:00
|
|
|
'' if user_email else '{} (no email address supplied)'.format(form.name.data),
|
2016-08-04 18:01:08 +01:00
|
|
|
form.feedback.data
|
|
|
|
|
)
|
2016-04-26 10:32:26 +01:00
|
|
|
data = {
|
2016-12-12 11:31:26 +00:00
|
|
|
'person_email': user_email or current_app.config.get('DESKPRO_PERSON_EMAIL'),
|
|
|
|
|
'person_name': user_name,
|
2016-05-18 15:03:23 +01:00
|
|
|
'department_id': current_app.config.get('DESKPRO_DEPT_ID'),
|
2016-05-20 15:58:20 +01:00
|
|
|
'agent_team_id': current_app.config.get('DESKPRO_ASSIGNED_AGENT_TEAM_ID'),
|
2016-04-26 10:32:26 +01:00
|
|
|
'subject': 'Notify feedback',
|
2016-12-12 11:25:43 +00:00
|
|
|
'message': feedback_msg,
|
|
|
|
|
'label': ticket_type,
|
2016-12-12 11:44:11 +00:00
|
|
|
'urgency': 10 if urgent else 1,
|
2016-04-26 10:32:26 +01:00
|
|
|
}
|
|
|
|
|
headers = {
|
|
|
|
|
"X-DeskPRO-API-Key": current_app.config.get('DESKPRO_API_KEY'),
|
|
|
|
|
'Content-Type': "application/x-www-form-urlencoded"
|
|
|
|
|
}
|
|
|
|
|
resp = requests.post(
|
|
|
|
|
current_app.config.get('DESKPRO_API_HOST') + '/api/tickets',
|
|
|
|
|
data=data,
|
|
|
|
|
headers=headers)
|
|
|
|
|
if resp.status_code != 201:
|
|
|
|
|
current_app.logger.error(
|
|
|
|
|
"Deskpro create ticket request failed with {} '{}'".format(
|
|
|
|
|
resp.status_code,
|
|
|
|
|
resp.json())
|
|
|
|
|
)
|
|
|
|
|
abort(500, "Feedback submission failed")
|
2016-12-12 12:29:29 +00:00
|
|
|
return redirect(url_for('.thanks', urgent=urgent, anonymous=anonymous))
|
2016-04-26 10:32:26 +01:00
|
|
|
|
2016-12-12 11:25:43 +00:00
|
|
|
return render_template(
|
|
|
|
|
'views/support/{}.html'.format(ticket_type),
|
|
|
|
|
form=form,
|
2016-12-12 11:44:11 +00:00
|
|
|
ticket_type=ticket_type,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@main.route('/support/escalate', methods=['GET', 'POST'])
|
|
|
|
|
def bat_phone():
|
|
|
|
|
|
|
|
|
|
if current_user.is_authenticated:
|
|
|
|
|
return redirect(url_for('main.feedback', ticket_type='problem'))
|
|
|
|
|
|
|
|
|
|
return render_template('views/support/bat-phone.html')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@main.route('/support/thanks', methods=['GET', 'POST'])
|
|
|
|
|
def thanks():
|
|
|
|
|
return render_template(
|
|
|
|
|
'views/support/thanks.html',
|
2016-12-12 12:29:29 +00:00
|
|
|
urgent=convert_to_boolean(request.args.get('urgent')),
|
|
|
|
|
anonymous=convert_to_boolean(request.args.get('anonymous')),
|
|
|
|
|
logged_in=(current_user and current_user.is_authenticated),
|
2016-12-12 11:44:11 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def in_business_hours():
|
|
|
|
|
|
|
|
|
|
now = datetime.now().replace(tzinfo=pytz.timezone('Europe/London'))
|
|
|
|
|
|
|
|
|
|
if is_weekend(now) or is_bank_holiday(now):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
opening_time = now.replace(hour=9, minute=30, second=0, tzinfo=pytz.timezone('Europe/London'))
|
|
|
|
|
closing_time = now.replace(hour=17, minute=30, second=0, tzinfo=pytz.timezone('Europe/London'))
|
|
|
|
|
|
|
|
|
|
return opening_time <= now < closing_time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_weekend(time):
|
|
|
|
|
return time.strftime('%A') in {
|
|
|
|
|
'Saturday',
|
|
|
|
|
'Sunday',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_bank_holiday(time):
|
|
|
|
|
return time.strftime('%d/%m/%Y') in {
|
|
|
|
|
# taken from
|
|
|
|
|
# https://github.com/alphagov/calendars/blob/7f6512b0a95d77aa22accef105860074c19f1ec0/lib/data/bank-holidays.json
|
|
|
|
|
"01/01/2016",
|
|
|
|
|
"25/03/2016",
|
|
|
|
|
"28/03/2016",
|
|
|
|
|
"02/05/2016",
|
|
|
|
|
"30/05/2016",
|
|
|
|
|
"29/08/2016",
|
|
|
|
|
"26/12/2016",
|
|
|
|
|
"27/12/2016",
|
|
|
|
|
"02/01/2017",
|
|
|
|
|
"14/04/2017",
|
|
|
|
|
"17/04/2017",
|
|
|
|
|
"01/05/2017",
|
|
|
|
|
"29/05/2017",
|
|
|
|
|
"28/08/2017",
|
|
|
|
|
"25/12/2017",
|
|
|
|
|
"26/12/2017",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def has_live_services(user_id):
|
|
|
|
|
return any(
|
|
|
|
|
service['restricted'] is False
|
|
|
|
|
for service in service_api_client.get_services({'user_id': user_id})['data']
|
2016-12-12 11:25:43 +00:00
|
|
|
)
|
2016-12-12 11:44:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def needs_triage(ticket_type, severe):
|
|
|
|
|
return all((
|
|
|
|
|
ticket_type == 'problem',
|
|
|
|
|
severe is None,
|
|
|
|
|
(
|
|
|
|
|
not current_user.is_authenticated or has_live_services(current_user.id)
|
|
|
|
|
),
|
|
|
|
|
not in_business_hours(),
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def needs_escalation(ticket_type, severe):
|
|
|
|
|
return all((
|
|
|
|
|
ticket_type == 'problem',
|
|
|
|
|
convert_to_boolean(severe),
|
|
|
|
|
not current_user.is_authenticated,
|
|
|
|
|
not in_business_hours(),
|
|
|
|
|
))
|