class Form18EFilingSubmitView(generics.GenericAPIView):
    permission_classes = (permissions.IsAuthenticated, )

    def __init__(self):
        self.efiling_parsing = EFilingParsing()
        self.efiling_submission = EFilingSubmission(EFilingPackaging())

    # """ This inserts our generated file, iterates over files and converts to PDF if necessary. """

    def get_change_of_address_for_user(self, change_of_address_id, uid):
        try:
            change_of_address_query = ChangeOfAddress.objects.get(
                id=change_of_address_id, user_id=uid)
            return change_of_address_query
        except (ChangeOfAddress.DoesNotExist):
            logger.debug(no_record_found)
            return

    def _get_pdf_content(self, change_of_address, document_type):
        outgoing_documents = []
        #Modify If more than one form type exist in the future

        current_document_type = "FORM"
        try:
            prepared_pdf = FormPdf.objects.get(
                change_of_address_id=change_of_address.id,
                pdf_type=f"{current_document_type}")
        except FormPdf.DoesNotExist:
            raise NotFound(
                detail=
                f"Missing document type {current_document_type} from database."
            )
        pdf_content = settings.ENCRYPTOR.decrypt(prepared_pdf.key_id,
                                                 prepared_pdf.data)
        document_json = json.loads(
            settings.ENCRYPTOR.decrypt(prepared_pdf.key_id,
                                       prepared_pdf.json_data).decode("utf-8"))
        document_json.update({"applicationId": change_of_address.id})

        outgoing_documents.append({
            "type": f"{document_type}",
            "name": "form18.pdf",
            "file_data": pdf_content,
            "data": document_json,
            "md5": hashlib.md5(pdf_content).hexdigest(),
        })
        return outgoing_documents

    def put(self, request, change_of_address_id):
        uid = request.user.id
        body = request.data

        change_of_address = self.get_change_of_address_for_user(
            change_of_address_id, uid)
        if not change_of_address:
            return HttpResponseNotFound("no record found")

        if not change_of_address.submission_id or not change_of_address.transaction_id:
            return HttpResponseNotFound("no record found")

        change_of_address.package_number = body.get("packageNumber")
        change_of_address.package_url = body.get("packageUrl")
        change_of_address.status = "Submitted"
        change_of_address.last_filed = timezone.now()
        change_of_address.save()
        return HttpResponse(status=204)

    def post(self, request, change_of_address_id):

        if 'document_type' in request.data:
            document_type = request.data['document_type']
        else:
            document_type = "CNAC"  # type Form18 for Efiling

        uid = request.user.id

        change_of_address = self.get_change_of_address_for_user(
            change_of_address_id, uid)
        if not change_of_address:
            return HttpResponseNotFound("no record found")

        if change_of_address.package_number or change_of_address.package_url:
            return JsonMessageResponse(
                "This application has already been submitted.", status=500)

        outgoing_documents = self._get_pdf_content(change_of_address,
                                                   document_type)
        data_for_efiling = self.efiling_parsing.convert_data_for_efiling(
            request, change_of_address, outgoing_documents, document_type)

        # EFiling upload document.
        transaction_id = str(uuid.uuid4())
        change_of_address.transaction_id = transaction_id
        change_of_address.save()

        outgoing_files = convert_document_to_multi_part(outgoing_documents)
        del outgoing_documents
        upload_result = self.efiling_submission.upload_documents(
            request.user.universal_id, transaction_id, outgoing_files)

        if upload_result is None or "submissionId" not in upload_result:
            message = (upload_result["message"]
                       if upload_result and "message" in upload_result else
                       "Document Upload Failed.")
            return JsonMessageResponse(message, status=500)

        # EFiling package submission.
        submission_id = upload_result["submissionId"]
        redirect_url, message = self.efiling_submission.generate_efiling_url(
            request.user.universal_id, transaction_id, submission_id,
            data_for_efiling)

        if redirect_url is not None:
            change_of_address.submission_id = submission_id
            change_of_address.last_filed = timezone.now()
            change_of_address.save()

            return JsonResponse({
                "redirectUrl": redirect_url,
                "message": message
            })

        return JsonMessageResponse(message, status=500)
 def __init__(self):
     self.efiling_parsing = EFilingParsing()
     self.efiling_submission = EFilingSubmission(EFilingPackaging())
Example #3
0
 def __init__(self):
     self.efiling_parsing = EFilingParsing()
     self.efiling_submission = EFilingSubmission(EFilingPackaging())
     self.file_byte_size_limit = 1024 * 1024 * 10  # 10 MBytes
     self.allowed_extensions = ["pdf", "jpg", "jpeg", "gif", "png"]
Example #4
0
class EFilingSubmitView(generics.GenericAPIView):
    permission_classes = (permissions.IsAuthenticated, )

    def __init__(self):
        self.efiling_parsing = EFilingParsing()
        self.efiling_submission = EFilingSubmission(EFilingPackaging())
        self.file_byte_size_limit = 1024 * 1024 * 10  # 10 MBytes
        self.allowed_extensions = ["pdf", "jpg", "jpeg", "gif", "png"]

    def _file_size_too_large(self, size):
        return size > self.file_byte_size_limit

    def _invalid_file_extension(self, file):
        extension = file.name.split(".")[-1]
        return extension.lower() not in self.allowed_extensions

    def _get_validation_errors(self, request_files):
        for file in request_files:
            if file.size == 0:
                return JsonMessageResponse("One of the files was empty.",
                                           status=400)
            if self._file_size_too_large(file.size):
                return JsonMessageResponse("Filesize limit exceeded: 10 MB.",
                                           status=400)
            if self._invalid_file_extension(file):
                return JsonMessageResponse("Wrong file format.", status=400)
        return None

    """ This inserts our generated file, iterates over files and converts to PDF if necessary.
        Also converts MemoryUploadedFiles into a multi-form payload to be sent out as files. """

    def _convert_incoming_files(self, incoming_files, po_pdf_content,
                                document_types):
        outgoing_files = [("files", ("fpo_generated.pdf", po_pdf_content,
                                     "application/pdf"))]
        document_types.insert(0, "POR")

        # Convert files, if they aren't PDF.
        for incoming_file in incoming_files:
            outgoing_files.append((
                "files",
                (
                    incoming_file.name if incoming_file.name.endswith(".pdf")
                    else f"{incoming_file.name.rsplit('.', 1)[0] + '.pdf'}",
                    incoming_file.read()
                    if incoming_file.name.endswith(".pdf") else image_to_pdf({
                        "images": [{
                            "base64":
                            base64.b64encode(
                                incoming_file.read()).decode("utf-8"),
                            "type":
                            incoming_file.name.lower().split(".")[-1],
                        }]
                    }),
                    "application/pdf",
                ),
            ))
        return document_types, outgoing_files

    def _get_protection_order_content(self, prepared_pdf_id, application_id):
        prepared_pdf = PreparedPdf.objects.get(id=prepared_pdf_id)
        po_pdf_content = settings.ENCRYPTOR.decrypt(prepared_pdf.key_id,
                                                    prepared_pdf.data)
        po_json = json.loads(
            settings.ENCRYPTOR.decrypt(prepared_pdf.key_id,
                                       prepared_pdf.json_data).decode("utf-8"))
        po_json.update({"applicationId": application_id})
        return (po_pdf_content, po_json)

    def put(self, request, application_id):
        body = request.data
        application = get_application_for_user(application_id, request.user.id)
        efiling_submission = EFilingSubmissionModel.objects.filter(
            id=application.last_efiling_submission_id).first()
        if not efiling_submission:
            return HttpResponse(status=404)
        efiling_submission.package_number = body.get("packageNumber")
        efiling_submission.package_url = body.get("packageUrl")
        efiling_submission.last_updated = timezone.now()
        efiling_submission.save()
        application.last_filed = timezone.now()
        application.save()
        return HttpResponse(status=204)

    def post(self, request, application_id):
        document_types = request.POST.getlist("documentTypes")
        request_files = request.FILES.getlist("files")

        # Validations.
        validations_errors = self._get_validation_errors(request_files)
        if validations_errors:
            return validations_errors

        application = get_application_for_user(application_id, request.user.id)
        if application.prepared_pdf_id is None:
            return JsonMessageResponse("PO PDF is not generated.", status=400)

        # Data conversion.
        po_pdf_content, po_json = self._get_protection_order_content(
            application.prepared_pdf_id, application_id)
        document_types, outgoing_files = self._convert_incoming_files(
            request_files, po_pdf_content, document_types)
        data = self.efiling_parsing.convert_data_for_efiling(
            request, application, po_json, outgoing_files, document_types)

        # EFiling upload document.
        transaction_id = str(uuid.uuid4())
        efiling_submission = EFilingSubmissionModel(
            transaction_id=transaction_id,
            application_id=application.id,
        )
        efiling_submission.save()
        upload_result = self.efiling_submission.upload_documents(
            request.user.universal_id, transaction_id, outgoing_files)

        if upload_result is None or "submissionId" not in upload_result:
            message = (upload_result["message"]
                       if upload_result and "message" in upload_result else
                       "Document Upload Failed.")
            return JsonMessageResponse(message, status=500)

        # EFiling package submission.
        submission_id = upload_result["submissionId"]
        redirect_url, message = self.efiling_submission.generate_efiling_url(
            request.user.universal_id, transaction_id, submission_id, data)

        if redirect_url is not None:
            efiling_submission.submission_id = submission_id
            efiling_submission.last_updated = timezone.now()
            efiling_submission.save()

            application.last_efiling_submission_id = efiling_submission.id
            application.save()
            return JsonResponse({
                "redirectUrl": redirect_url,
                "message": message
            })

        return JsonMessageResponse(message, status=500)
Example #5
0
class EFilingSubmitView(generics.GenericAPIView):
    permission_classes = (permissions.IsAuthenticated,)

    def __init__(self):
        self.efiling_parsing = EFilingParsing()
        self.efiling_submission = EFilingSubmission(EFilingPackaging())
        self.file_byte_size_limit = 1024 * 1024 * 10  # 10 MBytes
        self.allowed_extensions = ["pdf", "jpg", "jpeg", "gif", "png"]

    def _file_size_too_large(self, size):
        return size > self.file_byte_size_limit

    def _invalid_file_extension(self, file):
        extension = file.name.split(".")[-1]
        return extension.lower() not in self.allowed_extensions

    def _get_validation_errors(self, request_files, documents):
        
        total_file_size = 0
        
        if not is_valid_json(documents):
            return JsonMessageResponse("Invalid json data for documents.", status=400)
        if len(request_files) > 30:
            return JsonMessageResponse("Too many files.", status=400)

        for file in request_files:
            total_file_size = total_file_size + file.size
            if file.size == 0:
                return JsonMessageResponse("One of the files was empty.", status=400)
            if self._file_size_too_large(file.size):
                return JsonMessageResponse(
                    "Filesize limit exceeded: 10 MB.", status=400
                )
            if self._invalid_file_extension(file):
                return JsonMessageResponse("Wrong file format.", status=400)
        
        if self._file_size_too_large(total_file_size):
            return JsonMessageResponse(
                "The total Files size limit exceeded: 10 MB.", status=400
            )

        return None

    def _unique_file_names(self, request_files):
        file_names =  [file.name.split('.')[0] for file in request_files]
        dup = dict(Counter(file_names))
        l_uniq = unique(file_names)
        unique_names = [key if i == 0 else key + str(i+1) for key in l_uniq for i in range(dup[key])]
        for i, unique_name in enumerate(unique_names):
            request_files[i].name = f"{unique_name}.{request_files[i].name.split('.')[1]}"
        return request_files

    """ This inserts our generated file, iterates over files and converts to PDF if necessary. """

    def _get_pdf_content(self, application, application_steps):
        outgoing_documents = []
        for existing_orders in application_steps[0]["result"]["existingOrders"]:
            document_type = existing_orders["type"]
            try:
                prepared_pdf = PreparedPdf.objects.get(
                    application_id=application.id, pdf_type=f"{document_type}"
                )
            except PreparedPdf.DoesNotExist:
                raise NotFound(
                    detail=f"Missing document type {document_type} from database."
                )
            pdf_content = settings.ENCRYPTOR.decrypt(
                prepared_pdf.key_id, prepared_pdf.data
            )
            document_json = json.loads(
                settings.ENCRYPTOR.decrypt(
                    prepared_pdf.key_id, prepared_pdf.json_data
                ).decode("utf-8")
            )
            document_json.update({"applicationId": application.id})
            outgoing_documents.append(
                {
                    "type": f"{document_type}",
                    "name": f"{document_type}_generated.pdf",
                    "file_data": pdf_content,
                    "data": document_json,
                    "md5": hashlib.md5(pdf_content).hexdigest(),
                }
            )
        return outgoing_documents

    def _merge_sch1_with_form15(self, outgoing_documents, pdf_files, image_files, rotations):
        output = PdfFileWriter()
        non_AXP_doc =  [x for x in outgoing_documents if x["type"]!="AXP"]
        AXP_doc = next(x for x in outgoing_documents if x["type"]=="AXP")
        
        output = self._add_pdf_to_output(output, AXP_doc["file_data"])

        if len(image_files) > 0:
            rotations = rotations
            imagedata = rotate_images_and_convert_pdf(image_files, rotations)
            output = self._add_pdf_to_output(output, imagedata)

        for file in pdf_files:
            data = file.read()
            output = self._add_pdf_to_output(output, data)       
        
        in_memory = BytesIO()
        output.write(in_memory)
        in_memory.seek(0)
        pdf_content = in_memory.read()

        non_AXP_doc.append(
            {
                "type": AXP_doc["type"],
                "name": AXP_doc["name"],
                "file_data": pdf_content,
                "data": AXP_doc["data"],
                "md5": hashlib.md5( pdf_content).hexdigest(),
            }
        )

        return non_AXP_doc
       
    def _add_pdf_to_output(self, output, data_bytes):
        pdf_bytes = BytesIO(data_bytes)
        read_pdf = PdfFileReader(pdf_bytes)
        for pgno in range(0, read_pdf.getNumPages()):            
            output.addPage(read_pdf.getPage(pgno))
        return output

    def _process_incoming_files_and_documents(
        self, application, application_steps, incoming_documents, incoming_files
    ):
        outgoing_documents = self._get_pdf_content(application, application_steps)
        for incoming_document in incoming_documents:
            if "files" not in incoming_document:
                continue
            
            file_indexes = incoming_document["files"]
            files = [incoming_files[index] for index in file_indexes]

            # 1 PDF and 2 JPG for example, we need to split into 2 PDFs.
            pdf_files = [x for x in files if x.name.endswith(".pdf")]
            image_files = [x for x in files if not x.name.endswith(".pdf")]

            if ("type" in incoming_document and incoming_document["type"] == "Merge With Form15"):                
                outgoing_documents = self._merge_sch1_with_form15( outgoing_documents, pdf_files, image_files, incoming_document["rotations"] )
                continue

            
            for file in pdf_files:
                data = file.read()
                file_name = file.name
                outgoing_documents.append(
                    {
                        "type": incoming_document["type"],
                        "name": file_name,
                        "file_data": data,
                        "data": "",
                        "md5": hashlib.md5(data).hexdigest(),
                    }
                )
            if len(image_files) > 0:
                rotations = incoming_document["rotations"]
                data = rotate_images_and_convert_pdf(image_files, rotations)
                file_name = f"{image_files[0].name.split('.')[0]}.pdf"
                outgoing_documents.append(
                    {
                        "type": incoming_document["type"],
                        "name": file_name,
                        "file_data": data,
                        "data": "",
                        "md5": hashlib.md5(data).hexdigest(),
                    }
                )
        return outgoing_documents

    def put(self, request, application_id):
        body = request.data
        application = get_application_for_user(application_id, request.user.id)
        efiling_submission = EFilingSubmissionModel.objects.filter(
            id=application.last_efiling_submission_id
        ).first()
        if not efiling_submission:
            return HttpResponse(status=404)
        efiling_submission.package_number = body.get("packageNumber")
        efiling_submission.package_url = body.get("packageUrl")
        efiling_submission.last_updated = timezone.now()
        efiling_submission.save()
        application.last_filed = timezone.now()
        application.save()
        return HttpResponse(status=204)

    def post(self, request, application_id):
        documents_string = request.POST.get("documents")
        request_files = request.FILES.getlist("files")

        # Validations.
        validations_errors = self._get_validation_errors(
            request_files, documents_string
        )
        if validations_errors:
            return validations_errors

        # Unique names.
        request_files = self._unique_file_names(request_files)

        application = get_application_for_user(application_id, request.user.id)
        application_steps = json.loads(
            settings.ENCRYPTOR.decrypt(application.key_id, application.steps).decode(
                "utf-8"
            )
        )

        # Data conversion.
        incoming_documents = json.loads(documents_string)

        outgoing_documents = self._process_incoming_files_and_documents(
            application, application_steps, incoming_documents, request_files
        )
        del request_files

        data = self.efiling_parsing.convert_data_for_efiling(
            request, application, application_steps, outgoing_documents
        )

        # EFiling upload document.
        transaction_id = str(uuid.uuid4())
        efiling_submission = EFilingSubmissionModel(
            transaction_id=transaction_id,
            application_id=application.id,
        )
        efiling_submission.save()
        outgoing_files = convert_document_to_multi_part(outgoing_documents)
        del outgoing_documents
        upload_result = self.efiling_submission.upload_documents(
            request.user.universal_id, transaction_id, outgoing_files
        )

        if upload_result is None or "submissionId" not in upload_result:
            message = (
                upload_result["message"]
                if upload_result and "message" in upload_result
                else "Document Upload Failed."
            )
            return JsonMessageResponse(message, status=500)

        # EFiling package submission.
        submission_id = upload_result["submissionId"]
        redirect_url, message = self.efiling_submission.generate_efiling_url(
            request.user.universal_id, transaction_id, submission_id, data
        )

        if redirect_url is not None:
            efiling_submission.submission_id = submission_id
            efiling_submission.last_updated = timezone.now()
            efiling_submission.save()

            application.last_efiling_submission_id = efiling_submission.id
            application.save()
            return JsonResponse({"redirectUrl": redirect_url, "message": message})

        return JsonMessageResponse(message, status=500)
class Form5EFilingSubmitView(generics.GenericAPIView):
    permission_classes = (permissions.IsAuthenticated,)

    def __init__(self):
        self.efiling_parsing = EFilingParsing()
        self.efiling_submission = EFilingSubmission(EFilingPackaging())

    # """ This inserts our generated file, iterates over files and converts to PDF if necessary. """

    def get_notice_for_user(self, notice_id, uid):
        try:
            notice_query = NoticeOfHearing.objects.get(id=notice_id, user_id=uid)
            return notice_query
        except (NoticeOfHearing.DoesNotExist):
            logger.debug(no_record_found)
            return


    def _get_pdf_content(self, notice, document_type):
        outgoing_documents = [] 
        #Modify If more than one form type exist in the future       
        
        current_document_type = "NHA"
        try:                      
            prepared_pdf = FormPdf.objects.get(
                notice_of_hearing_id=notice.id, pdf_type=f"{current_document_type}"
            )
        except FormPdf.DoesNotExist:
            raise NotFound(
                detail=f"Missing document type {current_document_type} from database."
            )
        pdf_content = settings.ENCRYPTOR.decrypt(
            prepared_pdf.key_id, prepared_pdf.data
        )
        document_json = json.loads(
            settings.ENCRYPTOR.decrypt(
                prepared_pdf.key_id, prepared_pdf.json_data
            ).decode("utf-8")
        )
        document_json.update({"applicationId": notice.id})

        
        outgoing_documents.append(
            {
                "type": f"{document_type}",
                "name": "form5.pdf",
                "file_data": pdf_content,
                "data": document_json,
                "md5": hashlib.md5(pdf_content).hexdigest(),
            }
        )
        return outgoing_documents


    def put(self, request, notice_id):
        uid = request.user.id
        body = request.data

        notice = self.get_notice_for_user(notice_id, uid)
        if not notice:        
            return HttpResponseNotFound("no record found")

        if not notice.submission_id or  not notice.transaction_id:
            return HttpResponseNotFound("no record found")

        notice.package_number = body.get("packageNumber")
        notice.package_url = body.get("packageUrl")
        notice.status="Submitted"
        notice.last_filed = timezone.now()
        notice.save()
        return HttpResponse(status=204)


    def post(self, request, notice_id):
        
        document_type = "NHA" # type Form5 for Efiling
        uid = request.user.id

        documents_string = request.POST.get("documents")
        attachment_files = request.FILES.getlist("files")

        notice = self.get_notice_for_user(notice_id, uid)        
        if not notice:
            return HttpResponseNotFound("no record found")

        if notice.package_number or notice.package_url: 
            return JsonMessageResponse("This application has already been submitted.", status=500)


        # Validations.
        validations_errors = _get_validation_errors(
            attachment_files, documents_string
        )
        if validations_errors:
            return validations_errors

        # Unique names.
        attachment_files = _unique_file_names(attachment_files)

        # Data conversion.
        incoming_documents = json.loads(documents_string)

        outgoing_documents = self._get_pdf_content(notice, document_type)               
        
        outgoing_documents = _process_incoming_files_and_documents(
            incoming_documents, attachment_files, outgoing_documents
        )
        del attachment_files 



        data_for_efiling = self.efiling_parsing.convert_data_for_efiling(
            request, notice, outgoing_documents, document_type
        )
        
        # EFiling upload document.
        transaction_id = str(uuid.uuid4())
        notice.transaction_id = transaction_id
        notice.save()

        outgoing_files = convert_document_to_multi_part(outgoing_documents)
        del outgoing_documents
        upload_result = self.efiling_submission.upload_documents(
            request.user.universal_id, transaction_id, outgoing_files
        )
       
        if upload_result is None or "submissionId" not in upload_result:
            message = (
                upload_result["message"]
                if upload_result and "message" in upload_result
                else "Document Upload Failed."
            )
            return JsonMessageResponse(message, status=500)

    
        # EFiling package submission.
        submission_id = upload_result["submissionId"]
        redirect_url, message = self.efiling_submission.generate_efiling_url(
            request.user.universal_id, transaction_id, submission_id, data_for_efiling
        )

        if redirect_url is not None:
            notice.submission_id = submission_id 
            notice.last_filed = timezone.now()            
            notice.save()

            return JsonResponse({"redirectUrl": redirect_url, "message": message})

        return JsonMessageResponse(message, status=500)
class EFilingSubmitView(generics.GenericAPIView):
    permission_classes = (permissions.IsAuthenticated, )

    def __init__(self):
        self.efiling_parsing = EFilingParsing()
        self.efiling_submission = EFilingSubmission(EFilingPackaging())
        self.file_byte_size_limit = 1024 * 1024 * 10  # 10 MBytes
        self.allowed_extensions = ["pdf", "jpg", "jpeg", "gif", "png"]

    def _file_size_too_large(self, size):
        return size > self.file_byte_size_limit

    def _invalid_file_extension(self, file):
        extension = file.name.split(".")[-1]
        return extension.lower() not in self.allowed_extensions

    def _get_validation_errors(self, request_files, documents):
        # TODO: check group of images isn't over 10MB
        if not is_valid_json(documents):
            return JsonMessageResponse("Invalid json data for documents.",
                                       status=400)
        if len(request_files) > 30:
            return JsonMessageResponse("Too many files.", status=400)
        for file in request_files:
            if file.size == 0:
                return JsonMessageResponse("One of the files was empty.",
                                           status=400)
            if self._file_size_too_large(file.size):
                return JsonMessageResponse("Filesize limit exceeded: 10 MB.",
                                           status=400)
            if self._invalid_file_extension(file):
                return JsonMessageResponse("Wrong file format.", status=400)
        return None

    """ This inserts our generated file, iterates over files and converts to PDF if necessary. """

    def _process_incoming_files_and_documents(self, po_pdf_content, po_json,
                                              incoming_documents,
                                              incoming_files):
        outgoing_documents = [{
            "type": "POR",
            "name": "fpo_generated.pdf",
            "file_data": po_pdf_content,
            "data": po_json,
            "md5": hashlib.md5(po_pdf_content).hexdigest(),
        }]
        for incoming_document in incoming_documents:
            file_indexes = incoming_document["files"]
            files = [incoming_files[index] for index in file_indexes]
            if files[0].name.endswith(".pdf"):
                data = files[0].read()
                file_name = files[0].name
            else:
                rotations = incoming_document["rotations"]
                data = rotate_images_and_convert_pdf(files, rotations)
                file_name = f"{files[0].name.split('.')[0]}.pdf"
            outgoing_documents.append({
                "type": incoming_document["type"],
                "name": file_name,
                "file_data": data,
                "data": "",
                "md5": hashlib.md5(data).hexdigest(),
            })
        return outgoing_documents

    def put(self, request, application_id):
        body = request.data
        application = get_application_for_user(application_id, request.user.id)
        efiling_submission = EFilingSubmissionModel.objects.filter(
            id=application.last_efiling_submission_id).first()
        if not efiling_submission:
            return HttpResponse(status=404)
        efiling_submission.package_number = body.get("packageNumber")
        efiling_submission.package_url = body.get("packageUrl")
        efiling_submission.last_updated = timezone.now()
        efiling_submission.save()
        application.last_filed = timezone.now()
        application.save()
        return HttpResponse(status=204)

    def post(self, request, application_id):
        documents_string = request.POST.get("documents")
        request_files = request.FILES.getlist("files")

        # Validations.
        validations_errors = self._get_validation_errors(
            request_files, documents_string)
        if validations_errors:
            return validations_errors

        application = get_application_for_user(application_id, request.user.id)
        if application.prepared_pdf_id is None:
            return JsonMessageResponse("PO PDF is not generated.", status=400)

        # Data conversion.
        incoming_documents = json.loads(documents_string)
        po_pdf_content, po_json = get_protection_order_content(application)
        outgoing_documents = self._process_incoming_files_and_documents(
            po_pdf_content, po_json, incoming_documents, request_files)
        del request_files

        data = self.efiling_parsing.convert_data_for_efiling(
            request, application, outgoing_documents)

        # EFiling upload document.
        transaction_id = str(uuid.uuid4())
        efiling_submission = EFilingSubmissionModel(
            transaction_id=transaction_id,
            application_id=application.id,
        )
        efiling_submission.save()
        outgoing_files = convert_document_to_multi_part(outgoing_documents)
        del outgoing_documents
        upload_result = self.efiling_submission.upload_documents(
            request.user.universal_id, transaction_id, outgoing_files)

        if upload_result is None or "submissionId" not in upload_result:
            message = (upload_result["message"]
                       if upload_result and "message" in upload_result else
                       "Document Upload Failed.")
            return JsonMessageResponse(message, status=500)

        # EFiling package submission.
        submission_id = upload_result["submissionId"]
        redirect_url, message = self.efiling_submission.generate_efiling_url(
            request.user.universal_id, transaction_id, submission_id, data)

        if redirect_url is not None:
            efiling_submission.submission_id = submission_id
            efiling_submission.last_updated = timezone.now()
            efiling_submission.save()

            application.last_efiling_submission_id = efiling_submission.id
            application.save()
            return JsonResponse({
                "redirectUrl": redirect_url,
                "message": message
            })

        return JsonMessageResponse(message, status=500)