diff --git a/exporter/core/helpers.py b/exporter/core/helpers.py index dce445ec9..7fb8762c2 100644 --- a/exporter/core/helpers.py +++ b/exporter/core/helpers.py @@ -262,7 +262,7 @@ def has_organisation_firearm_act_document(application, document_type): def get_organisation_firearm_act_document(application, document_type): - documents = get_organisation_documents(application) + documents = 33(application) return documents[document_type] diff --git a/exporter/f680/application_sections/supporting_documents/__init__.py b/exporter/f680/application_sections/supporting_documents/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/exporter/f680/application_sections/supporting_documents/forms.py b/exporter/f680/application_sections/supporting_documents/forms.py new file mode 100644 index 000000000..49badc952 --- /dev/null +++ b/exporter/f680/application_sections/supporting_documents/forms.py @@ -0,0 +1,34 @@ +from core.common.forms import BaseForm +from django import forms + +from core.file_handler import validate_mime_type +from exporter.core.constants import FileUploadFileTypes +from exporter.core.forms import PotentiallyUnsafeClearableFileInput + + +class F680AttachSupportingDocument(BaseForm): + class Layout: + TITLE = "Attach a supporting document" + + file = forms.FileField( + label=FileUploadFileTypes.UPLOAD_GUIDANCE_TEXT, + error_messages={ + "required": "supporting document required", + }, + validators=[ + validate_mime_type, + ], + widget=PotentiallyUnsafeClearableFileInput, + ) + + description = forms.CharField( + widget=forms.Textarea(attrs={"rows": "5"}), + label="Description (optional)", + required=False, + ) + + def get_layout_fields(self): + return ( + "file", + "description", + ) diff --git a/exporter/f680/application_sections/supporting_documents/urls.py b/exporter/f680/application_sections/supporting_documents/urls.py new file mode 100644 index 000000000..025f95619 --- /dev/null +++ b/exporter/f680/application_sections/supporting_documents/urls.py @@ -0,0 +1,11 @@ +from django.urls import path + +from . import views + + +app_name = "supporting_documents" + +urlpatterns = [ + path("", views.SupportingDocumentsView.as_view(), name="add"), + path("attach-document/", views.SupportingDocumentsAddView.as_view(), name="attach"), +] diff --git a/exporter/f680/application_sections/supporting_documents/views.py b/exporter/f680/application_sections/supporting_documents/views.py new file mode 100644 index 000000000..a234a256f --- /dev/null +++ b/exporter/f680/application_sections/supporting_documents/views.py @@ -0,0 +1,92 @@ +from http import HTTPStatus + +from django.views.generic import TemplateView +from django.urls import reverse + +from core.decorators import expect_status + +from core.helpers import get_document_data +from exporter.f680.views import F680FeatureRequiredMixin +from exporter.f680.services import get_f680_application, get_f680_documents, post_f680_document +from django.views.generic import FormView + +from .forms import F680AttachSupportingDocument + + +class SupportingDocumentsView(F680FeatureRequiredMixin, TemplateView): + template_name = "f680/supporting_documents/supporting-documents-documents.html" + + @expect_status( + HTTPStatus.OK, + "Error getting F680 documents", + "Unexpected error getting F680 documents", + reraise_404=True, + ) + def get_f680_supporting_documents(self, application_id): + # A new F680 Endpoint which retrieved all the documents from + # Application document + # We could then potentially filter based on what's in the supporting-section + # Of the JSON however this isn't nesseasry for first parse since we only have supporting + # documents + return get_f680_documents(self.request, application_id) + + @expect_status( + HTTPStatus.OK, + "Error retrieving F680 application", + "Unexpected error retrieving F680 application", + reraise_404=True, + ) + def get_f680_application(self, pk): + return get_f680_application(self.request, pk) + + def setup(self, request, *args, **kwargs): + super().setup(request, *args, **kwargs) + self.application, _ = self.get_f680_application(kwargs["pk"]) + self.supporting_documents, _ = self.get_f680_supporting_documents(self.kwargs["pk"]) + + def get_context_data(self, pk, **kwargs): + return { + "application": self.application, + "additional_documents": self.supporting_documents["documents"], + } + + +class SupportingDocumentsAddView(F680FeatureRequiredMixin, FormView): + form_class = F680AttachSupportingDocument + template_name = "core/form.html" + + @expect_status( + HTTPStatus.CREATED, + "Error creating F680 document", + "Unexpected error creating F680 document", + ) + def post_f680_document(self, data): + return post_f680_document(self.request, data) + + def setup(self, request, *args, **kwargs): + super().setup(request, *args, **kwargs) + self.application, _ = self.get_f680_application(kwargs["pk"]) + + def get_success_url(self): + return reverse( + "f680:summary", + kwargs={ + "pk": self.application.id, + }, + ) + + def form_valid(self, form): + data = form.cleaned_data + file = data["file"] + description = data["description"] + payload = {**get_document_data(file), "description": description, "application": self.application.id} + # Here we post the document to a new F680 Specific endpoint + # This is stored on ApplicationDocumention + # This is required so we can do virus scans etc etc + self.post_f680_document(payload) + # After we enrich the JSON with + # {:supporting-documents: {documents:{}}} + # This could contain a dummy id for the entry and JSON blurb of the + # Form i.e in this case description and a reference to the id of the + # Physical document on ApplicationDocument + return super().form_valid(form) diff --git a/exporter/f680/services.py b/exporter/f680/services.py index be19ab1e7..8f14bc1ec 100644 --- a/exporter/f680/services.py +++ b/exporter/f680/services.py @@ -19,3 +19,13 @@ def patch_f680_application(request, application_id, json): def submit_f680_application(request, application_id): data = client.post(request, f"/exporter/f680/application/{application_id}/submit") return data.json(), data.status_code + + +def post_f680_document(request, json): + data = client.post(request, "/exporter/f680/application/{application_id}/document", json) + return data.json(), data.status_code + + +def get_f680_documents(request, json): + data = client.get(request, "/exporter/f680/application/{application_id}/document", json) + return data.json(), data.status_code diff --git a/exporter/f680/urls.py b/exporter/f680/urls.py index 50b6490af..65e78b699 100644 --- a/exporter/f680/urls.py +++ b/exporter/f680/urls.py @@ -2,7 +2,6 @@ from . import views - app_name = "f680" urlpatterns = [ @@ -24,4 +23,8 @@ "/user-information/", include("exporter.f680.application_sections.user_information.urls"), ), + path( + "/supporting-documents/", + include("exporter.f680.application_sections.supporting_documents.urls"), + ), ] diff --git a/exporter/templates/f680/supporting_documents/supporting-documents-documents.html b/exporter/templates/f680/supporting_documents/supporting-documents-documents.html new file mode 100644 index 000000000..4f952f711 --- /dev/null +++ b/exporter/templates/f680/supporting_documents/supporting-documents-documents.html @@ -0,0 +1,68 @@ +{% extends 'layouts/base.html' %} + +{% load additional_documents svg %} + +{% block back_link %} + Back +{% endblock %} + +{% block body %} +
+
+

Supporting Documents

+
+
+ + Add a document + + {% if additional_documents %} + + + + + + + + + + + {% for additional_document in additional_documents %} + + + + + + + {% endfor %} + +
NameDescriptionMessageAction
{{ additional_document.name }} + {{ additional_document.description|default_na }} + + {% if additional_document.safe == True %} + + {% lcs 'AdditionalDocuments.Documents.DOWNLOAD_DOCUMENT' %} + + {% elif additional_document.safe == False %} + {% lcs 'AdditionalDocuments.Documents.VIRUS' %} + {% else %} + {% lcs 'AdditionalDocuments.Documents.PROCESSING' %} + {% endif %} + + {% if editable and not additional_document|is_system_document %} + + Delete + + {% endif %} +
+ {% else %} +
+ +

+ Information + NO Docs +

+
+
+ {% endif %} + +{% endblock %}