diff --git a/edivorce/apps/core/templates/pdf/images_to_pdf.html b/edivorce/apps/core/templates/pdf/images_to_pdf.html new file mode 100644 index 00000000..aaf9a707 --- /dev/null +++ b/edivorce/apps/core/templates/pdf/images_to_pdf.html @@ -0,0 +1,40 @@ +{% load static %} +{% load format_utils %} + + + + + + + + {{ form }} + + + + + + {% include 'partials/gtm_head.html' %} + + + + + + + + + diff --git a/edivorce/apps/core/templatetags/format_utils.py b/edivorce/apps/core/templatetags/format_utils.py index 3401dde2..ae6d422c 100644 --- a/edivorce/apps/core/templatetags/format_utils.py +++ b/edivorce/apps/core/templatetags/format_utils.py @@ -191,3 +191,19 @@ def agreed_child_support_amount(context, claimant_id, line_breaks=True): return context.get('amount_income_over_high_income_limit_{}'.format(claimant_id), '') else: return linebreaksli(context.get('amount_income_over_high_income_limit_{}'.format(claimant_id), '')) + + +@register.filter +def css_rotate(image): + """ Gets extra CSS needed for image rotation when generating PDFs """ + if image.rotation == 90 or image.rotation == 270: + height = image.width + width = image.height + else: + height = image.height + width = image.width + + if width == 0 or height/width < 1.3: + return 'width: 100%' + else: + return 'height: 26.7cm' diff --git a/edivorce/apps/core/urls.py b/edivorce/apps/core/urls.py index 0deb0204..f37c1737 100644 --- a/edivorce/apps/core/urls.py +++ b/edivorce/apps/core/urls.py @@ -7,7 +7,7 @@ urlpatterns = [ # url(r'^guide$', styleguide.guide), url(r'^api/response$', api.UserResponseHandler.as_view()), url(r'^api/documents/$', api.DocumentCreateView.as_view(), name='documents'), - path('api/documents//', api.get_document_file_by_key, name='file_by_key'), + path('api/documents///', api.get_document_file_by_key, name='document_by_key'), # we add an extra 'x' to the file extension so the siteminder proxy doesn't treat it as an image path('api/documents///x//', api.DocumentView.as_view(), name='document'), @@ -32,6 +32,7 @@ urlpatterns = [ # url(r'^headers$', system.headers), url(r'^pdf-form(?P[0-9]{1,3}(_we|_claimant1|_claimant2)?)$', pdf.form, name="pdf_form"), + path('pdf-images///', pdf.images_to_pdf, name='pdf_images'), url(r'^prequalification/step_(?P[0-9]{2})$', main.prequalification, name="prequalification"), url(r'^question/(?P.*)/(?P.*)/$', main.question, name="question_steps"), url(r'^question/(?P.*)$', main.question, name="question_steps"), diff --git a/edivorce/apps/core/views/api.py b/edivorce/apps/core/views/api.py index eb397b49..a6a42108 100644 --- a/edivorce/apps/core/views/api.py +++ b/edivorce/apps/core/views/api.py @@ -5,6 +5,7 @@ from rest_framework import permissions, status from rest_framework.generics import CreateAPIView, ListAPIView, RetrieveUpdateDestroyAPIView from rest_framework.views import APIView from rest_framework.response import Response +from PIL import Image from ..models import Document, Question from ..serializer import CreateDocumentSerializer, DocumentMetadataSerializer, UserResponseSerializer @@ -87,9 +88,44 @@ class DocumentView(RetrieveUpdateDestroyAPIView): return HttpResponse(file_contents, content_type=content_type) -def get_document_file_by_key(request, file_key): +def get_document_file_by_key(request, file_key, rotation): file = Document.get_file(file_key) if not file: return HttpResponseNotFound() content_type = Document.content_type_from_filename(file.name) - return HttpResponse(file, content_type=content_type) + + # if it's a PDF or it doesn't require rotation + if content_type == 'application/pdf' or rotation == 0: + try: + return HttpResponse(file, content_type=content_type) + except TypeError: + raise Http404("File not found") + + # if the file needs to be rotated + rot_img = __rotate_image(file, rotation) + extension = __get_file_extension(file) + + try: + response = HttpResponse(content_type=content_type) + rot_img.save(response, extension) + return response + except TypeError: + raise Http404("File not found") + + +def __get_file_extension(file): + extension = re.split(r'[\._]', file.name.upper())[-1] + if extension == "JPG" or extension == "JPE": + return "JPEG" + return extension + + +def __rotate_image(file, rotation): + im = Image.open(file) + + if rotation == 90: + return im.transpose(Image.ROTATE_270) + elif rotation == 270: + return im.transpose(Image.ROTATE_90) + else: + return im.transpose(Image.ROTATE_180) diff --git a/edivorce/apps/core/views/pdf.py b/edivorce/apps/core/views/pdf.py index 5d307203..00fc472e 100644 --- a/edivorce/apps/core/views/pdf.py +++ b/edivorce/apps/core/views/pdf.py @@ -9,6 +9,7 @@ from django.template.loader import render_to_string import requests from ..decorators import bceid_required +from ..models import Document from ..utils.derived import get_derived_data from ..utils.user_response import get_data_for_user @@ -66,8 +67,12 @@ def __render_form(request, form_name, context): if output_as_html: context['css_root'] = settings.FORCE_SCRIPT_NAME[:-1] + template_name = form_name + if not form_name.startswith('form'): + template_name = 'images_to_pdf' + # render to form as HTML - rendered_html = render_to_string('pdf/' + form_name + '.html', + rendered_html = render_to_string('pdf/' + template_name + '.html', context=context, request=request) # if '?html' is in the querystring, then return the plain html @@ -93,3 +98,30 @@ def __add_claimant_info(responses, claimant): claimant_info[claimant_key] = responses[key] responses.update(claimant_info) return responses + + +@bceid_required +def images_to_pdf(request, doc_type, party_code): + documents = Document.objects.filter( + bceid_user=request.user, doc_type=doc_type, party_code=party_code) + + if not documents: + return HttpResponse(status=204) + + if party_code == 1: + form_name = doc_type + "_claimant1" + elif party_code == 2: + form_name = doc_type + "_claimant2" + else: + form_name = doc_type + + if documents[0].filename.endswith(('.pdf', '.PDF')): + response = HttpResponse(documents[0].file.read(), content_type='application/pdf') + response['Content-Disposition'] = 'inline;filename=' + form_name + '.pdf' + return response + + return __render_form(request, form_name, { + 'css_root': settings.WEASYPRINT_CSS_LOOPBACK, + 'images': documents, + 'form': form_name + }) diff --git a/requirements.txt b/requirements.txt index 936bc4af..31d972b5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,6 +19,7 @@ gunicorn==20.0.4 idna==2.10 libsass==0.20.0 marshmallow==3.7.1 +Pillow==7.2.0 promise==2.3 psycopg2==2.8.5 python-dotenv==0.14.0 diff --git a/vue/src/components/Uploader/Uploader.vue b/vue/src/components/Uploader/Uploader.vue index 15ed3967..c1a54d8c 100644 --- a/vue/src/components/Uploader/Uploader.vue +++ b/vue/src/components/Uploader/Uploader.vue @@ -98,6 +98,9 @@
(Maximum {{ maxMegabytes }} MB)
+ + {{ pdfURL }} + {{ warningText }}