From 0391348b5d0bafea25866a14f46dcaa7846339eb Mon Sep 17 00:00:00 2001 From: dandds Date: Wed, 5 Sep 2018 17:45:12 -0400 Subject: [PATCH] basic task order pdf downloads --- atst/routes/requests/approval.py | 17 ++++++++++-- atst/uploader.py | 5 ++-- templates/requests/_review.html | 8 ++++++ templates/requests/approval.html | 2 +- tests/routes/test_request_approval.py | 38 +++++++++++++++++++++++++++ tests/test_uploader.py | 16 +++++++++++ 6 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 tests/routes/test_request_approval.py diff --git a/atst/routes/requests/approval.py b/atst/routes/requests/approval.py index 9df64395..e9525ec7 100644 --- a/atst/routes/requests/approval.py +++ b/atst/routes/requests/approval.py @@ -1,7 +1,9 @@ -from flask import render_template, g +from flask import render_template, g, Response +from flask import current_app as app from . import requests_bp from atst.domain.requests import Requests +from atst.domain.exceptions import NotFoundError def task_order_dictionary(task_order): @@ -19,4 +21,15 @@ def approval(request_id): if request.task_order: data["task_order"] = task_order_dictionary(request.task_order) - return render_template("requests/approval.html", data=data, financial_review=True) + return render_template("requests/approval.html", data=data, request_id=request.id, financial_review=True) + + +@requests_bp.route("/requests/task_order_download/", methods=["GET"]) +def task_order_pdf_download(request_id): + request = Requests.get(g.current_user, request_id) + if request.task_order and request.task_order.pdf: + object_name = request.task_order.pdf.object_name + generator = app.uploader.download_stream(object_name) + return Response(generator, mimetype="application/pdf") + else: + raise NotFoundError("task_order pdf") diff --git a/atst/uploader.py b/atst/uploader.py index e63ba4ce..5955913c 100644 --- a/atst/uploader.py +++ b/atst/uploader.py @@ -37,8 +37,9 @@ class Uploader: ) return (fyle.filename, object_name) - def download(self, path): - pass + def download_stream(self, object_name): + obj = self.container.get_object(object_name=object_name) + return obj.as_stream() def _get_container(self, provider, container, key, secret): if provider == "LOCAL": diff --git a/templates/requests/_review.html b/templates/requests/_review.html index 7e7fb33d..8ba3dfda 100644 --- a/templates/requests/_review.html +++ b/templates/requests/_review.html @@ -153,6 +153,14 @@ {{ DefinitionReviewField("
CLIN 2003
-
Unclassified Cloud Support Package
OPTION PERIOD 2
", "task_order", "clin_2003", filter="dollars") }} +
+
Task Order PDF
+
+ + Download the Task Order PDF + +
+
{{ DefinitionReviewField("Unique Item Identifier (UII)s related to your application(s) if you already have them", "financial_verification", "uii_ids", filter="renderList") }} diff --git a/templates/requests/approval.html b/templates/requests/approval.html index 6f9b8dd8..9d219c6d 100644 --- a/templates/requests/approval.html +++ b/templates/requests/approval.html @@ -18,7 +18,7 @@

Ongoing maintainence for Death Star (a moon-sized Imperial military battlestation armed with a planet-destroying superlaser). Its definitely hasn't been sabotaged from the start.

- {% with data=data, service_branches=service_branches %} + {% with data=data, request_id=request_id %} {% include "requests/_review.html" %} {% endwith %} diff --git a/tests/routes/test_request_approval.py b/tests/routes/test_request_approval.py new file mode 100644 index 00000000..7e89026f --- /dev/null +++ b/tests/routes/test_request_approval.py @@ -0,0 +1,38 @@ +import os +from flask import url_for + +from atst.models.attachment import Attachment +from tests.factories import RequestFactory, TaskOrderFactory, UserFactory + + +def test_approval(): + pass + + +def test_task_order_download(app, client, user_session, pdf_upload): + user = UserFactory.create() + user_session(user) + + attachment = Attachment.attach(pdf_upload) + task_order = TaskOrderFactory.create(number="abc123", pdf=attachment) + request = RequestFactory.create(task_order=task_order, creator=user) + + # ensure that real data for pdf upload has been flushed to disk + pdf_upload.seek(0) + pdf_content = pdf_upload.read() + pdf_upload.close() + full_path = os.path.join(app.config.get("STORAGE_CONTAINER"), attachment.object_name) + with open(full_path, "wb") as output_file: + output_file.write(pdf_content) + output_file.flush() + + response = client.get(url_for("requests.task_order_pdf_download", request_id=request.id)) + assert response.data == pdf_content + + +def test_task_order_download_does_not_exist(client, user_session): + user = UserFactory.create() + user_session(user) + request = RequestFactory.create(creator=user) + response = client.get(url_for("requests.task_order_pdf_download", request_id=request.id)) + assert response.status_code == 404 diff --git a/tests/test_uploader.py b/tests/test_uploader.py index 89ec1b73..131277f5 100644 --- a/tests/test_uploader.py +++ b/tests/test_uploader.py @@ -31,3 +31,19 @@ def test_upload_fails_for_non_pdfs(uploader): fs = FileStorage(fp, content_type="text/plain") with pytest.raises(UploadError): uploader.upload(fs) + + +def test_download_stream(upload_dir, uploader, pdf_upload): + # write pdf content to upload file storage and make sure it is flushed to + # disk + pdf_upload.seek(0) + pdf_content = pdf_upload.read() + pdf_upload.close() + full_path = os.path.join(upload_dir, "abc") + with open(full_path, "wb") as output_file: + output_file.write(pdf_content) + output_file.flush() + + stream = uploader.download_stream("abc") + stream_content = b"".join([b for b in stream]) + assert pdf_content == stream_content