Skip to content

Commit

Permalink
DST-514/licensing grounds views (#18)
Browse files Browse the repository at this point in the history
* Data model

* Updating models

* Migrations and tidying up user flows

* Fix third party flows

* Adding business employing individual view

* Types of service

* Services views

* remove unneeded file

* Squash migrations

* Service views update

* service views updates

* case switch

* remove migration

* Choices field

* remove unnecessary repeated code

* recipients initial views

* updating field sizes

* Required fields on recipient models

* Remove sanctions regimes unneeded js

* Remove unneeded JS for sanctions regimes

* Review comments

* Licensing grounds views

* squash migrations

* Licesngin grounds with legal advisory

* purpose of licesning

* Edit comments

* Add variable for clarity

---------

Co-authored-by: Morgan Rees <[email protected]>
  • Loading branch information
morganmaerees and Morgan Rees authored Jul 18, 2024
1 parent 84eb14e commit ceca0db
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 7 deletions.
28 changes: 28 additions & 0 deletions django_app/apply_for_a_licence/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,31 @@ class ProfessionalOrBusinessServicesChoices(models.TextChoices):
it_consultancy_or_design = "it_consultancy_or_design", "IT consultancy or design"
legal_advisory = "legal_advisory", "Legal advisory"
public_relations = "public_relations", "Public relations"


class LicensingGroundsChoices(models.TextChoices):
civil_society = (
"civil_society",
"Civil society activities that directly promote democracy, human rights or the rule of law in Russia",
)
energy = "energy", "Services necessary for ensuring critical energy supply to any country"
divest = (
"divest",
"Services necessary for non - Russian persons to divest from Russia, or to wind down business operations in Russia",
)
humanitarian = "humanitarian", "The delivery of humanitarian assistance activity"
parent_or_subsidiary_company = (
"parent_or_subsidiary_company",
"Services to a person connected with Russia by a UK parent company or UK subsidiary of that parent company",
)
medical_and_pharmaceutical = (
"medical_and_pharmaceutical",
"Medical and pharmaceutical purposes for the benefit of the civilian population",
)
safety = (
"safety",
"Services required to enable activities necessary for the urgent prevention or mitigation of an "
"event likely to have a serious and significant impact on human health or safety, including the "
"safety of existing infrastructure, or the environment",
)
food = "food", "Services in connection with the production or distribution of food for the benefit of the civilian population"
96 changes: 96 additions & 0 deletions django_app/apply_for_a_licence/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
Address,
Applicant,
ApplicationOrganisation,
ApplicationServices,
ApplicationType,
BaseApplication,
ExistingLicences,
Expand Down Expand Up @@ -861,3 +862,98 @@ def __init__(self, *args: object, **kwargs: object) -> None:
super().__init__(*args, **kwargs)
self.fields["relationship"].required = True
self.fields["relationship"].widget.attrs = {"rows": 5}


class LicensingGroundsForm(BaseForm):
form_h1_header = "Which of these licensing grounds describes your purpose for providing the sanctioned services?"
licensing_grounds = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
choices=choices.LicensingGroundsChoices.choices,
required=True,
label="Select all that apply",
error_messages={
"required": "Select the licensing grounds",
"invalid": "Select the licensing grounds or select I do not know",
},
)

class Media:
js = ["apply_for_a_licence/javascript/licensing_grounds.js"]

def __init__(self, *args: object, **kwargs: object) -> None:
self.legal_advisory = kwargs.pop("legal_advisory", False)
super().__init__(*args, **kwargs)
checkbox_choices = self.fields["licensing_grounds"].choices
# Create the 'or' divider between the last choice and I do not know
last_checkbox_value = checkbox_choices[-1][0]
last_checkbox_label = checkbox_choices[-1][1]
checkbox_choices[-1] = Choice(
value=last_checkbox_value,
label=last_checkbox_label,
divider="or",
)
checkbox_choices.append(Choice("Unknown grounds", "I do not know"))
checkbox_choices.append(Choice("None of these", "None of these"))
self.fields["licensing_grounds"].choices = checkbox_choices
self.helper.layout = Layout(
Fieldset(
get_field_with_label_id("licensing_grounds", field_method=Field.checkboxes, label_id="checkbox"),
aria_describedby="checkbox",
)
)

if self.legal_advisory:
self.form_h1_header = (
"Which of these licensing grounds describes your purpose for providing the "
"(non-legal advisory) sanctioned services?"
)

else:
if professional_or_business_service := self.request.session.get("ProfessionalOrBusinessServicesView", False):
if professional_or_business_service.get("professional_or_business_service") == "legal_advisory":
self.form_h1_header = (
"Which of the licensing grounds describes the purpose of the relevant activity for which "
"the legal advice is being given?"
)
self.fields["licensing_grounds"].label = (
"If your client is a non-UK national or business and is also outside the UK "
"then UK sanctions do not apply to them. Instead you should select the licensing "
"grounds that would apply if UK sanctions did apply to them."
)
self.fields["licensing_grounds"].help_text = "Select all that apply"

def clean(self):
cleaned_data = super().clean()
if licensing_grounds := cleaned_data.get("licensing_grounds"):
if ("Unknown grounds" in licensing_grounds or "None of these" in licensing_grounds) and len(licensing_grounds) >= 2:
# the user has selected "I do not know" or 'None of these' and other grounds, this is an issue.
# note that the user can select both "I do not know" and "None of these"
self.add_error(
"licensing_grounds",
forms.ValidationError(code="invalid", message=self.fields["licensing_grounds"].error_messages["invalid"]),
)
return cleaned_data


class PurposeOfProvisionForm(BaseModelForm):
class Meta:
model = ApplicationServices
fields = ["purpose_of_provision"]
labels = {
"purpose_of_provision": "What is your purpose for providing these services?",
}
help_texts = {
"purpose_of_provision": "Tell us how your reasons for providing these services are consistent with "
"the purposes of the sanctions and why providing them is both necessary and justified. If you've "
"selected any licensing considerations (licensing grounds), as laid out in the statutory guidance, "
"explain how your purpose aligns with those grounds"
}
error_messages = {
"purpose_of_provision": {
"required": "Select the purpose for providing these services",
}
}

def __init__(self, *args: object, **kwargs: object) -> None:
super().__init__(*args, **kwargs)
self.fields["purpose_of_provision"].required = True
2 changes: 2 additions & 0 deletions django_app/apply_for_a_licence/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django_countries.fields import CountryField

from . import choices
from .choices import LicensingGroundsChoices


class Address(BaseModelID):
Expand Down Expand Up @@ -238,6 +239,7 @@ class Meta:

class Ground(BaseModelID):
# ! This table is required as it is for data pipelines - speak with data architect before modifying
licensing_grounds = models.CharField(choices=LicensingGroundsChoices.choices)
label = models.CharField()
start_date = models.DateField()
end_date = models.DateField()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
document.addEventListener("DOMContentLoaded", function (event) {
$(document).on('change', 'input[value="Unknown grounds"], input[value="None of these"]', function(){
if ($(this).is(':checked')) {
// clear the other inputs
$('input[name$="licensing_grounds"]').not($(this)).prop('checked', false);
}
})

$('.govuk-checkboxes__divider').prevAll().find('input[name$="licensing_grounds"]').on('change', function () {
if ($(this).is(':checked')) {
// clear the unknown grounds input or the none of these input
$('input[name$="licensing_grounds"][value="Unknown grounds"]').prop('checked', false);
$('input[name$="licensing_grounds"][value="None of these"]').prop('checked', false);
}
});

});
7 changes: 7 additions & 0 deletions django_app/apply_for_a_licence/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,12 @@
views.RelationshipProviderRecipientView.as_view(),
name="relationship_provider_recipient",
),
path("licensing_grounds", views.LicensingGroundsView.as_view(), name="licensing_grounds"),
path(
"licensing_grounds_legal_advisory",
views.LicensingGroundsLegalAdvisoryView.as_view(),
name="licensing_grounds_legal_advisory",
),
path("purpose_of_provision", views.PurposeOfProvisionView.as_view(), name="purpose_of_provision"),
path("complete", views.CompleteView.as_view(), name="complete"),
]
34 changes: 27 additions & 7 deletions django_app/apply_for_a_licence/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ def get_success_url(self):
class PreviousLicenceView(BaseFormView):
form_class = forms.ExistingLicencesForm

def get_form_kwargs(self) -> dict[str, Any]:
kwargs = super().get_form_kwargs()
kwargs.update({"request": self.request})
return kwargs

def get_success_url(self):
success_url = reverse("type_of_service")
if start_view := self.request.session.get("StartView", False):
Expand Down Expand Up @@ -472,8 +467,7 @@ def get_success_url(self):
if add_recipient:
return reverse("where_is_the_recipient_located")
else:
# todo: change success url to licensing grounds flow
return reverse("complete")
return reverse("licensing_grounds")


class DeleteRecipientView(BaseFormView):
Expand All @@ -490,3 +484,29 @@ def post(self, *args: object, **kwargs: object) -> HttpResponse:
class RelationshipProviderRecipientView(BaseFormView):
form_class = forms.RelationshipProviderRecipientForm
success_url = reverse_lazy("recipient_added")


class LicensingGroundsView(BaseFormView):
form_class = forms.LicensingGroundsForm
success_url = reverse_lazy("purpose_of_provision")

def get_success_url(self) -> str:
if professional_or_business_service := self.request.session.get("ProfessionalOrBusinessServicesView", False):
if professional_or_business_service.get("professional_or_business_service") == "legal_advisory":
return reverse("licensing_grounds_legal_advisory")
return reverse("purpose_of_provision")


class LicensingGroundsLegalAdvisoryView(BaseFormView):
form_class = forms.LicensingGroundsForm
success_url = reverse_lazy("upload_documents")

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["legal_advisory"] = True
return kwargs


class PurposeOfProvisionView(BaseFormView):
form_class = forms.PurposeOfProvisionForm
success_url = reverse_lazy("upload_documents")

0 comments on commit ceca0db

Please sign in to comment.