Skip to content

Commit

Permalink
Merge pull request #2263 from uktrade/LTD-5714-other-ogd-sessionwizard
Browse files Browse the repository at this point in the history
Ltd 5714 other ogd sessionwizard
  • Loading branch information
Tllew authored Jan 14, 2025
2 parents c1888a6 + 508d3b7 commit 2d201ca
Show file tree
Hide file tree
Showing 37 changed files with 638 additions and 182 deletions.
4 changes: 2 additions & 2 deletions caseworker/advice/conditionals.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ def _get_form_field_boolean(wizard):
return _get_form_field_boolean


def is_desnz_team(wizard):
return wizard.caseworker["team"]["alias"] in services.DESNZ_TEAMS
def is_fcdo_team(wizard):
return wizard.caseworker["team"]["alias"] == services.FCDO_TEAM
3 changes: 1 addition & 2 deletions caseworker/advice/forms/approval.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Layout:
TITLE = "Recommend an approval"

approval_reasons = forms.CharField(
widget=forms.Textarea(attrs={"rows": 7}),
widget=forms.Textarea(attrs={"rows": 7, "class": "govuk-!-margin-top-4", "name": "approval_reasons"}),
label="",
error_messages={"required": "Enter a reason for approving"},
)
Expand All @@ -61,7 +61,6 @@ def __init__(self, *args, **kwargs):
approval_choices, approval_text = self._picklist_to_choices(approval_reason)
self.approval_text = approval_text
super().__init__(*args, **kwargs)

self.fields["approval_radios"].choices = approval_choices

def get_layout_fields(self):
Expand Down
2 changes: 1 addition & 1 deletion caseworker/advice/forms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class GiveApprovalAdviceForm(PicklistAdviceForm):
)
instructions_to_exporter = forms.CharField(
widget=forms.Textarea(attrs={"rows": "3"}),
label="Add any instructions for the exporter (optional)",
label="Add instructions to the exporter, or a reporting footnote (optional)",
help_text="These may be added to the licence cover letter, subject to review by the Licensing Unit.",
required=False,
)
Expand Down
10 changes: 5 additions & 5 deletions caseworker/advice/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ def can_desnz_make_recommendation(user, case, queue_alias):
return True


def can_desnz_make_edit(team):
return team in services.DESNZ_TEAMS
def can_ogd_make_edit(team):
return team != services.FCDO_TEAM


def case_has_approval_advice(advice):
Expand All @@ -44,15 +44,15 @@ def case_has_approval_advice(advice):


@rules.predicate
def can_user_make_desnz_edit(request, case):
def can_user_make_edit(request, case):
try:
user = request.lite_user
except AttributeError:
return False

team = user["team"]["alias"]
advice = services.filter_current_user_advice(case.advice, user["id"])
return can_desnz_make_edit(team) and case_has_approval_advice(advice)
return can_ogd_make_edit(team) and case_has_approval_advice(advice)


@rules.predicate
Expand Down Expand Up @@ -84,4 +84,4 @@ def can_user_make_recommendation(request, case):

rules.add_rule("can_user_make_recommendation", is_user_allocated & can_user_make_recommendation)
rules.add_rule("can_user_allocate_and_approve", can_user_make_recommendation)
rules.add_rule("can_user_make_desnz_edit", can_user_make_desnz_edit)
rules.add_rule("can_user_make_edit", can_user_make_edit)
4 changes: 2 additions & 2 deletions caseworker/advice/templates/advice/view_my_advice.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ <h2 class="govuk-error-summary__title" id="error-summary-title">
<div class="govuk-grid-column-three-quarters">
<h1 class="govuk-heading-xl">View recommendation</h1>
{% if my_advice %}
{% test_rule 'can_user_make_desnz_edit' request case as can_user_make_desnz_edit %}
{% test_rule 'can_user_make_edit' request case as can_user_make_edit %}

{% if buttons.edit_recommendation %}
{% if can_user_make_desnz_edit %}
{% if can_user_make_edit %}
<a role="button" draggable="false" class="govuk-button govuk-button--secondary" href="{% url 'cases:edit_advice' queue_pk case.id %}">Edit recommendation</a>
{% else %}
<a role="button" draggable="false" class="govuk-button govuk-button--secondary" href="{% url 'cases:edit_advice_legacy' queue_pk case.id %}">Edit recommendation</a>
Expand Down
4 changes: 2 additions & 2 deletions caseworker/advice/urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from django.urls import path

from caseworker.advice.views import consolidate, views
from caseworker.advice.views.approval import GiveApprovalAdviceView
from caseworker.advice.views.approval import GiveApprovalAdviceView, SelectAdviceView
from caseworker.advice.views.edit import EditAdviceView

urlpatterns = [
path("", views.AdviceView.as_view(), name="advice_view"),
path("case-details/", views.CaseDetailView.as_view(), name="case_details"),
path("select-advice/", views.SelectAdviceView.as_view(), name="select_advice"),
path("select-advice/", SelectAdviceView.as_view(), name="select_advice"),
path("approve-all-legacy/", views.GiveApprovalAdviceViewLegacy.as_view(), name="approve_all_legacy"),
path("approve-all/", GiveApprovalAdviceView.as_view(), name="approve_all"),
path("refuse-all/", views.RefusalAdviceView.as_view(), name="refuse_all"),
Expand Down
28 changes: 25 additions & 3 deletions caseworker/advice/views/approval.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from http import HTTPStatus
from caseworker.advice.conditionals import form_add_licence_conditions, is_desnz_team
from caseworker.advice.conditionals import form_add_licence_conditions, is_fcdo_team
from caseworker.advice.forms.approval import (
FootnotesApprovalAdviceForm,
PicklistLicenceConditionsForm,
SimpleLicenceConditionsForm,
RecommendAnApprovalForm,
SelectAdviceForm,
)
from caseworker.advice.payloads import GiveApprovalAdvicePayloadBuilder
from caseworker.advice.picklist_helpers import approval_picklist, footnote_picklist, proviso_picklist
Expand All @@ -14,16 +15,37 @@
from django.urls import reverse
from caseworker.advice.views.mixins import CaseContextMixin
from caseworker.advice import services

from caseworker.advice.constants import AdviceSteps
from core.auth.views import LoginRequiredMixin
from core.decorators import expect_status
from django.views.generic import FormView


class SelectAdviceView(LoginRequiredMixin, CaseContextMixin, FormView):
template_name = "advice/select_advice.html"
form_class = SelectAdviceForm

def get_success_url(self):
if self.recommendation == "approve_all":
if self.caseworker["team"]["alias"] == services.FCDO_TEAM:
return reverse("cases:approve_all_legacy", kwargs=self.kwargs)
return reverse("cases:approve_all", kwargs=self.kwargs)
else:
return reverse("cases:refuse_all", kwargs=self.kwargs)

def form_valid(self, form):
self.recommendation = form.cleaned_data["recommendation"]
return super().form_valid(form)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return {**context, "security_approvals_classified_display": self.security_approvals_classified_display}


class BaseApprovalAdviceView(LoginRequiredMixin, CaseContextMixin, BaseSessionWizardView):

condition_dict = {
AdviceSteps.RECOMMEND_APPROVAL: C(is_desnz_team),
AdviceSteps.RECOMMEND_APPROVAL: ~C(is_fcdo_team),
AdviceSteps.LICENCE_CONDITIONS: C(form_add_licence_conditions(AdviceSteps.RECOMMEND_APPROVAL)),
AdviceSteps.LICENCE_FOOTNOTES: C(form_add_licence_conditions(AdviceSteps.RECOMMEND_APPROVAL)),
}
Expand Down
31 changes: 5 additions & 26 deletions caseworker/advice/views/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from http import HTTPStatus
from caseworker.advice.forms.approval import MoveCaseForwardForm, SelectAdviceForm
from caseworker.advice.forms.approval import MoveCaseForwardForm
from caseworker.advice.forms.consolidate import (
ConsolidateApprovalForm,
LUConsolidateRefusalForm,
Expand Down Expand Up @@ -50,24 +50,6 @@ class CaseDetailView(LoginRequiredMixin, CaseContextMixin, TemplateView):
template_name = "advice/case_detail_example.html"


class SelectAdviceView(LoginRequiredMixin, CaseContextMixin, FormView):
template_name = "advice/select_advice.html"
form_class = SelectAdviceForm

def get_success_url(self):
recommendation = self.request.POST.get("recommendation")
if recommendation == "approve_all":
if self.caseworker["team"]["alias"] in services.DESNZ_TEAMS:
return reverse("cases:approve_all", kwargs=self.kwargs)
return reverse("cases:approve_all_legacy", kwargs=self.kwargs)
else:
return reverse("cases:refuse_all", kwargs=self.kwargs)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return {**context, "security_approvals_classified_display": self.security_approvals_classified_display}


class GiveApprovalAdviceViewLegacy(LoginRequiredMixin, CaseContextMixin, FormView):
"""
Form to recommend approval advice for all products on the application
Expand All @@ -76,13 +58,10 @@ class GiveApprovalAdviceViewLegacy(LoginRequiredMixin, CaseContextMixin, FormVie
template_name = "advice/give-approval-advice.html"

def get_form(self):
if self.caseworker["team"]["alias"] == services.FCDO_TEAM:
return FCDOApprovalAdviceForm(
services.unadvised_countries(self.caseworker, self.case),
**self.get_form_kwargs(),
)
else:
return GiveApprovalAdviceForm(**self.get_form_kwargs())
return FCDOApprovalAdviceForm(
services.unadvised_countries(self.caseworker, self.case),
**self.get_form_kwargs(),
)

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
Expand Down
1 change: 1 addition & 0 deletions conf/caseworker.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,4 @@
# using it here as some browsers still don't support CSP_REPORT_TO which replaces it

CSP_REPORT_URI = env.tuple("CASEWORKER_CSP_REPORT_URI", default=("",))
E2E_WAIT_MULTIPLIER = env.int("E2E_WAIT_MULTIPLIER", default=1)
1 change: 1 addition & 0 deletions conf/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,4 @@
# using it here as some browsers still don't support CSP_REPORT_TO which replaces it

CSP_REPORT_URI = env.tuple("EXPORTER_CSP_REPORT_URI", default=("",))
E2E_WAIT_MULTIPLIER = env.int("E2E_WAIT_MULTIPLIER", default=1)
13 changes: 7 additions & 6 deletions tests_common/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from django.conf import settings


def click_submit(driver: WebDriver):
Expand Down Expand Up @@ -70,7 +71,7 @@ def select_multi_select_options(driver: WebDriver, element_selector: str, option
element = driver.find_element(by=By.CSS_SELECTOR, value=element_selector)
element.send_keys(option)
element.send_keys(Keys.ENTER)
WebDriverWait(driver, 30).until(
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located(
(By.XPATH, f"//span[@class='selected-options__option-text' and contains(text(), '{option}')]")
),
Expand All @@ -83,17 +84,17 @@ def click_apply_filters(driver: WebDriver):

def open_case_filters(driver: WebDriver):
if not driver.find_element(by=By.CLASS_NAME, value="case-filters").is_displayed():
WebDriverWait(driver, 30).until(
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located((By.ID, "show-filters-link"))
).click()
WebDriverWait(driver, 30).until(
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.element_to_be_clickable((By.ID, "accordion-case-filters"))
).click()


def try_open_filters(driver: WebDriver):
if not driver.find_element(by=By.CLASS_NAME, value="lite-filter-bar").is_displayed():
WebDriverWait(driver, 30).until(
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located((By.ID, "show-filters-link"))
).click()

Expand All @@ -115,7 +116,7 @@ def click_next_page(driver: WebDriver):
def select_report_summary_subject_and_fill(driver, subject):
suggestion_input_autocomplete = driver.find_element(by=By.ID, value="_report_summary_subject")
suggestion_input_autocomplete.send_keys(subject)
WebDriverWait(driver, 30).until(
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.text_to_be_present_in_element(
(By.CSS_SELECTOR, ".lite-autocomplete__menu--visible #_report_summary_subject__option--0"),
subject,
Expand All @@ -128,7 +129,7 @@ def select_report_summary_subject_and_fill(driver, subject):
def select_report_summary_prefix_and_fill(driver, prefix):
suggestion_input_autocomplete = driver.find_element(by=By.ID, value="_report_summary_prefix")
suggestion_input_autocomplete.send_keys(prefix)
WebDriverWait(driver, 30).until(
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.text_to_be_present_in_element(
(By.CSS_SELECTOR, ".lite-autocomplete__menu--visible #_report_summary_prefix__option--0"),
prefix,
Expand Down
25 changes: 17 additions & 8 deletions ui_tests/caseworker/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def prepare_case(api_test_client, nlr): # noqa
def submit_form(driver): # noqa
old_page = driver.find_element(by=By.TAG_NAME, value="html")
Shared(driver).click_submit()
WebDriverWait(driver, 45).until(expected_conditions.staleness_of(old_page))
WebDriverWait(driver, 45 * settings.E2E_WAIT_MULTIPLIER).until(expected_conditions.staleness_of(old_page))


@when(parsers.parse('I click the text "{text}"'))
Expand All @@ -295,7 +295,7 @@ def click_text(driver, text): # noqa

@when(parsers.parse('I click "{button_text}"'))
def click_button_with_text(driver, button_text): # noqa
WebDriverWait(driver, 20).until(
WebDriverWait(driver, 20 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located(
(
By.XPATH,
Expand Down Expand Up @@ -396,21 +396,28 @@ def case_list_page(driver, internal_url): # noqa

@when("I go to my profile page") # noqa
def get_profile_page(driver): # noqa
WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "link-profile"))).click()
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located((By.ID, "link-profile"))
).click()


@when(parsers.parse('I change my team to "{team}" and default queue to "{queue}"')) # noqa
def go_to_team_edit_page(driver, team, queue): # noqa
# we should already be on the profile page
WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "link-edit-team"))).click()
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located((By.ID, "link-edit-team"))
).click()
teams_page = TeamsPages(driver)
teams_page.select_team_from_dropdown(team)
teams_page.select_default_queue_from_dropdown(queue)
functions.click_submit(driver)
# Ensure we return to the profile page
WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "link-edit-team")))
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located((By.ID, "link-edit-team"))
)
# Check that the team/queue change was applied successfully
assert driver.find_element(by=By.ID, value="user-team-name").text == team
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER)
assert driver.find_element(by=By.ID, value="user-default-queue").text == queue


Expand All @@ -432,7 +439,9 @@ def system_queue_shown_in_dropdown(driver, queue_name): # noqa
@when(parsers.parse('I switch to "{queue_name}" queue')) # noqa
def switch_to_queue(driver, queue_name): # noqa
driver.find_element(by=By.ID, value="link-queue").click()
WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "filter-queues")))
WebDriverWait(driver, 30 * settings.E2E_WAIT_MULTIPLIER).until(
expected_conditions.presence_of_element_located((By.ID, "filter-queues"))
)
driver.find_element(by=By.ID, value="filter-queues").send_keys(queue_name)
elements = [
item
Expand Down Expand Up @@ -678,7 +687,7 @@ def click_edit_case_flags_link(driver, flag_name):

old_page = driver.find_element(by=By.TAG_NAME, value="html")
functions.click_submit(driver)
WebDriverWait(driver, 45).until(expected_conditions.staleness_of(old_page))
WebDriverWait(driver, 45 * settings.E2E_WAIT_MULTIPLIER).until(expected_conditions.staleness_of(old_page))


@given(parsers.parse('the status is set to "{status}"')) # noqa
Expand Down Expand Up @@ -1005,7 +1014,7 @@ def approve_case_as_team(driver, team, queue, context, internal_url, internal_in
recommendation_and_decisions_page.click_make_recommendation()
recommendation_and_decisions_page.click_approve_all()
Shared(driver).click_submit()
recommendation_and_decisions_page.enter_reasons_for_approving("approving")
recommendation_and_decisions_page.enter_approval_reasons("approving")
functions.click_submit(driver) # Submit recommmendation
functions.click_submit(driver) # Move case forward
click_on_created_application(driver, context, internal_url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,20 @@ Feature: I want to record my user advice and any comments and conditions relatin
And I click make recommendation
And I click approve all
And I click continue
And I enter "reason for approving" as the reasons for approving
And I click the text "Add a licence condition, instruction to exporter or footnote"
And I enter "MOD licence condition" as the licence condition
And I enter "instruction for exporter" as the instructions for the exporter
And I enter "reporting footnote" as the reporting footnote
And I enter "reason for approving" as the approval reasons
And I click add licence condition
And I click continue
And I enter "MOD licence condition" into the licence condition
And I click continue
And I enter "instruction for exporter" as the instructions for the exporter on the instructions step
And I enter "reporting footnote" as the reporting footnote on the instructions step
And I click submit recommendation
Then I see "reason for approving" as the reasons for approving
And I see "MOD licence condition" as the licence condition
And I see "instruction for exporter" as the instructions for the exporter
And I see "reporting footnote" as the reporting footnote


##### FCDO Sub-advisor to give advice #####
When I go to my profile page
And I change my team to "FCDO" and default queue to "FCDO Cases to Review"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,19 @@ Feature: I want to record my user advice and any comments and conditions relatin
And I click make recommendation
And I click approve all
And I click continue
And I enter "reason for approving" as the reasons for approving
And I click the text "Add a licence condition, instruction to exporter or footnote"
And I enter "licence condition" as the licence condition
And I enter "instruction for exporter" as the instructions for the exporter
And I enter "reporting footnote" as the reporting footnote
And I click submit recommendation
And I enter "reason for approving" as the approval reasons
And I click add licence condition
And I click continue
And I enter "licence condition" into the licence condition
And I click continue
And I enter "instruction for exporter" as the instructions for the exporter on the instructions step
And I enter "reporting footnote" as the reporting footnote on the instructions step
And I click continue
Then I see "reason for approving" as the reasons for approving
And I see "licence condition" as the licence condition
And I see "instruction for exporter" as the instructions for the exporter
And I see "reporting footnote" as the reporting footnote

When I click move case forward
Then I don't see previously created application

Expand Down
Loading

0 comments on commit 2d201ca

Please sign in to comment.