Changed page flow to first save file and then redirect to check.

On check numbers in file are validated.

Posting to check then uploads file to s3
This commit is contained in:
Adam Shimali
2016-01-13 17:32:40 +00:00
parent 7c246ba3ac
commit 4dcb180da1
7 changed files with 106 additions and 38 deletions

15
app/main/uploader.py Normal file
View File

@@ -0,0 +1,15 @@
import os
import uuid
from boto3 import resource
# TODO add service name to bucket name as well
def s3upload(filepath):
filename = filepath.split(os.path.sep)[-1]
upload_id = str(uuid.uuid4())
s3 = resource('s3')
s3.create_bucket(Bucket=upload_id)
key = s3.Object(upload_id, filename)
key.put(Body=open(filepath, 'rb'), ServerSideEncryption='AES256')
return upload_id

View File

@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-
import time
from flask import render_template
from flask import (
render_template,
session
)
from flask_login import login_required
from app.main import main
from ._jobs import jobs
now = time.strftime('%H:%M')
@@ -55,6 +58,11 @@ def showjobs(service_id):
@main.route("/services/<int:service_id>/jobs/<job_id>")
@login_required
def showjob(service_id, job_id):
# TODO the uploaded file name could be part of job definition
# so won't need to be passed on from last view via session
uploaded_file_name = session.get(job_id)
return render_template(
'views/job.html',
messages=messages,
@@ -68,7 +76,7 @@ def showjob(service_id, job_id):
])
},
cost=u'£0.00',
uploaded_file_name='dispatch_20151114.csv',
uploaded_file_name=uploaded_file_name,
uploaded_file_time=now,
template_used='Test message 1',
flash_message=u'Weve started sending your messages',

View File

@@ -1,5 +1,8 @@
import csv
import re
import os
from datetime import date
from flask import (
request,
@@ -12,9 +15,11 @@ from flask import (
)
from flask_login import login_required
from werkzeug import secure_filename
from app.main import main
from app.main.forms import CsvUploadForm
from app.main.uploader import s3upload
# TODO move this to the templates directory
message_templates = [
@@ -39,26 +44,27 @@ message_templates = [
@login_required
def sendsms(service_id):
form = CsvUploadForm()
if form.validate_on_submit():
csv_file = form.file.data
# in memory handing is temporary until next story to save csv file
if form.validate_on_submit():
try:
results = _build_upload_result(csv_file)
except Exception:
message = 'There was a problem with the file: {}'.format(
csv_file = form.file.data
filename = _format_filename(csv_file.filename)
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'],
filename)
csv_file.save(filepath)
_check_file(csv_file.filename, filepath)
return redirect(url_for('.checksms',
service_id=service_id,
recipients=filename))
except (IOError, ValueError) as e:
message = 'There was a problem uploading: {}'.format(
csv_file.filename)
flash(message)
if isinstance(e, ValueError):
flash(str(e))
os.remove(filepath)
return redirect(url_for('.sendsms', service_id=service_id))
if not results['valid'] and not results['rejects']:
message = "The file {} contained no data".format(csv_file.filename)
flash(message, 'error')
return redirect(url_for('.sendsms', service_id=service_id))
session[csv_file.filename] = results
return redirect(url_for('.checksms', service_id=service_id, recipients=csv_file.filename))
return render_template('views/send-sms.html',
message_templates=message_templates,
form=form,
@@ -69,33 +75,59 @@ def sendsms(service_id):
@login_required
def checksms(service_id):
if request.method == 'GET':
recipients_filename = request.args.get('recipients')
# upload results in session until file is persisted in next story
upload_result = session.get(recipients_filename)
filename = request.args.get('recipients')
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'],
filename)
upload_result = _build_upload_result(filepath)
if upload_result.get('rejects'):
flash('There was a problem with some of the numbers')
return render_template(
'views/check-sms.html',
upload_result=upload_result,
filename=filename,
message_template=message_templates[0]['body'],
service_id=service_id
)
elif request.method == 'POST':
return redirect(url_for('.showjob', service_id=service_id, job_id=456))
filename = request.form['recipients']
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'],
filename)
try:
upload_id = s3upload(filepath)
# TODO when job is created record filename in job itself
# so downstream pages can get the original filename that way
session[upload_id] = filename
return redirect(url_for('.showjob', service_id=service_id, job_id=upload_id))
except:
flash('There as a problem saving the file')
return redirect(url_for('.checksms', recipients=filename))
def _check_file(filename, filepath):
if os.stat(filepath).st_size == 0:
message = 'The file {} contained no data'.format(filename)
raise ValueError(message)
def _format_filename(filename):
d = date.today()
basename, extenstion = filename.split('.')
formatted_name = '{}_{}.csv'.format(basename, d.strftime('%Y%m%d'))
return secure_filename(formatted_name)
def _build_upload_result(csv_file):
pattern = re.compile(r'^\+44\s?\d{4}\s?\d{6}$')
reader = csv.DictReader(
csv_file.read().decode('utf-8').splitlines(),
lineterminator='\n',
quoting=csv.QUOTE_NONE)
valid, rejects = [], []
for i, row in enumerate(reader):
if pattern.match(row['phone']):
valid.append(row)
else:
rejects.append({"line_number": i+2, "phone": row['phone']})
with open(csv_file) as f:
reader = csv.DictReader(
f,
lineterminator='\n',
quoting=csv.QUOTE_NONE)
valid, rejects = [], []
for i, row in enumerate(reader):
if pattern.match(row['phone']):
valid.append(row)
else:
rejects.append({"line_number": i+2, "phone": row['phone']})
return {"valid": valid, "rejects": rejects}

View File

@@ -59,6 +59,8 @@
back_link = url_for(".sendsms", service_id=service_id)
)}}
<input type='hidden' name='recipients' value='{{filename}}'>
</form>
{% endif %}
{% endblock %}