Skip to content

Commit

Permalink
Merge pull request #2352 from uktrade/LTD-5889-f680s-exporter-general…
Browse files Browse the repository at this point in the history
…-application-details

[LTD-5889] F680s exporter general application details
  • Loading branch information
currycoder authored Feb 11, 2025
2 parents fd4ef7f + 544c2d6 commit e017500
Show file tree
Hide file tree
Showing 33 changed files with 981 additions and 369 deletions.
8 changes: 4 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 2.1

orbs:
browser-tools: circleci/[email protected]
browser-tools: circleci/[email protected] # /PS-IGNORE

parameters:
run_ui_tests:
Expand Down Expand Up @@ -131,7 +131,7 @@ commands:
- run:
name: Clone API
command: |
git clone [email protected]:uktrade/lite-api.git
git clone [email protected]:uktrade/lite-api.git # /PS-IGNORE
cd lite-api
git checkout $(python ../which_branch.py <<parameters.api_branch>>)
- run:
Expand Down Expand Up @@ -252,7 +252,7 @@ jobs:
environment:
<<: *common_env_vars
PIPENV_DOTENV_LOCATION: tests.exporter.env
PYTEST_ADDOPTS: unit_tests/exporter --capture=no --nomigrations
PYTEST_ADDOPTS: exporter unit_tests/exporter --capture=no --nomigrations
FILE_UPLOAD_HANDLERS: django.core.files.uploadhandler.MemoryFileUploadHandler,django.core.files.uploadhandler.TemporaryFileUploadHandler
steps:
- backend_unit_tests:
Expand All @@ -266,7 +266,7 @@ jobs:
environment:
<<: *common_env_vars
PIPENV_DOTENV_LOCATION: tests.exporter.env
PYTEST_ADDOPTS: unit_tests/core --capture=no --nomigrations
PYTEST_ADDOPTS: core unit_tests/core --capture=no --nomigrations
FILE_UPLOAD_HANDLERS: django.core.files.uploadhandler.MemoryFileUploadHandler,django.core.files.uploadhandler.TemporaryFileUploadHandler
steps:
- backend_unit_tests:
Expand Down
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ repos:
- id: detect-aws-credentials
args: ["--allow-missing-credentials"]
- repo: https://github.com/uktrade/pii-secret-check-hooks
rev: 0.0.0.36
# TODO: Switch back to a versioned release after this feature branch merges on the PII repo
rev: add-file-content-ignore-strings-option
hooks:
- id: pii_secret_filename
files: ""
Expand Down
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pylint-celery = "==0.3"
pylint-flask = "==0.6"
pylint-plugin-utils = "==0.7"
pytest-circleci-parallelized = "*"
freezegun = "*"

[packages]
beautifulsoup4 = "~=4.8.2"
Expand Down
702 changes: 367 additions & 335 deletions Pipfile.lock

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions core/wizard/payloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,16 @@ def build(self, form_dict):
if form:
always_merger.merge(payload, payload_func(form))
return payload


def get_cleaned_data(form):
return form.cleaned_data


def get_questions_data(form):
if not form.cleaned_data:
return {}
questions = {}
for field_name, field in form.declared_fields.items():
questions[field_name] = field.label
return questions
Empty file added core/wizard/tests/__init__.py
Empty file.
29 changes: 29 additions & 0 deletions core/wizard/tests/test_payloads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from unittest import mock

from core.wizard.payloads import get_questions_data, get_cleaned_data


class TestGetQuestionsData:

def test_get_questions_data_no_cleaned_data(self):
form = mock.Mock()
form.cleaned_data = None
assert get_questions_data(form) == {}

def test_get_questions_data_form_with_declared_fields(self):
form = mock.Mock()
form.cleaned_data.return_value = {"cleaned": "data"}
mock_field = mock.Mock()
mock_field.label = "Name"
form.declared_fields = {
"name": mock_field,
}
assert get_questions_data(form) == {"name": "Name"}


class TestGetCleanedData:

def test_get_cleaned_data(self):
form = mock.Mock()
form.cleaned_data = {"some": "value"}
assert get_cleaned_data(form) == {"some": "value"}
6 changes: 1 addition & 5 deletions exporter/applications/views/goods/common/payloads.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
from exporter.applications.views.goods.common import constants
from core.wizard.payloads import MergingPayloadBuilder


def get_cleaned_data(form):
return form.cleaned_data
from core.wizard.payloads import MergingPayloadBuilder, get_cleaned_data


def get_pv_grading_payload(form):
Expand Down
3 changes: 1 addition & 2 deletions exporter/applications/views/parties/payloads.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from core.wizard.payloads import MergingPayloadBuilder
from exporter.applications.views.goods.common.payloads import get_cleaned_data
from core.wizard.payloads import MergingPayloadBuilder, get_cleaned_data
from exporter.core.constants import (
SetPartyFormSteps,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from core.decorators import expect_status

from exporter.applications.views.goods.common.mixins import ApplicationMixin
from exporter.applications.views.goods.common.payloads import get_cleaned_data
from core.wizard.payloads import get_cleaned_data
from exporter.applications.services import put_application
from core.wizard.views import BaseSessionWizardView

Expand Down
2 changes: 1 addition & 1 deletion exporter/applications/views/security_approvals/payloads.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from core.wizard.payloads import MergingPayloadBuilder

from .constants import SecurityApprovalSteps
from exporter.applications.views.goods.common.payloads import get_cleaned_data
from core.wizard.payloads import get_cleaned_data


def get_f1686_data(form):
Expand Down
3 changes: 3 additions & 0 deletions exporter/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pylint: disable=unused-wildcard-import,wildcard-import
from unit_tests.conftest import *
from unit_tests.exporter.conftest import *
3 changes: 1 addition & 2 deletions exporter/core/organisation/payloads.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from exporter.applications.views.goods.common.payloads import get_cleaned_data
from core.wizard.payloads import MergingPayloadBuilder
from core.wizard.payloads import MergingPayloadBuilder, get_cleaned_data

from .constants import RegistrationSteps
from .forms import RegisterAddressDetailsUKIndividualForm, RegisterAddressDetailsUKCommercialForm
Expand Down
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class FormSteps:
APPLICATION_NAME = "APPLICATION_NAME"
EXCEPTIONAL_CIRCUMSTANCES = "EXCEPTIONAL_CIRCUMSTANCES"
EXCEPTIONAL_CIRCUMSTANCES_REASONS = "EXCEPTIONAL_CIRCUMSTANCES_REASONS"
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from datetime import datetime
from django import forms
from django.template.loader import render_to_string

from crispy_forms_gds.fields import DateInputField
from crispy_forms_gds.layout.content import HTML

from core.common.forms import BaseForm
from core.forms.utils import coerce_str_to_bool

from exporter.core.validators import (
FutureDateValidator,
RelativeDeltaDateValidator,
)


class ApplicationNameForm(BaseForm):
class Layout:
TITLE = "Name the application"
TITLE_AS_LABEL_FOR = "name"
SUBMIT_BUTTON_TEXT = "Continue"

name = forms.CharField(
label=Layout.TITLE,
help_text="Give the application a reference name so you can refer back to it when needed",
)

def get_layout_fields(self):
return ("name",)


class ExceptionalCircumstancesForm(BaseForm):
class Layout:
TITLE = "Do you have exceptional circumstances that mean you need F680 approval in less than 30 days?"
TITLE_AS_LABEL_FOR = "is_exceptional_circumstances"
SUBMIT_BUTTON_TEXT = "Continue"

is_exceptional_circumstances = forms.TypedChoiceField(
choices=(
(True, "Yes"),
(False, "No"),
),
label="Do you have exceptional circumstances that mean you need F680 approval in less than 30 days?",
widget=forms.RadioSelect,
coerce=coerce_str_to_bool,
)

def get_layout_fields(self):
return (
"is_exceptional_circumstances",
HTML.details(
"Help with exceptional circumstances",
render_to_string("f680/forms/help_exceptional_circumstances.html"),
),
)


class ExplainExceptionalCircumstancesForm(BaseForm):
class Layout:
TITLE = "Explain your exceptional circumstances"
SUBMIT_BUTTON_TEXT = "Save and continue"

exceptional_circumstances_date = DateInputField(
label="When do you need your F680 approval?",
validators=[
FutureDateValidator("Date must be in the future"),
RelativeDeltaDateValidator("Date must be within 30 days", days=30),
],
)
exceptional_circumstances_reason = forms.CharField(
label="Why do you need approval in less than 30 days?",
widget=forms.Textarea(attrs={"rows": "5"}),
)

def __init__(self, *args, **kwargs):
# We have to do some coercion from string to datetime object here due to JSON serialization
if (
"initial" in kwargs
and "exceptional_circumstances_date" in kwargs["initial"]
and isinstance(kwargs["initial"]["exceptional_circumstances_date"], str)
):
kwargs["initial"]["exceptional_circumstances_date"] = datetime.fromisoformat(
kwargs["initial"]["exceptional_circumstances_date"]
)
super().__init__(*args, **kwargs)

def clean(self):
# We have to do some coercion from datetime object to string here due to JSON serialization
cleaned_data = super().clean()
if "exceptional_circumstances_date" in cleaned_data:
cleaned_data["exceptional_circumstances_date"] = cleaned_data["exceptional_circumstances_date"].isoformat()
return cleaned_data

def get_layout_fields(self):
return (
"exceptional_circumstances_date",
"exceptional_circumstances_reason",
)
Empty file.
Loading

0 comments on commit e017500

Please sign in to comment.