2016-04-04 14:28:52 +01:00
|
|
|
|
import itertools
|
2018-04-03 14:43:38 +01:00
|
|
|
|
import json
|
2016-05-31 14:18:35 +01:00
|
|
|
|
from string import ascii_uppercase
|
2016-05-13 21:25:59 +01:00
|
|
|
|
from zipfile import BadZipFile
|
2016-01-11 15:00:51 +00:00
|
|
|
|
|
|
|
|
|
|
from flask import (
|
2016-02-01 11:28:36 +00:00
|
|
|
|
abort,
|
2016-12-20 14:38:34 +00:00
|
|
|
|
current_app,
|
2018-02-20 11:22:17 +00:00
|
|
|
|
flash,
|
|
|
|
|
|
redirect,
|
|
|
|
|
|
render_template,
|
|
|
|
|
|
request,
|
|
|
|
|
|
session,
|
|
|
|
|
|
url_for,
|
2016-01-11 15:00:51 +00:00
|
|
|
|
)
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from flask_login import current_user, login_required
|
2017-06-29 15:31:44 +01:00
|
|
|
|
from notifications_python_client.errors import HTTPError
|
2018-08-16 16:51:32 +01:00
|
|
|
|
from notifications_utils import SMS_CHAR_COUNT_LIMIT
|
2018-06-08 12:49:29 +01:00
|
|
|
|
from notifications_utils.columns import Columns
|
2017-05-04 09:30:55 +01:00
|
|
|
|
from notifications_utils.recipients import (
|
|
|
|
|
|
RecipientCSV,
|
|
|
|
|
|
first_column_headings,
|
|
|
|
|
|
optional_address_columns,
|
|
|
|
|
|
)
|
2018-07-12 15:14:58 +01:00
|
|
|
|
from notifications_utils.sanitise_text import SanitiseASCII
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from orderedset import OrderedSet
|
2018-04-30 12:55:56 +01:00
|
|
|
|
from werkzeug.routing import RequestRedirect
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from xlrd.biffh import XLRDError
|
Catch exceptions caused by ambiguous Excel files
Excel stores dates as floating point numbers, counting the days (or
fraction thereof) since 1900 (except when it counts from 1904).
However it also, incorrectly, recognises 1900 as a leap year. This means
that it’s ambiguous whether day 59 is February 28th, or February 27th,
depending if you’re counting up or down. In fact any number less than 60
is, therefore, ambiguous.
This shouldn’t really matter since no-one is going to be using dates in
the year 1900 in Notify messages. _Except_ when Excel misidentifies a
cell as containing a date. For example, if you have the number `9`
inside a cell, it means _house number 9_ if the next cell contains
_example_ street. but Excel is all like ‘oh they must want January 9th
1900!’ No. Bad Excel.
There’s not much we can do about this, but we can at least give people
an error message with the workaround, which is what this commit does.
Most of this commit message is paraphrased from:
http://xlrd.readthedocs.io/en/latest/dates.html
2018-02-28 14:45:57 +00:00
|
|
|
|
from xlrd.xldate import XLDateError
|
2015-12-10 21:15:20 +00:00
|
|
|
|
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from app import (
|
|
|
|
|
|
current_service,
|
|
|
|
|
|
job_api_client,
|
|
|
|
|
|
notification_api_client,
|
|
|
|
|
|
service_api_client,
|
|
|
|
|
|
user_api_client,
|
|
|
|
|
|
)
|
2015-12-10 21:15:20 +00:00
|
|
|
|
from app.main import main
|
2017-05-04 09:30:55 +01:00
|
|
|
|
from app.main.forms import (
|
|
|
|
|
|
ChooseTimeForm,
|
2018-02-20 11:22:17 +00:00
|
|
|
|
CsvUploadForm,
|
2017-10-16 16:35:35 +01:00
|
|
|
|
SetSenderForm,
|
2018-02-20 11:22:17 +00:00
|
|
|
|
get_placeholder_form_instance,
|
2016-01-14 16:00:13 +00:00
|
|
|
|
)
|
2019-01-30 09:42:15 +00:00
|
|
|
|
from app.s3_client.s3_csv_client import (
|
|
|
|
|
|
s3download,
|
|
|
|
|
|
s3upload,
|
|
|
|
|
|
set_metadata_on_csv_upload,
|
|
|
|
|
|
)
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from app.template_previews import TemplatePreview, get_page_count_for_letter
|
2016-12-28 11:06:11 +00:00
|
|
|
|
from app.utils import (
|
|
|
|
|
|
Spreadsheet,
|
2018-02-20 11:22:17 +00:00
|
|
|
|
email_or_sms_not_enabled,
|
|
|
|
|
|
get_errors_for_csv,
|
2016-12-28 11:06:11 +00:00
|
|
|
|
get_help_argument,
|
2017-07-04 17:25:35 +01:00
|
|
|
|
get_template,
|
2018-08-09 16:29:51 +01:00
|
|
|
|
should_skip_template_page,
|
2018-04-30 10:46:39 +01:00
|
|
|
|
unicode_truncate,
|
2018-02-20 11:22:17 +00:00
|
|
|
|
user_has_permissions,
|
2016-12-28 11:06:11 +00:00
|
|
|
|
)
|
2016-02-22 17:17:18 +00:00
|
|
|
|
|
2016-03-01 15:53:58 +00:00
|
|
|
|
|
|
|
|
|
|
def get_page_headings(template_type):
|
2016-04-01 10:42:23 +01:00
|
|
|
|
return {
|
|
|
|
|
|
'email': 'Email templates',
|
2016-11-08 13:12:07 +00:00
|
|
|
|
'sms': 'Text message templates',
|
|
|
|
|
|
'letter': 'Letter templates'
|
2016-04-01 10:42:23 +01:00
|
|
|
|
}[template_type]
|
2016-03-01 15:53:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
2016-05-05 08:39:36 +01:00
|
|
|
|
def get_example_csv_fields(column_headers, use_example_as_example, submitted_fields):
|
|
|
|
|
|
if use_example_as_example:
|
|
|
|
|
|
return ["example" for header in column_headers]
|
|
|
|
|
|
elif submitted_fields:
|
|
|
|
|
|
return [submitted_fields.get(header) for header in column_headers]
|
|
|
|
|
|
else:
|
|
|
|
|
|
return list(column_headers)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_example_csv_rows(template, use_example_as_example=True, submitted_fields=False):
|
2016-11-10 13:39:05 +00:00
|
|
|
|
return {
|
|
|
|
|
|
'email': ['test@example.com'] if use_example_as_example else [current_user.email_address],
|
2017-04-26 16:19:34 +01:00
|
|
|
|
'sms': ['07700 900321'] if use_example_as_example else [current_user.mobile_number],
|
2016-11-11 09:51:20 +00:00
|
|
|
|
'letter': [
|
|
|
|
|
|
(submitted_fields or {}).get(
|
|
|
|
|
|
key, get_example_letter_address(key) if use_example_as_example else key
|
|
|
|
|
|
)
|
|
|
|
|
|
for key in first_column_headings['letter']
|
2016-11-10 13:39:05 +00:00
|
|
|
|
]
|
2018-06-08 12:49:29 +01:00
|
|
|
|
}[template.template_type] + get_example_csv_fields(
|
|
|
|
|
|
(
|
|
|
|
|
|
placeholder for placeholder in template.placeholders
|
|
|
|
|
|
if placeholder not in Columns.from_keys(
|
|
|
|
|
|
first_column_headings[template.template_type]
|
|
|
|
|
|
)
|
|
|
|
|
|
),
|
|
|
|
|
|
use_example_as_example,
|
|
|
|
|
|
submitted_fields
|
|
|
|
|
|
)
|
2016-04-01 14:31:28 +01:00
|
|
|
|
|
|
|
|
|
|
|
2016-11-11 09:51:20 +00:00
|
|
|
|
def get_example_letter_address(key):
|
|
|
|
|
|
return {
|
|
|
|
|
|
'address line 1': 'A. Name',
|
|
|
|
|
|
'address line 2': '123 Example Street',
|
|
|
|
|
|
'postcode': 'XM4 5HQ'
|
|
|
|
|
|
}.get(key, '')
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-04-12 14:19:51 +01:00
|
|
|
|
@main.route("/services/<service_id>/send/<template_id>/csv", methods=['GET', 'POST'])
|
2016-01-11 15:00:51 +00:00
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2016-02-22 17:17:18 +00:00
|
|
|
|
def send_messages(service_id, template_id):
|
2018-04-03 14:43:38 +01:00
|
|
|
|
# if there's lots of data in the session, lets log it for debugging purposes
|
|
|
|
|
|
# TODO: Remove this once we're confident we have session size under control
|
|
|
|
|
|
if len(session.get('file_uploads', {}).keys()) > 2:
|
|
|
|
|
|
current_app.logger.info('session contains large file_uploads - json_len {}, keys: {}'.format(
|
|
|
|
|
|
len(json.dumps(session['file_uploads'])),
|
|
|
|
|
|
session['file_uploads'].keys())
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2017-06-22 16:00:14 +01:00
|
|
|
|
db_template = service_api_client.get_service_template(service_id, template_id)['data']
|
2017-05-11 12:01:51 +01:00
|
|
|
|
|
2018-11-06 14:22:22 +00:00
|
|
|
|
email_reply_to = None
|
|
|
|
|
|
sms_sender = None
|
|
|
|
|
|
|
|
|
|
|
|
if db_template['template_type'] == 'email':
|
|
|
|
|
|
email_reply_to = get_email_reply_to_address_from_session()
|
|
|
|
|
|
elif db_template['template_type'] == 'sms':
|
|
|
|
|
|
sms_sender = get_sms_sender_from_session()
|
|
|
|
|
|
|
2018-07-20 08:42:01 +01:00
|
|
|
|
if email_or_sms_not_enabled(db_template['template_type'], current_service.permissions):
|
2017-06-30 10:55:59 +01:00
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'.action_blocked',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
notification_type=db_template['template_type'],
|
|
|
|
|
|
return_to='view_template',
|
|
|
|
|
|
template_id=template_id
|
|
|
|
|
|
))
|
|
|
|
|
|
|
2016-12-08 11:50:59 +00:00
|
|
|
|
template = get_template(
|
2017-06-22 16:00:14 +01:00
|
|
|
|
db_template,
|
2016-12-08 11:50:59 +00:00
|
|
|
|
current_service,
|
2016-12-20 14:38:34 +00:00
|
|
|
|
show_recipient=True,
|
2017-05-11 12:01:51 +01:00
|
|
|
|
expand_emails=True,
|
2017-04-28 16:04:52 +01:00
|
|
|
|
letter_preview_url=url_for(
|
|
|
|
|
|
'.view_letter_template_preview',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
filetype='png',
|
2017-06-22 16:00:14 +01:00
|
|
|
|
page_count=get_page_count_for_letter(db_template),
|
2017-04-28 16:04:52 +01:00
|
|
|
|
),
|
2018-11-06 14:22:22 +00:00
|
|
|
|
email_reply_to=email_reply_to,
|
|
|
|
|
|
sms_sender=sms_sender,
|
2016-03-29 15:59:53 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
2016-01-11 15:00:51 +00:00
|
|
|
|
form = CsvUploadForm()
|
2016-01-13 17:32:40 +00:00
|
|
|
|
if form.validate_on_submit():
|
2016-01-11 15:00:51 +00:00
|
|
|
|
try:
|
2016-05-15 07:47:50 +01:00
|
|
|
|
upload_id = s3upload(
|
2016-03-07 18:47:05 +00:00
|
|
|
|
service_id,
|
2016-05-15 10:47:52 +01:00
|
|
|
|
Spreadsheet.from_file(form.file.data, filename=form.file.data.filename).as_dict,
|
2016-03-07 18:47:05 +00:00
|
|
|
|
current_app.config['AWS_REGION']
|
|
|
|
|
|
)
|
2018-03-29 17:01:35 +01:00
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'.check_messages',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
upload_id=upload_id,
|
|
|
|
|
|
template_id=template.id,
|
|
|
|
|
|
original_file_name=form.file.data.filename,
|
|
|
|
|
|
))
|
2016-05-13 21:25:59 +01:00
|
|
|
|
except (UnicodeDecodeError, BadZipFile, XLRDError):
|
|
|
|
|
|
flash('Couldn’t read {}. Try using a different file format.'.format(
|
|
|
|
|
|
form.file.data.filename
|
|
|
|
|
|
))
|
Catch exceptions caused by ambiguous Excel files
Excel stores dates as floating point numbers, counting the days (or
fraction thereof) since 1900 (except when it counts from 1904).
However it also, incorrectly, recognises 1900 as a leap year. This means
that it’s ambiguous whether day 59 is February 28th, or February 27th,
depending if you’re counting up or down. In fact any number less than 60
is, therefore, ambiguous.
This shouldn’t really matter since no-one is going to be using dates in
the year 1900 in Notify messages. _Except_ when Excel misidentifies a
cell as containing a date. For example, if you have the number `9`
inside a cell, it means _house number 9_ if the next cell contains
_example_ street. but Excel is all like ‘oh they must want January 9th
1900!’ No. Bad Excel.
There’s not much we can do about this, but we can at least give people
an error message with the workaround, which is what this commit does.
Most of this commit message is paraphrased from:
http://xlrd.readthedocs.io/en/latest/dates.html
2018-02-28 14:45:57 +00:00
|
|
|
|
except (XLDateError):
|
|
|
|
|
|
flash((
|
|
|
|
|
|
'{} contains numbers or dates that Notify can’t understand. '
|
|
|
|
|
|
'Try formatting all columns as ‘text’ or export your file as CSV.'
|
|
|
|
|
|
).format(
|
|
|
|
|
|
form.file.data.filename
|
|
|
|
|
|
))
|
2016-01-11 15:00:51 +00:00
|
|
|
|
|
2018-06-08 12:49:29 +01:00
|
|
|
|
column_headings = get_spreadsheet_column_headings_from_template(template)
|
2016-11-10 13:39:05 +00:00
|
|
|
|
|
2016-02-08 16:36:53 +00:00
|
|
|
|
return render_template(
|
2016-02-22 17:17:18 +00:00
|
|
|
|
'views/send.html',
|
2016-02-08 16:36:53 +00:00
|
|
|
|
template=template,
|
2016-11-10 13:39:05 +00:00
|
|
|
|
column_headings=list(ascii_uppercase[:len(column_headings)]),
|
|
|
|
|
|
example=[column_headings, get_example_csv_rows(template)],
|
2016-04-04 16:53:52 +01:00
|
|
|
|
form=form
|
2016-02-08 16:36:53 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-22 14:45:13 +00:00
|
|
|
|
@main.route("/services/<service_id>/send/<template_id>.csv", methods=['GET'])
|
2016-02-08 16:36:53 +00:00
|
|
|
|
@login_required
|
2018-03-01 10:37:55 +00:00
|
|
|
|
@user_has_permissions('send_messages', 'manage_templates')
|
2016-05-05 08:39:36 +01:00
|
|
|
|
def get_example_csv(service_id, template_id):
|
2016-12-08 11:50:59 +00:00
|
|
|
|
template = get_template(
|
|
|
|
|
|
service_api_client.get_service_template(service_id, template_id)['data'], current_service
|
|
|
|
|
|
)
|
2016-05-15 10:47:52 +01:00
|
|
|
|
return Spreadsheet.from_rows([
|
2018-06-08 12:49:29 +01:00
|
|
|
|
get_spreadsheet_column_headings_from_template(template),
|
2016-05-15 10:47:52 +01:00
|
|
|
|
get_example_csv_rows(template)
|
|
|
|
|
|
]).as_csv_data, 200, {
|
|
|
|
|
|
'Content-Type': 'text/csv; charset=utf-8',
|
|
|
|
|
|
'Content-Disposition': 'inline; filename="{}.csv"'.format(template.name)
|
|
|
|
|
|
}
|
2015-12-10 21:15:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
2017-10-16 16:35:35 +01:00
|
|
|
|
@main.route("/services/<service_id>/send/<template_id>/set-sender", methods=['GET', 'POST'])
|
|
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2017-10-16 16:35:35 +01:00
|
|
|
|
def set_sender(service_id, template_id):
|
|
|
|
|
|
session['sender_id'] = None
|
|
|
|
|
|
redirect_to_one_off = redirect(
|
|
|
|
|
|
url_for('.send_one_off', service_id=service_id, template_id=template_id)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
template = service_api_client.get_service_template(service_id, template_id)['data']
|
|
|
|
|
|
|
2017-11-02 12:07:46 +00:00
|
|
|
|
if template['template_type'] == 'letter':
|
2017-10-16 16:35:35 +01:00
|
|
|
|
return redirect_to_one_off
|
|
|
|
|
|
|
|
|
|
|
|
sender_details = get_sender_details(service_id, template['template_type'])
|
|
|
|
|
|
if len(sender_details) <= 1:
|
|
|
|
|
|
return redirect_to_one_off
|
|
|
|
|
|
|
|
|
|
|
|
sender_context = get_sender_context(sender_details, template['template_type'])
|
|
|
|
|
|
|
|
|
|
|
|
form = SetSenderForm(
|
|
|
|
|
|
sender=sender_context['default_id'],
|
|
|
|
|
|
sender_choices=sender_context['value_and_label'],
|
|
|
|
|
|
sender_label=sender_context['description']
|
|
|
|
|
|
)
|
2018-03-01 11:04:25 +00:00
|
|
|
|
option_hints = {sender_context['default_id']: '(Default)'}
|
2017-11-02 15:48:19 +00:00
|
|
|
|
if sender_context.get('receives_text_message', None):
|
|
|
|
|
|
option_hints.update({sender_context['receives_text_message']: '(Receives replies)'})
|
|
|
|
|
|
if sender_context.get('default_and_receives', None):
|
|
|
|
|
|
option_hints = {sender_context['default_and_receives']: '(Default and receives replies)'}
|
2017-10-16 16:35:35 +01:00
|
|
|
|
|
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
|
session['sender_id'] = form.sender.data
|
|
|
|
|
|
return redirect(url_for('.send_one_off',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id))
|
|
|
|
|
|
|
|
|
|
|
|
return render_template(
|
|
|
|
|
|
'views/templates/set-sender.html',
|
|
|
|
|
|
form=form,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
sender_context={'title': sender_context['title'], 'description': sender_context['description']},
|
|
|
|
|
|
option_hints=option_hints
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_sender_context(sender_details, template_type):
|
|
|
|
|
|
context = {
|
|
|
|
|
|
'email': {
|
2017-11-20 16:47:03 +00:00
|
|
|
|
'title': 'Where should replies come back to?',
|
|
|
|
|
|
'description': 'Where should replies come back to?',
|
2017-10-16 16:35:35 +01:00
|
|
|
|
'field_name': 'email_address'
|
|
|
|
|
|
},
|
|
|
|
|
|
'letter': {
|
2017-11-13 11:34:32 +00:00
|
|
|
|
'title': 'Send to one recipient',
|
2017-11-13 11:31:12 +00:00
|
|
|
|
'description': 'What should appear in the top right of the letter?',
|
2017-10-16 16:35:35 +01:00
|
|
|
|
'field_name': 'contact_block'
|
2017-11-02 12:07:46 +00:00
|
|
|
|
},
|
|
|
|
|
|
'sms': {
|
2017-11-20 16:26:09 +00:00
|
|
|
|
'title': 'Who should the message come from?',
|
2017-11-13 11:31:12 +00:00
|
|
|
|
'description': 'Who should the message come from?',
|
2017-11-02 12:07:46 +00:00
|
|
|
|
'field_name': 'sms_sender'
|
2017-10-16 16:35:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
}[template_type]
|
|
|
|
|
|
|
|
|
|
|
|
sender_format = context['field_name']
|
|
|
|
|
|
|
|
|
|
|
|
context['default_id'] = next(sender['id'] for sender in sender_details if sender['is_default'])
|
2017-11-02 14:58:14 +00:00
|
|
|
|
if template_type == 'sms':
|
2017-11-02 15:48:19 +00:00
|
|
|
|
inbound = [sender['id'] for sender in sender_details if sender['inbound_number_id']]
|
|
|
|
|
|
if inbound:
|
|
|
|
|
|
context['receives_text_message'] = next(iter(inbound))
|
|
|
|
|
|
if context['default_id'] == context.get('receives_text_message', None):
|
|
|
|
|
|
context['default_and_receives'] = context['default_id']
|
|
|
|
|
|
|
2017-10-16 16:35:35 +01:00
|
|
|
|
context['value_and_label'] = [(sender['id'], sender[sender_format]) for sender in sender_details]
|
|
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_sender_details(service_id, template_type):
|
|
|
|
|
|
api_call = {
|
|
|
|
|
|
'email': service_api_client.get_reply_to_email_addresses,
|
2017-11-02 12:07:46 +00:00
|
|
|
|
'letter': service_api_client.get_letter_contacts,
|
|
|
|
|
|
'sms': service_api_client.get_sms_senders
|
2017-10-16 16:35:35 +01:00
|
|
|
|
}[template_type]
|
|
|
|
|
|
return api_call(service_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-05-25 08:55:05 +01:00
|
|
|
|
@main.route("/services/<service_id>/send/<template_id>/test", endpoint='send_test')
|
|
|
|
|
|
@main.route("/services/<service_id>/send/<template_id>/one-off", endpoint='send_one_off')
|
2016-02-12 10:55:21 +00:00
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2016-05-05 08:39:36 +01:00
|
|
|
|
def send_test(service_id, template_id):
|
2017-06-23 17:30:34 +01:00
|
|
|
|
session['recipient'] = None
|
|
|
|
|
|
session['placeholders'] = {}
|
2017-05-16 17:52:19 +01:00
|
|
|
|
session['send_test_letter_page_count'] = None
|
2017-06-30 10:55:59 +01:00
|
|
|
|
|
|
|
|
|
|
db_template = service_api_client.get_service_template(service_id, template_id)['data']
|
2017-11-02 12:07:46 +00:00
|
|
|
|
if db_template['template_type'] == 'letter':
|
2017-10-16 16:35:35 +01:00
|
|
|
|
session['sender_id'] = None
|
2017-06-30 10:55:59 +01:00
|
|
|
|
|
2018-07-20 08:42:01 +01:00
|
|
|
|
if email_or_sms_not_enabled(db_template['template_type'], current_service.permissions):
|
2017-06-30 10:55:59 +01:00
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'.action_blocked',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
notification_type=db_template['template_type'],
|
|
|
|
|
|
return_to='view_template',
|
|
|
|
|
|
template_id=template_id))
|
|
|
|
|
|
|
2017-05-04 09:30:55 +01:00
|
|
|
|
return redirect(url_for(
|
2017-05-25 08:55:05 +01:00
|
|
|
|
{
|
|
|
|
|
|
'main.send_test': '.send_test_step',
|
|
|
|
|
|
'main.send_one_off': '.send_one_off_step',
|
|
|
|
|
|
}[request.endpoint],
|
2017-05-04 09:30:55 +01:00
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
step_index=0,
|
|
|
|
|
|
help=get_help_argument(),
|
|
|
|
|
|
))
|
|
|
|
|
|
|
2016-04-03 11:30:23 +01:00
|
|
|
|
|
2017-06-23 17:30:34 +01:00
|
|
|
|
def get_notification_check_endpoint(service_id, template):
|
2018-10-30 14:24:50 +00:00
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'main.check_notification',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template.id,
|
|
|
|
|
|
# at check phase we should move to help stage 2 ("the template pulls in the data you provide")
|
|
|
|
|
|
help='2' if 'help' in request.args else None
|
|
|
|
|
|
))
|
2017-06-23 17:30:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
2017-05-25 08:55:05 +01:00
|
|
|
|
@main.route(
|
|
|
|
|
|
"/services/<service_id>/send/<template_id>/test/step-<int:step_index>",
|
|
|
|
|
|
methods=['GET', 'POST'],
|
|
|
|
|
|
endpoint='send_test_step',
|
|
|
|
|
|
)
|
|
|
|
|
|
@main.route(
|
|
|
|
|
|
"/services/<service_id>/send/<template_id>/one-off/step-<int:step_index>",
|
|
|
|
|
|
methods=['GET', 'POST'],
|
|
|
|
|
|
endpoint='send_one_off_step',
|
|
|
|
|
|
)
|
2017-05-04 09:30:55 +01:00
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2017-05-04 09:30:55 +01:00
|
|
|
|
def send_test_step(service_id, template_id, step_index):
|
2017-06-23 17:30:34 +01:00
|
|
|
|
if {'recipient', 'placeholders'} - set(session.keys()):
|
2017-05-22 11:49:15 +01:00
|
|
|
|
return redirect(url_for(
|
2017-05-25 08:55:05 +01:00
|
|
|
|
{
|
|
|
|
|
|
'main.send_test_step': '.send_test',
|
|
|
|
|
|
'main.send_one_off_step': '.send_one_off',
|
|
|
|
|
|
}[request.endpoint],
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
2017-05-22 11:49:15 +01:00
|
|
|
|
))
|
|
|
|
|
|
|
2017-06-22 16:00:14 +01:00
|
|
|
|
db_template = service_api_client.get_service_template(service_id, template_id)['data']
|
2017-05-11 12:01:51 +01:00
|
|
|
|
|
2017-05-16 17:52:19 +01:00
|
|
|
|
if not session.get('send_test_letter_page_count'):
|
2017-06-22 16:00:14 +01:00
|
|
|
|
session['send_test_letter_page_count'] = get_page_count_for_letter(db_template)
|
2017-11-02 12:07:46 +00:00
|
|
|
|
email_reply_to = None
|
|
|
|
|
|
sms_sender = None
|
|
|
|
|
|
if db_template['template_type'] == 'email':
|
2018-10-26 17:31:49 +01:00
|
|
|
|
email_reply_to = get_email_reply_to_address_from_session()
|
2017-11-02 12:07:46 +00:00
|
|
|
|
elif db_template['template_type'] == 'sms':
|
2018-10-26 17:31:49 +01:00
|
|
|
|
sms_sender = get_sms_sender_from_session()
|
2016-12-08 11:50:59 +00:00
|
|
|
|
template = get_template(
|
2017-06-22 16:00:14 +01:00
|
|
|
|
db_template,
|
2016-12-08 11:50:59 +00:00
|
|
|
|
current_service,
|
2016-12-20 14:38:34 +00:00
|
|
|
|
show_recipient=True,
|
2017-05-11 12:01:51 +01:00
|
|
|
|
expand_emails=True,
|
2017-04-28 16:04:52 +01:00
|
|
|
|
letter_preview_url=url_for(
|
2017-05-04 09:30:55 +01:00
|
|
|
|
'.send_test_preview',
|
2017-04-28 16:04:52 +01:00
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
filetype='png',
|
|
|
|
|
|
),
|
2017-10-17 16:06:15 +01:00
|
|
|
|
page_count=session['send_test_letter_page_count'],
|
2017-11-02 12:07:46 +00:00
|
|
|
|
email_reply_to=email_reply_to,
|
|
|
|
|
|
sms_sender=sms_sender
|
2016-05-05 08:39:36 +01:00
|
|
|
|
)
|
2016-03-29 15:59:53 +01:00
|
|
|
|
|
2017-05-25 09:18:26 +01:00
|
|
|
|
placeholders = fields_to_fill_in(
|
|
|
|
|
|
template,
|
|
|
|
|
|
prefill_current_user=(request.endpoint == 'main.send_test_step'),
|
|
|
|
|
|
)
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
2017-05-22 11:49:15 +01:00
|
|
|
|
try:
|
2018-11-30 10:58:32 +00:00
|
|
|
|
if request.endpoint == 'main.send_test_step':
|
|
|
|
|
|
current_placeholder = placeholders[step_index - 1]
|
|
|
|
|
|
else:
|
|
|
|
|
|
current_placeholder = placeholders[step_index]
|
|
|
|
|
|
|
2017-05-22 11:49:15 +01:00
|
|
|
|
except IndexError:
|
2017-05-25 09:18:26 +01:00
|
|
|
|
if all_placeholders_in_session(placeholders):
|
2017-06-23 17:30:34 +01:00
|
|
|
|
return get_notification_check_endpoint(service_id, template)
|
2017-05-22 11:49:15 +01:00
|
|
|
|
return redirect(url_for(
|
2017-05-25 08:55:05 +01:00
|
|
|
|
{
|
|
|
|
|
|
'main.send_test_step': '.send_test',
|
|
|
|
|
|
'main.send_one_off_step': '.send_one_off',
|
|
|
|
|
|
}[request.endpoint],
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
2017-05-22 11:49:15 +01:00
|
|
|
|
))
|
2017-06-22 16:00:14 +01:00
|
|
|
|
|
2017-05-04 09:30:55 +01:00
|
|
|
|
optional_placeholder = (current_placeholder in optional_address_columns)
|
|
|
|
|
|
form = get_placeholder_form_instance(
|
|
|
|
|
|
current_placeholder,
|
2017-06-23 17:30:34 +01:00
|
|
|
|
dict_to_populate_from=get_normalised_placeholders_from_session(),
|
2018-03-16 14:17:43 +00:00
|
|
|
|
template_type=template.template_type,
|
2017-05-04 09:30:55 +01:00
|
|
|
|
optional_placeholder=optional_placeholder,
|
2018-07-20 08:43:02 +01:00
|
|
|
|
allow_international_phone_numbers=current_service.has_permission('international_sms'),
|
2017-05-04 09:30:55 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if form.validate_on_submit():
|
2017-06-26 10:58:43 +01:00
|
|
|
|
# if it's the first input (phone/email), we store against `recipient` as well, for easier extraction.
|
|
|
|
|
|
# Only if it's not a letter.
|
|
|
|
|
|
# And only if we're not on the test route, since that will already have the user's own number set
|
|
|
|
|
|
if (
|
|
|
|
|
|
step_index == 0 and
|
|
|
|
|
|
template.template_type != 'letter' and
|
|
|
|
|
|
request.endpoint != 'main.send_test_step'
|
|
|
|
|
|
):
|
2017-06-23 17:30:34 +01:00
|
|
|
|
session['recipient'] = form.placeholder_value.data
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
2017-06-23 17:30:34 +01:00
|
|
|
|
session['placeholders'][current_placeholder] = form.placeholder_value.data
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
2017-05-25 09:18:26 +01:00
|
|
|
|
if all_placeholders_in_session(placeholders):
|
2017-06-23 17:30:34 +01:00
|
|
|
|
return get_notification_check_endpoint(service_id, template)
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
2016-05-15 10:47:52 +01:00
|
|
|
|
return redirect(url_for(
|
2017-05-25 08:55:05 +01:00
|
|
|
|
request.endpoint,
|
2016-05-15 10:47:52 +01:00
|
|
|
|
service_id=service_id,
|
2017-05-04 09:30:55 +01:00
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
step_index=step_index + 1,
|
|
|
|
|
|
help=get_help_argument(),
|
2016-05-15 10:47:52 +01:00
|
|
|
|
))
|
2016-02-12 10:55:21 +00:00
|
|
|
|
|
2018-08-09 16:29:51 +01:00
|
|
|
|
back_link = get_back_link(service_id, template, step_index)
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
2017-06-29 15:31:44 +01:00
|
|
|
|
template.values = get_recipient_and_placeholders_from_session(template.template_type)
|
2017-05-16 17:17:11 +01:00
|
|
|
|
template.values[current_placeholder] = None
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
2017-05-25 13:31:51 +01:00
|
|
|
|
if (
|
|
|
|
|
|
request.endpoint == 'main.send_one_off_step' and
|
|
|
|
|
|
step_index == 0 and
|
2017-11-09 16:09:00 +00:00
|
|
|
|
template.template_type != 'letter' and
|
2018-06-14 15:04:01 +01:00
|
|
|
|
not (template.template_type == 'sms' and current_user.mobile_number is None) and
|
2018-08-07 11:10:00 +01:00
|
|
|
|
current_user.has_permissions('manage_templates', 'manage_service')
|
2017-05-25 13:31:51 +01:00
|
|
|
|
):
|
|
|
|
|
|
skip_link = (
|
|
|
|
|
|
'Use my {}'.format(first_column_headings[template.template_type][0]),
|
2018-11-30 10:58:32 +00:00
|
|
|
|
url_for('.send_test_step', service_id=service_id, template_id=template.id, step_index=1),
|
2017-05-25 13:31:51 +01:00
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
skip_link = None
|
2016-05-05 08:39:36 +01:00
|
|
|
|
return render_template(
|
|
|
|
|
|
'views/send-test.html',
|
2017-11-20 16:45:59 +00:00
|
|
|
|
page_title=get_send_test_page_title(
|
|
|
|
|
|
template.template_type,
|
|
|
|
|
|
get_help_argument(),
|
2018-08-06 11:20:50 +01:00
|
|
|
|
entering_recipient=not session['recipient'],
|
|
|
|
|
|
name=template.name,
|
2017-11-20 16:45:59 +00:00
|
|
|
|
),
|
2016-05-05 08:39:36 +01:00
|
|
|
|
template=template,
|
2017-05-04 09:30:55 +01:00
|
|
|
|
form=form,
|
2017-05-25 13:31:51 +01:00
|
|
|
|
skip_link=skip_link,
|
2017-05-04 09:30:55 +01:00
|
|
|
|
optional_placeholder=optional_placeholder,
|
|
|
|
|
|
back_link=back_link,
|
2017-06-01 13:29:30 +01:00
|
|
|
|
help=get_help_argument(),
|
2018-07-18 09:48:19 +01:00
|
|
|
|
link_to_upload=(
|
|
|
|
|
|
request.endpoint == 'main.send_one_off_step' and
|
|
|
|
|
|
step_index == 0
|
|
|
|
|
|
),
|
2016-05-05 08:39:36 +01:00
|
|
|
|
)
|
2016-02-12 10:55:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
2017-05-04 09:30:55 +01:00
|
|
|
|
@main.route("/services/<service_id>/send/<template_id>/test.<filetype>", methods=['GET'])
|
|
|
|
|
|
@login_required
|
2018-02-28 17:22:20 +00:00
|
|
|
|
@user_has_permissions('send_messages')
|
2017-05-04 09:30:55 +01:00
|
|
|
|
def send_test_preview(service_id, template_id, filetype):
|
|
|
|
|
|
|
|
|
|
|
|
if filetype not in ('pdf', 'png'):
|
|
|
|
|
|
abort(404)
|
|
|
|
|
|
|
2017-06-22 16:00:14 +01:00
|
|
|
|
db_template = service_api_client.get_service_template(service_id, template_id)['data']
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
|
|
|
|
|
template = get_template(
|
2017-06-22 16:00:14 +01:00
|
|
|
|
db_template,
|
2017-05-04 09:30:55 +01:00
|
|
|
|
current_service,
|
|
|
|
|
|
letter_preview_url=url_for(
|
|
|
|
|
|
'.send_test_preview',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
filetype='png',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2017-06-23 17:30:34 +01:00
|
|
|
|
template.values = get_normalised_placeholders_from_session()
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
|
|
|
|
|
return TemplatePreview.from_utils_template(template, filetype, page=request.args.get('page'))
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-05-11 08:46:42 +01:00
|
|
|
|
def _check_messages(service_id, template_id, upload_id, preview_row, letters_as_pdf=False):
|
2016-02-22 17:17:18 +00:00
|
|
|
|
|
2018-05-03 13:35:59 +01:00
|
|
|
|
try:
|
2018-04-30 12:55:56 +01:00
|
|
|
|
# The happy path is that the job doesn’t already exist, so the
|
|
|
|
|
|
# API will return a 404 and the client will raise HTTPError.
|
|
|
|
|
|
job_api_client.get_job(service_id, upload_id)
|
2018-05-03 13:35:59 +01:00
|
|
|
|
|
|
|
|
|
|
# the job exists already - so go back to the templates page
|
2018-04-30 12:55:56 +01:00
|
|
|
|
# If we just return a `redirect` (302) object here, we'll get
|
|
|
|
|
|
# errors when we try and unpack in the check_messages route.
|
|
|
|
|
|
# Rasing a werkzeug.routing redirect means that doesn't happen.
|
|
|
|
|
|
raise RequestRedirect(url_for(
|
|
|
|
|
|
'.send_messages',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id
|
|
|
|
|
|
))
|
2018-05-03 13:35:59 +01:00
|
|
|
|
except HTTPError as e:
|
|
|
|
|
|
if e.status_code != 404:
|
|
|
|
|
|
raise
|
2018-04-30 12:55:56 +01:00
|
|
|
|
|
2016-04-04 14:28:52 +01:00
|
|
|
|
users = user_api_client.get_users_for_service(service_id=service_id)
|
2016-06-17 11:54:01 +01:00
|
|
|
|
|
2018-05-09 13:53:02 +01:00
|
|
|
|
statistics = service_api_client.get_service_statistics(service_id, today_only=True)
|
2018-07-20 08:42:01 +01:00
|
|
|
|
remaining_messages = (current_service.message_limit - sum(stat['requested'] for stat in statistics.values()))
|
2016-04-04 14:28:52 +01:00
|
|
|
|
|
2016-03-07 18:47:05 +00:00
|
|
|
|
contents = s3download(service_id, upload_id)
|
2018-03-29 17:01:35 +01:00
|
|
|
|
|
|
|
|
|
|
db_template = service_api_client.get_service_template(
|
|
|
|
|
|
service_id,
|
|
|
|
|
|
str(template_id),
|
|
|
|
|
|
)['data']
|
|
|
|
|
|
|
2017-11-02 12:07:46 +00:00
|
|
|
|
email_reply_to = None
|
|
|
|
|
|
sms_sender = None
|
2018-03-29 17:01:35 +01:00
|
|
|
|
if db_template['template_type'] == 'email':
|
2018-10-26 17:31:49 +01:00
|
|
|
|
email_reply_to = get_email_reply_to_address_from_session()
|
2018-03-29 17:01:35 +01:00
|
|
|
|
elif db_template['template_type'] == 'sms':
|
2018-10-26 17:31:49 +01:00
|
|
|
|
sms_sender = get_sms_sender_from_session()
|
2016-12-08 11:50:59 +00:00
|
|
|
|
template = get_template(
|
2018-05-10 17:00:41 +01:00
|
|
|
|
db_template,
|
2016-12-08 11:50:59 +00:00
|
|
|
|
current_service,
|
2016-12-20 14:38:34 +00:00
|
|
|
|
show_recipient=True,
|
2018-11-19 15:21:09 +00:00
|
|
|
|
expand_emails=True,
|
2016-12-20 14:38:34 +00:00
|
|
|
|
letter_preview_url=url_for(
|
2017-04-28 16:04:52 +01:00
|
|
|
|
'.check_messages_preview',
|
2016-12-20 14:38:34 +00:00
|
|
|
|
service_id=service_id,
|
2018-03-29 17:01:35 +01:00
|
|
|
|
template_id=template_id,
|
2017-04-28 16:04:52 +01:00
|
|
|
|
upload_id=upload_id,
|
|
|
|
|
|
filetype='png',
|
2017-12-06 22:04:58 +00:00
|
|
|
|
row_index=preview_row,
|
2017-10-17 16:06:15 +01:00
|
|
|
|
) if not letters_as_pdf else None,
|
2017-11-02 12:07:46 +00:00
|
|
|
|
email_reply_to=email_reply_to,
|
2018-03-29 17:01:35 +01:00
|
|
|
|
sms_sender=sms_sender,
|
2018-10-01 16:03:06 +01:00
|
|
|
|
page_count=get_page_count_for_letter(db_template),
|
2016-03-07 18:47:05 +00:00
|
|
|
|
)
|
|
|
|
|
|
recipients = RecipientCSV(
|
|
|
|
|
|
contents,
|
|
|
|
|
|
template_type=template.template_type,
|
|
|
|
|
|
placeholders=template.placeholders,
|
2016-04-07 14:30:51 +01:00
|
|
|
|
max_initial_rows_shown=50,
|
|
|
|
|
|
max_errors_shown=50,
|
2016-04-04 14:28:52 +01:00
|
|
|
|
whitelist=itertools.chain.from_iterable(
|
2016-11-08 13:12:07 +00:00
|
|
|
|
[user.name, user.mobile_number, user.email_address] for user in users
|
2018-07-20 08:42:01 +01:00
|
|
|
|
) if current_service.trial_mode else None,
|
2017-04-26 16:19:49 +01:00
|
|
|
|
remaining_messages=remaining_messages,
|
2018-07-20 08:43:02 +01:00
|
|
|
|
international_sms=current_service.has_permission('international_sms'),
|
2016-02-26 10:54:06 +00:00
|
|
|
|
)
|
2016-03-07 18:47:05 +00:00
|
|
|
|
|
2016-07-01 07:04:55 +01:00
|
|
|
|
if request.args.get('from_test'):
|
2017-06-30 11:49:03 +01:00
|
|
|
|
# only happens if generating a letter preview test
|
|
|
|
|
|
back_link = url_for('.send_test', service_id=service_id, template_id=template.id)
|
2016-08-30 09:27:24 +01:00
|
|
|
|
choose_time_form = None
|
2016-05-05 08:39:36 +01:00
|
|
|
|
else:
|
|
|
|
|
|
back_link = url_for('.send_messages', service_id=service_id, template_id=template.id)
|
2016-08-30 09:27:24 +01:00
|
|
|
|
choose_time_form = ChooseTimeForm()
|
2016-05-05 08:39:36 +01:00
|
|
|
|
|
2018-01-15 11:35:45 +00:00
|
|
|
|
if preview_row < 2:
|
|
|
|
|
|
abort(404)
|
|
|
|
|
|
|
2018-03-05 15:57:10 +00:00
|
|
|
|
if preview_row < len(recipients) + 2:
|
|
|
|
|
|
template.values = recipients[preview_row - 2].recipient_and_personalisation
|
2018-01-15 11:35:45 +00:00
|
|
|
|
elif preview_row > 2:
|
2017-12-20 11:48:30 +00:00
|
|
|
|
abort(404)
|
2016-03-07 18:47:05 +00:00
|
|
|
|
|
2016-12-20 11:56:22 +00:00
|
|
|
|
return dict(
|
2016-03-07 18:47:05 +00:00
|
|
|
|
recipients=recipients,
|
|
|
|
|
|
template=template,
|
2016-06-03 13:52:15 +01:00
|
|
|
|
errors=recipients.has_errors,
|
|
|
|
|
|
row_errors=get_errors_for_csv(recipients, template.template_type),
|
2018-03-05 15:57:10 +00:00
|
|
|
|
count_of_recipients=len(recipients),
|
|
|
|
|
|
count_of_displayed_recipients=len(list(recipients.displayed_rows)),
|
2018-07-12 15:14:58 +01:00
|
|
|
|
original_file_name=request.args.get('original_file_name', ''),
|
2016-03-29 15:59:53 +01:00
|
|
|
|
upload_id=upload_id,
|
2016-04-22 09:36:42 +01:00
|
|
|
|
form=CsvUploadForm(),
|
2016-07-25 14:16:34 +01:00
|
|
|
|
remaining_messages=remaining_messages,
|
2016-08-30 09:27:24 +01:00
|
|
|
|
choose_time_form=choose_time_form,
|
2016-07-05 11:39:07 +01:00
|
|
|
|
back_link=back_link,
|
2017-08-08 10:01:44 +01:00
|
|
|
|
help=get_help_argument(),
|
2017-08-25 14:17:23 +01:00
|
|
|
|
trying_to_send_letters_in_trial_mode=all((
|
2018-07-20 08:42:01 +01:00
|
|
|
|
current_service.trial_mode,
|
2017-08-25 14:17:23 +01:00
|
|
|
|
template.template_type == 'letter',
|
|
|
|
|
|
)),
|
2018-01-15 11:25:11 +00:00
|
|
|
|
required_recipient_columns=OrderedSet(recipients.recipient_column_headers) - optional_address_columns,
|
|
|
|
|
|
preview_row=preview_row,
|
2019-02-04 14:08:11 +00:00
|
|
|
|
sent_previously=job_api_client.has_sent_previously(
|
|
|
|
|
|
service_id, template.id, db_template['version'], request.args.get('original_file_name', '')
|
|
|
|
|
|
)
|
2016-03-07 18:47:05 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-29 17:01:35 +01:00
|
|
|
|
@main.route("/services/<service_id>/<uuid:template_id>/check/<upload_id>", methods=['GET'])
|
|
|
|
|
|
@main.route("/services/<service_id>/<uuid:template_id>/check/<upload_id>/row-<int:row_index>", methods=['GET'])
|
2016-12-20 11:56:22 +00:00
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2018-03-29 17:01:35 +01:00
|
|
|
|
def check_messages(service_id, template_id, upload_id, row_index=2):
|
2017-07-20 08:59:49 +01:00
|
|
|
|
|
2018-05-11 08:46:42 +01:00
|
|
|
|
data = _check_messages(service_id, template_id, upload_id, row_index)
|
2017-07-20 08:59:49 +01:00
|
|
|
|
|
2017-07-20 09:10:23 +01:00
|
|
|
|
if (
|
|
|
|
|
|
data['recipients'].too_many_rows or
|
|
|
|
|
|
not data['count_of_recipients'] or
|
|
|
|
|
|
not data['recipients'].has_recipient_columns or
|
2018-03-02 10:45:29 +00:00
|
|
|
|
data['recipients'].duplicate_recipient_column_headers or
|
2019-02-04 14:08:11 +00:00
|
|
|
|
data['recipients'].missing_column_headers or
|
|
|
|
|
|
data['sent_previously']
|
2017-07-20 09:10:23 +01:00
|
|
|
|
):
|
|
|
|
|
|
return render_template('views/check/column-errors.html', **data)
|
|
|
|
|
|
|
2017-07-20 08:59:49 +01:00
|
|
|
|
if data['row_errors']:
|
|
|
|
|
|
return render_template('views/check/row-errors.html', **data)
|
|
|
|
|
|
|
2017-09-14 12:21:40 +01:00
|
|
|
|
if (
|
|
|
|
|
|
data['errors'] or
|
|
|
|
|
|
data['trying_to_send_letters_in_trial_mode']
|
|
|
|
|
|
):
|
2017-07-20 08:59:49 +01:00
|
|
|
|
return render_template('views/check/column-errors.html', **data)
|
|
|
|
|
|
|
2018-07-12 15:14:58 +01:00
|
|
|
|
data['original_file_name'] = SanitiseASCII.encode(data.get('original_file_name', ''))
|
|
|
|
|
|
|
2018-11-06 14:22:22 +00:00
|
|
|
|
metadata_kwargs = {
|
|
|
|
|
|
'notification_count': data['count_of_recipients'],
|
|
|
|
|
|
'template_id': str(template_id),
|
|
|
|
|
|
'valid': True,
|
|
|
|
|
|
'original_file_name': unicode_truncate(
|
2018-07-12 15:14:58 +01:00
|
|
|
|
data['original_file_name'],
|
2018-05-11 08:46:42 +01:00
|
|
|
|
1600,
|
|
|
|
|
|
),
|
2018-11-06 14:22:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if session.get('sender_id'):
|
|
|
|
|
|
metadata_kwargs['sender_id'] = session['sender_id']
|
|
|
|
|
|
|
|
|
|
|
|
set_metadata_on_csv_upload(service_id, upload_id, **metadata_kwargs)
|
2018-05-11 08:46:42 +01:00
|
|
|
|
|
2017-07-20 08:59:49 +01:00
|
|
|
|
return render_template('views/check/ok.html', **data)
|
2016-12-20 11:56:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
2018-03-29 17:01:35 +01:00
|
|
|
|
@main.route(
|
|
|
|
|
|
"/services/<service_id>/<uuid:template_id>/check/<upload_id>.<filetype>",
|
|
|
|
|
|
methods=['GET'],
|
|
|
|
|
|
)
|
|
|
|
|
|
@main.route(
|
|
|
|
|
|
"/services/<service_id>/<uuid:template_id>/check/<upload_id>/row-<int:row_index>.<filetype>",
|
|
|
|
|
|
methods=['GET'],
|
|
|
|
|
|
)
|
2016-12-20 14:38:34 +00:00
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages')
|
2018-03-29 17:01:35 +01:00
|
|
|
|
def check_messages_preview(service_id, template_id, upload_id, filetype, row_index=2):
|
2018-10-15 14:02:13 +01:00
|
|
|
|
if filetype == 'pdf':
|
|
|
|
|
|
page = None
|
|
|
|
|
|
elif filetype == 'png':
|
|
|
|
|
|
page = request.args.get('page', 1)
|
|
|
|
|
|
else:
|
2017-04-12 12:12:11 +01:00
|
|
|
|
abort(404)
|
|
|
|
|
|
|
2016-12-20 14:38:34 +00:00
|
|
|
|
template = _check_messages(
|
2018-05-11 08:46:42 +01:00
|
|
|
|
service_id, template_id, upload_id, row_index, letters_as_pdf=True
|
2016-12-20 14:38:34 +00:00
|
|
|
|
)['template']
|
2018-10-15 14:02:13 +01:00
|
|
|
|
return TemplatePreview.from_utils_template(template, filetype, page=page)
|
2016-12-20 14:38:34 +00:00
|
|
|
|
|
2017-04-10 18:12:00 +01:00
|
|
|
|
|
2018-10-30 14:24:50 +00:00
|
|
|
|
@main.route(
|
|
|
|
|
|
"/services/<service_id>/<uuid:template_id>/check.<filetype>",
|
|
|
|
|
|
methods=['GET'],
|
|
|
|
|
|
)
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
@user_has_permissions('send_messages')
|
|
|
|
|
|
def check_notification_preview(service_id, template_id, filetype):
|
|
|
|
|
|
if filetype == 'pdf':
|
|
|
|
|
|
page = None
|
|
|
|
|
|
elif filetype == 'png':
|
|
|
|
|
|
page = request.args.get('page', 1)
|
|
|
|
|
|
else:
|
|
|
|
|
|
abort(404)
|
|
|
|
|
|
|
|
|
|
|
|
template = _check_notification(
|
|
|
|
|
|
service_id, template_id,
|
|
|
|
|
|
)['template']
|
|
|
|
|
|
return TemplatePreview.from_utils_template(template, filetype, page=page)
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-03-29 15:59:53 +01:00
|
|
|
|
@main.route("/services/<service_id>/start-job/<upload_id>", methods=['POST'])
|
2016-03-07 18:47:05 +00:00
|
|
|
|
@login_required
|
2018-02-28 18:13:29 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2016-03-07 18:47:05 +00:00
|
|
|
|
def start_job(service_id, upload_id):
|
|
|
|
|
|
|
2016-03-08 17:50:18 +00:00
|
|
|
|
job_api_client.create_job(
|
|
|
|
|
|
upload_id,
|
|
|
|
|
|
service_id,
|
2016-08-07 09:17:49 +01:00
|
|
|
|
scheduled_for=request.form.get('scheduled_for', '')
|
2016-03-08 17:50:18 +00:00
|
|
|
|
)
|
2016-03-07 18:47:05 +00:00
|
|
|
|
|
2018-11-06 14:22:22 +00:00
|
|
|
|
session.pop('sender_id', None)
|
|
|
|
|
|
|
2016-03-07 18:47:05 +00:00
|
|
|
|
return redirect(
|
2017-07-13 11:28:37 +01:00
|
|
|
|
url_for(
|
|
|
|
|
|
'main.view_job',
|
|
|
|
|
|
job_id=upload_id,
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
help=request.form.get('help'),
|
|
|
|
|
|
just_sent='yes',
|
|
|
|
|
|
)
|
2016-02-17 15:49:07 +00:00
|
|
|
|
)
|
2016-07-01 10:49:54 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@main.route("/services/<service_id>/end-tour/<example_template_id>")
|
|
|
|
|
|
@login_required
|
2018-03-01 10:30:17 +00:00
|
|
|
|
@user_has_permissions('manage_templates')
|
2016-07-01 10:49:54 +01:00
|
|
|
|
def go_to_dashboard_after_tour(service_id, example_template_id):
|
|
|
|
|
|
|
|
|
|
|
|
service_api_client.delete_service_template(service_id, example_template_id)
|
|
|
|
|
|
|
|
|
|
|
|
return redirect(
|
|
|
|
|
|
url_for('main.service_dashboard', service_id=service_id)
|
|
|
|
|
|
)
|
2017-01-19 18:15:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
2017-05-25 09:18:26 +01:00
|
|
|
|
def fields_to_fill_in(template, prefill_current_user=False):
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
|
|
|
|
|
recipient_columns = first_column_headings[template.template_type]
|
|
|
|
|
|
|
2017-05-25 09:18:26 +01:00
|
|
|
|
if 'letter' == template.template_type or not prefill_current_user:
|
2017-05-04 09:30:55 +01:00
|
|
|
|
return recipient_columns + list(template.placeholders)
|
|
|
|
|
|
|
2017-06-26 14:56:14 +01:00
|
|
|
|
session['recipient'] = current_user.mobile_number if template.template_type == 'sms' else current_user.email_address
|
2017-05-04 09:30:55 +01:00
|
|
|
|
|
|
|
|
|
|
return list(template.placeholders)
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-23 17:30:34 +01:00
|
|
|
|
def get_normalised_placeholders_from_session():
|
2017-05-04 09:30:55 +01:00
|
|
|
|
return {
|
|
|
|
|
|
key: ''.join(value or [])
|
2017-06-23 17:30:34 +01:00
|
|
|
|
for key, value in session.get('placeholders', {}).items()
|
2017-05-04 09:30:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-29 15:31:44 +01:00
|
|
|
|
def get_recipient_and_placeholders_from_session(template_type):
|
2017-06-26 14:56:14 +01:00
|
|
|
|
placeholders = get_normalised_placeholders_from_session()
|
|
|
|
|
|
|
|
|
|
|
|
if template_type == 'sms':
|
|
|
|
|
|
placeholders['phone_number'] = session['recipient']
|
|
|
|
|
|
else:
|
|
|
|
|
|
placeholders['email_address'] = session['recipient']
|
|
|
|
|
|
|
|
|
|
|
|
return placeholders
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-05-04 09:30:55 +01:00
|
|
|
|
def make_and_upload_csv_file(service_id, template):
|
|
|
|
|
|
upload_id = s3upload(
|
|
|
|
|
|
service_id,
|
|
|
|
|
|
Spreadsheet.from_dict(
|
2017-06-23 17:30:34 +01:00
|
|
|
|
session['placeholders'],
|
2017-05-04 09:30:55 +01:00
|
|
|
|
filename=current_app.config['TEST_MESSAGE_FILENAME']
|
|
|
|
|
|
).as_dict,
|
|
|
|
|
|
current_app.config['AWS_REGION'],
|
|
|
|
|
|
)
|
|
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'.check_messages',
|
|
|
|
|
|
upload_id=upload_id,
|
|
|
|
|
|
service_id=service_id,
|
2018-04-04 17:10:22 +01:00
|
|
|
|
template_id=template.id,
|
2017-05-04 09:30:55 +01:00
|
|
|
|
from_test=True,
|
|
|
|
|
|
help=2 if get_help_argument() else 0
|
|
|
|
|
|
))
|
2017-05-25 09:18:26 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def all_placeholders_in_session(placeholders):
|
|
|
|
|
|
return all(
|
2017-06-23 17:30:34 +01:00
|
|
|
|
get_normalised_placeholders_from_session().get(placeholder, False) not in (False, None)
|
2017-05-25 09:18:26 +01:00
|
|
|
|
for placeholder in placeholders
|
|
|
|
|
|
)
|
2017-05-25 13:31:23 +01:00
|
|
|
|
|
|
|
|
|
|
|
2018-08-06 11:20:50 +01:00
|
|
|
|
def get_send_test_page_title(template_type, help_argument, entering_recipient, name=None):
|
2017-05-25 13:31:51 +01:00
|
|
|
|
if help_argument:
|
2017-05-25 13:31:23 +01:00
|
|
|
|
return 'Example text message'
|
2017-11-20 16:45:59 +00:00
|
|
|
|
if entering_recipient:
|
2018-08-06 11:20:50 +01:00
|
|
|
|
return 'Send ‘{}’'.format(name)
|
2017-11-20 16:45:59 +00:00
|
|
|
|
return 'Personalise this message'
|
2017-06-22 16:00:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
2018-11-30 10:58:32 +00:00
|
|
|
|
def is_current_user_the_recipient():
|
2018-11-30 14:16:11 +00:00
|
|
|
|
if 'recipient' not in session:
|
|
|
|
|
|
return False
|
2018-12-03 17:53:47 +00:00
|
|
|
|
if hasattr(current_user, 'mobile_number'):
|
|
|
|
|
|
return session['recipient'] in {current_user.email_address, current_user.mobile_number}
|
2018-11-30 10:58:32 +00:00
|
|
|
|
return session['recipient'] == current_user.email_address
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-08-09 16:29:51 +01:00
|
|
|
|
def get_back_link(service_id, template, step_index):
|
2017-06-22 16:00:14 +01:00
|
|
|
|
if get_help_argument():
|
2017-06-30 12:33:31 +01:00
|
|
|
|
# if we're on the check page, redirect back to the beginning. anywhere else, don't return the back link
|
|
|
|
|
|
if request.endpoint == 'main.check_notification':
|
|
|
|
|
|
return url_for(
|
|
|
|
|
|
'main.send_test',
|
|
|
|
|
|
service_id=service_id,
|
2018-08-09 16:29:51 +01:00
|
|
|
|
template_id=template.id,
|
2017-06-30 12:33:31 +01:00
|
|
|
|
help=get_help_argument()
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
return None
|
2017-06-22 16:00:14 +01:00
|
|
|
|
elif step_index == 0:
|
2018-08-09 16:29:51 +01:00
|
|
|
|
if should_skip_template_page(template.template_type):
|
2018-06-13 14:32:52 +01:00
|
|
|
|
return url_for(
|
2018-08-09 16:29:51 +01:00
|
|
|
|
'.choose_template',
|
2018-06-13 14:32:52 +01:00
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
return url_for(
|
2018-08-09 16:29:51 +01:00
|
|
|
|
'.view_template',
|
2018-06-13 14:32:52 +01:00
|
|
|
|
service_id=service_id,
|
2018-08-09 16:29:51 +01:00
|
|
|
|
template_id=template.id,
|
2018-06-13 14:32:52 +01:00
|
|
|
|
)
|
2018-11-30 10:58:32 +00:00
|
|
|
|
elif is_current_user_the_recipient() and step_index > 1:
|
2019-01-30 12:02:45 +00:00
|
|
|
|
return url_for(
|
|
|
|
|
|
'main.send_test_step',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template.id,
|
|
|
|
|
|
step_index=step_index - 1,
|
|
|
|
|
|
)
|
2018-08-09 16:29:51 +01:00
|
|
|
|
|
2017-06-22 16:00:14 +01:00
|
|
|
|
else:
|
|
|
|
|
|
return url_for(
|
2018-06-13 14:32:52 +01:00
|
|
|
|
'main.send_one_off_step',
|
2017-06-22 16:00:14 +01:00
|
|
|
|
service_id=service_id,
|
2018-08-09 16:29:51 +01:00
|
|
|
|
template_id=template.id,
|
2017-06-22 16:00:14 +01:00
|
|
|
|
step_index=step_index - 1,
|
|
|
|
|
|
)
|
2017-06-23 15:02:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@main.route("/services/<service_id>/template/<template_id>/notification/check", methods=['GET'])
|
|
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2017-06-23 15:02:20 +01:00
|
|
|
|
def check_notification(service_id, template_id):
|
2018-10-30 14:24:50 +00:00
|
|
|
|
return render_template(
|
|
|
|
|
|
'views/notifications/check.html',
|
|
|
|
|
|
**_check_notification(service_id, template_id),
|
|
|
|
|
|
)
|
2017-06-29 15:31:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _check_notification(service_id, template_id, exception=None):
|
2017-06-23 15:02:20 +01:00
|
|
|
|
db_template = service_api_client.get_service_template(service_id, template_id)['data']
|
2017-11-02 12:07:46 +00:00
|
|
|
|
email_reply_to = None
|
|
|
|
|
|
sms_sender = None
|
|
|
|
|
|
if db_template['template_type'] == 'email':
|
2018-10-26 17:31:49 +01:00
|
|
|
|
email_reply_to = get_email_reply_to_address_from_session()
|
2017-11-02 12:07:46 +00:00
|
|
|
|
elif db_template['template_type'] == 'sms':
|
2018-10-26 17:31:49 +01:00
|
|
|
|
sms_sender = get_sms_sender_from_session()
|
2017-06-23 15:02:20 +01:00
|
|
|
|
template = get_template(
|
|
|
|
|
|
db_template,
|
|
|
|
|
|
current_service,
|
2017-10-17 16:06:15 +01:00
|
|
|
|
show_recipient=True,
|
2018-11-19 14:42:33 +00:00
|
|
|
|
expand_emails=True,
|
2017-11-02 12:07:46 +00:00
|
|
|
|
email_reply_to=email_reply_to,
|
2018-10-30 14:24:50 +00:00
|
|
|
|
sms_sender=sms_sender,
|
|
|
|
|
|
letter_preview_url=url_for(
|
|
|
|
|
|
'.check_notification_preview',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
filetype='png',
|
|
|
|
|
|
),
|
|
|
|
|
|
page_count=get_page_count_for_letter(db_template),
|
2017-06-23 15:02:20 +01:00
|
|
|
|
)
|
2017-06-26 17:09:51 +01:00
|
|
|
|
|
2018-08-09 16:29:51 +01:00
|
|
|
|
back_link = get_back_link(service_id, template, len(fields_to_fill_in(template)))
|
2017-06-26 17:09:51 +01:00
|
|
|
|
|
|
|
|
|
|
if (
|
2018-10-30 14:24:50 +00:00
|
|
|
|
(
|
|
|
|
|
|
not session.get('recipient')
|
|
|
|
|
|
and db_template['template_type'] != 'letter'
|
|
|
|
|
|
)
|
|
|
|
|
|
or not all_placeholders_in_session(template.placeholders)
|
2017-06-26 17:09:51 +01:00
|
|
|
|
):
|
2018-10-30 14:24:50 +00:00
|
|
|
|
raise RequestRedirect(back_link)
|
2017-06-26 17:09:51 +01:00
|
|
|
|
|
2017-06-29 15:31:44 +01:00
|
|
|
|
template.values = get_recipient_and_placeholders_from_session(template.template_type)
|
2018-10-30 14:24:50 +00:00
|
|
|
|
return dict(
|
2017-06-23 15:02:20 +01:00
|
|
|
|
template=template,
|
|
|
|
|
|
back_link=back_link,
|
|
|
|
|
|
help=get_help_argument(),
|
2018-10-30 14:24:50 +00:00
|
|
|
|
**(get_template_error_dict(exception) if exception else {}),
|
2017-06-23 15:02:20 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-29 15:31:44 +01:00
|
|
|
|
def get_template_error_dict(exception):
|
2017-06-29 16:06:36 +01:00
|
|
|
|
# TODO: Make API return some computer-friendly identifier as well as the end user error messages
|
2017-07-27 16:28:49 +01:00
|
|
|
|
if 'service is in trial mode' in exception.message:
|
2017-06-29 15:31:44 +01:00
|
|
|
|
error = 'not-allowed-to-send-to'
|
2017-07-27 16:28:49 +01:00
|
|
|
|
elif 'Exceeded send limits' in exception.message:
|
2017-06-29 16:06:36 +01:00
|
|
|
|
error = 'too-many-messages'
|
2017-07-27 16:28:49 +01:00
|
|
|
|
elif 'Content for template has a character count greater than the limit of' in exception.message:
|
2017-06-29 16:06:36 +01:00
|
|
|
|
error = 'message-too-long'
|
2017-06-29 15:31:44 +01:00
|
|
|
|
else:
|
|
|
|
|
|
raise exception
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
'error': error,
|
2018-08-16 16:51:32 +01:00
|
|
|
|
'SMS_CHAR_COUNT_LIMIT': SMS_CHAR_COUNT_LIMIT,
|
2017-06-29 16:06:36 +01:00
|
|
|
|
'current_service': current_service,
|
|
|
|
|
|
|
|
|
|
|
|
# used to trigger CSV specific err msg content, so not needed for single notification errors.
|
|
|
|
|
|
'original_file_name': False
|
2017-06-29 15:31:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-23 15:02:20 +01:00
|
|
|
|
@main.route("/services/<service_id>/template/<template_id>/notification/check", methods=['POST'])
|
|
|
|
|
|
@login_required
|
2018-03-01 11:04:25 +00:00
|
|
|
|
@user_has_permissions('send_messages', restrict_admin_usage=True)
|
2017-06-23 15:02:20 +01:00
|
|
|
|
def send_notification(service_id, template_id):
|
2017-06-23 17:30:34 +01:00
|
|
|
|
if {'recipient', 'placeholders'} - set(session.keys()):
|
2017-06-23 15:02:20 +01:00
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'.send_one_off',
|
|
|
|
|
|
service_id=service_id,
|
|
|
|
|
|
template_id=template_id,
|
|
|
|
|
|
))
|
2017-06-29 15:31:44 +01:00
|
|
|
|
try:
|
|
|
|
|
|
noti = notification_api_client.send_notification(
|
|
|
|
|
|
service_id,
|
|
|
|
|
|
template_id=template_id,
|
2018-10-30 14:24:50 +00:00
|
|
|
|
recipient=session['recipient'] or session['placeholders']['address line 1'],
|
2017-10-16 16:35:35 +01:00
|
|
|
|
personalisation=session['placeholders'],
|
|
|
|
|
|
sender_id=session['sender_id'] if 'sender_id' in session else None
|
2017-06-29 15:31:44 +01:00
|
|
|
|
)
|
|
|
|
|
|
except HTTPError as exception:
|
2017-06-29 16:06:36 +01:00
|
|
|
|
current_app.logger.info('Service {} could not send notification: "{}"'.format(
|
2018-07-20 08:42:01 +01:00
|
|
|
|
current_service.id,
|
2017-06-29 16:06:36 +01:00
|
|
|
|
exception.message
|
|
|
|
|
|
))
|
2018-10-30 14:24:50 +00:00
|
|
|
|
return render_template(
|
|
|
|
|
|
'views/notifications/check.html',
|
|
|
|
|
|
**_check_notification(service_id, template_id, exception),
|
|
|
|
|
|
)
|
2017-06-23 15:02:20 +01:00
|
|
|
|
|
2017-06-23 17:30:34 +01:00
|
|
|
|
session.pop('placeholders')
|
|
|
|
|
|
session.pop('recipient')
|
2017-10-16 16:35:35 +01:00
|
|
|
|
session.pop('sender_id', None)
|
2017-06-23 15:02:20 +01:00
|
|
|
|
|
|
|
|
|
|
return redirect(url_for(
|
|
|
|
|
|
'.view_notification',
|
|
|
|
|
|
service_id=service_id,
|
2017-06-30 11:49:03 +01:00
|
|
|
|
notification_id=noti['id'],
|
|
|
|
|
|
help=request.args.get('help')
|
2017-06-23 15:02:20 +01:00
|
|
|
|
))
|
2017-10-17 16:06:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
2018-10-26 17:31:49 +01:00
|
|
|
|
def get_email_reply_to_address_from_session():
|
2017-10-17 16:06:15 +01:00
|
|
|
|
if session.get('sender_id'):
|
2018-10-26 17:31:49 +01:00
|
|
|
|
return current_service.get_email_reply_to_address(
|
|
|
|
|
|
session['sender_id']
|
2017-10-17 16:06:15 +01:00
|
|
|
|
)['email_address']
|
2017-11-02 12:07:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
2018-10-26 17:31:49 +01:00
|
|
|
|
def get_sms_sender_from_session():
|
2017-11-02 12:07:46 +00:00
|
|
|
|
if session.get('sender_id'):
|
2018-10-26 17:31:49 +01:00
|
|
|
|
return current_service.get_sms_sender(
|
|
|
|
|
|
session['sender_id']
|
2017-11-02 12:07:46 +00:00
|
|
|
|
)['sms_sender']
|
2018-06-08 12:49:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_spreadsheet_column_headings_from_template(template):
|
|
|
|
|
|
column_headings = []
|
|
|
|
|
|
|
|
|
|
|
|
for column_heading in (
|
|
|
|
|
|
first_column_headings[template.template_type] + list(template.placeholders)
|
|
|
|
|
|
):
|
|
|
|
|
|
if column_heading not in Columns.from_keys(column_headings):
|
|
|
|
|
|
column_headings.append(column_heading)
|
|
|
|
|
|
|
|
|
|
|
|
return column_headings
|