From e58bc644918dc92168ceda65950ad2011261046b Mon Sep 17 00:00:00 2001 From: Kevin Carrogan Date: Tue, 6 Feb 2024 12:52:23 +0000 Subject: [PATCH 01/15] Close query form thing --- caseworker/cases/forms/queries.py | 6 ++-- caseworker/cases/helpers/case.py | 2 +- caseworker/cases/views/queries.py | 21 ++++++++++++++ caseworker/templates/case/close-query.html | 33 ++++++++++++++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 caseworker/templates/case/close-query.html diff --git a/caseworker/cases/forms/queries.py b/caseworker/cases/forms/queries.py index 74f584b58d..b506c6a2fd 100644 --- a/caseworker/cases/forms/queries.py +++ b/caseworker/cases/forms/queries.py @@ -8,10 +8,12 @@ class CloseQueryForm(forms.Form): reason_for_closing_query = forms.CharField( label="Why are you closing the query? This will not be visible to the exporter.", widget=forms.Textarea, - required=False, ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() - self.helper.layout = Layout("reason_for_closing_query", Button("submit", "Submit")) + self.helper.layout = Layout( + "reason_for_closing_query", + Button("submit", "Submit"), + ) diff --git a/caseworker/cases/helpers/case.py b/caseworker/cases/helpers/case.py index aa364909c7..da4ea6ca2e 100644 --- a/caseworker/cases/helpers/case.py +++ b/caseworker/cases/helpers/case.py @@ -239,7 +239,7 @@ def _transform_data(self): for queue_detail in self.case.queue_details: queue_detail["days_on_queue_elapsed"] = (timezone.now() - parse(queue_detail["joined_queue_at"])).days - def get(self, request, **kwargs): + def get(self, request, *args, **kwargs): self.case_id = str(kwargs["pk"]) self.case = get_case(request, self.case_id) self.queue_id = kwargs["queue_pk"] diff --git a/caseworker/cases/views/queries.py b/caseworker/cases/views/queries.py index 61b00a2bba..a0840ec09e 100644 --- a/caseworker/cases/views/queries.py +++ b/caseworker/cases/views/queries.py @@ -1,13 +1,16 @@ +from django.http import Http404 from django.urls import reverse from django.views.generic import FormView from caseworker.cases.forms.queries import CloseQueryForm +from caseworker.cases.helpers.ecju_queries import get_ecju_queries from caseworker.cases.services import put_ecju_query from core.auth.views import LoginRequiredMixin class CloseQueryView(LoginRequiredMixin, FormView): form_class = CloseQueryForm + template_name = "case/close-query.html" def dispatch(self, request, *args, **kwargs): self.lite_user = request.lite_user @@ -35,3 +38,21 @@ def get_success_url(self): "tab": "ecju-queries", }, ) + + def get_query(self, open_ecju_queries): + for query in open_ecju_queries: + if query["id"] == str(self.kwargs["query_pk"]): + return query + return None + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + + open_ecju_queries, _ = get_ecju_queries(self.request, self.kwargs["pk"]) + query = self.get_query(open_ecju_queries) + if not query: + raise Http404 + + context["query"] = query + + return context diff --git a/caseworker/templates/case/close-query.html b/caseworker/templates/case/close-query.html new file mode 100644 index 0000000000..b112766921 --- /dev/null +++ b/caseworker/templates/case/close-query.html @@ -0,0 +1,33 @@ +{% extends 'layouts/two-pane.html' %} +{% load crispy_forms_tags crispy_forms_gds %} + +{% block title %}{{title}}{% endblock %} +{% block back_link %} + {{ back_link_text|default:"Back" }} +{% endblock %} + +{% block two_thirds %} + +{% if errors %} + {% include "forms-errors.html" %} +{% endif %} + +
+ {% csrf_token %} + + {% error_summary form %} + +
+

+ +

+
+ {{ query.question }} +
+ {% crispy form %} +
+
+ +{% endblock %} From ceed2abe54332016256bd16008ce961ea08cf151 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Wed, 7 Feb 2024 17:13:37 +0000 Subject: [PATCH 02/15] Add Accessibility statement for both Internal and Exporter sites --- caseworker/templates/layouts/base.html | 5 + caseworker/urls.py | 3 + core/accessibility/views.py | 12 ++ .../accessibility/accessibility.html | 106 ++++++++++++++++++ exporter/templates/layouts/base.html | 5 + exporter/urls.py | 3 + unit_tests/caseworker/core/test_views.py | 14 +++ unit_tests/exporter/core/test_views.py | 11 ++ 8 files changed, 159 insertions(+) create mode 100644 core/accessibility/views.py create mode 100644 core/templates/accessibility/accessibility.html create mode 100644 unit_tests/caseworker/core/test_views.py diff --git a/caseworker/templates/layouts/base.html b/caseworker/templates/layouts/base.html index 0fad2fc156..17b0121056 100644 --- a/caseworker/templates/layouts/base.html +++ b/caseworker/templates/layouts/base.html @@ -152,6 +152,11 @@

Support links

{% endif %} + diff --git a/caseworker/urls.py b/caseworker/urls.py index 6e09bebe91..99d359453b 100644 --- a/caseworker/urls.py +++ b/caseworker/urls.py @@ -3,6 +3,8 @@ import caseworker.core.views +from core.accessibility.views import AccessibilityStatementView + urlpatterns = [ path("healthcheck/", include("health_check.urls")), @@ -27,6 +29,7 @@ path("tau/report_summary/", include("caseworker.report_summary.urls")), path("search/", include("caseworker.search.urls")), path("bookmarks/", include("caseworker.bookmarks.urls")), + path("accessibility-statement/", AccessibilityStatementView.as_view(), name="caseworker-accessibility-statement"), ] diff --git a/core/accessibility/views.py b/core/accessibility/views.py new file mode 100644 index 0000000000..cdacc0175f --- /dev/null +++ b/core/accessibility/views.py @@ -0,0 +1,12 @@ +from django.views.generic import TemplateView + + +class AccessibilityStatementView(TemplateView): + template_name = "accessibility/accessibility.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + uri = self.request.build_absolute_uri() + # Exclude current path and take only complete host name + context["host"] = uri.rsplit("/", 2)[0] + return context diff --git a/core/templates/accessibility/accessibility.html b/core/templates/accessibility/accessibility.html new file mode 100644 index 0000000000..c059b5533c --- /dev/null +++ b/core/templates/accessibility/accessibility.html @@ -0,0 +1,106 @@ +{% extends 'layouts/base.html' %} + +{% block title %}Accessibility statement{% endblock %} + +{% block body %} +
+
+
+
+
+

+ Accessibility statement +

+
+ +

+ This statement applies to {{ host }} +

+

+ This service is run by the Department for Business and Trade (DBT). It is currently in private beta + but is designed to be used by as many people as possible when it goes into public beta for + standard individual export licences (SIELs). +

+

+ AbilityNet has advice on making your device easier to + use if you have a disability. +

+ +

How accessible this website is

+

+ The service meets the Content Accessibility Guidelines (WCAG) version 2.1 AA standard. +

+

+ The below areas do not meet 2.1 AAA requirements, which were not in scope for the purposes of + this audit: +

    +
  • there was an ambiguous link identified on two pages that may be difficult to understand for + screen reader users browsing out of context
  • +
  • links that opened in a new window without informing users were identified
  • +
+

+ +

Feedback and contact information

+

+ If you find any problems not listed on this page or think we do not meet accessibility requirements, + contact LITE.support@businessandtrade.gov.uk. +

+

+ We’ll consider your request and get back to you within 15 days. +

+ +

Enforcement procedure

+

+ The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public + Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the + 'accessibility regulations'). If you're not happy with how we respond to your complaint, contact the + Equality Advisory and Support Service (EASS). +

+ +

Technical information about this website's accessibility

+

+ We are committed to making this website accessible, in accordance with the Public Sector Bodies + (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018. +

+ +

Compliance status

+

+ This website is fully compliant with the Web Content + Accessibility Guidelines version 2.1 AA standard. +

+ +

Content that’s not within the scope of the accessibility regulations

+

+ Our PDF documents are essential to providing our services. For example, we have PDFs with + information on the application outcome and a copy of the application is generated as a PDF. +

+ +

What we're doing to improve accessibility

+

+ We will schedule another accessibility audit in late 2024 to identify any issues that do not meet + the WCAG 2.2. success criteria. +

+

+ In late 2024, we will consider what we can do to improve the accessibility of our PDF documents + and licences. +

+ +

Preparation of this accessibility statement

+

+ This statement was prepared on Friday 2 February 2024. It was last reviewed on Friday 2 + February 2024. +

+

+ This website was last tested on 30 May 2023 and was checked for compliance with the WCAG 2.1 + AA standard. The test was carried out by the Digital Accessibility Centre (DAC). +

+ +
+
+
+
+ +{% endblock %} diff --git a/exporter/templates/layouts/base.html b/exporter/templates/layouts/base.html index f41e57482a..30c0d10bab 100644 --- a/exporter/templates/layouts/base.html +++ b/exporter/templates/layouts/base.html @@ -120,6 +120,11 @@

Support links

{% endif %} +
+
+
+
+

+ Privacy notice +

+ +

+ This notice sets out your rights with respect to how we will use your personal data when you apply + for a standard individual export + licence (SIEL). +

+

+ This notice explains how the Department for Business and Trade (DBT) (also referred to as “We” or + “Us” or “Our” in this privacy + notice) will use your personal data. We recognise that we have a duty to people whose information we + hold to treat that information + responsibly, keep it safe and secure, and process it correctly and proportionately. We will process + your personal data lawfully and + fairly in line with the 2018 Data Protection Act. +

+

+ This privacy notice broadly explains the information we collect, the purpose for processing, + categories of personal information and + who we may share it with. It is important that you read this notice, so that you are aware of how + and why we are using your + information. +

+ +

Purpose of privacy notice

+

+ This online service is for applying for export licenses and clearances, related to goods that + require government permission to be + exported from the UK or traded between countries. +

+

+ The information you provide will be processed by DBT and shared with third parties for the purpose + of processing licencing or + clearance application for controlled strategic goods and services. +

+

+ The information you provide will be processed on a lawful basis to enable DBT to perform a task in + the public interest or to fulfil an + official function, including conducting research appropriate to DBT and export controls. +

+ +

What data we collect

+

+ The personal data we will collect includes: +

    +
  • full name
  • +
  • email address
  • +
  • phone number
  • +
  • address
  • +
  • data related to criminal convictions, if applicable
  • +
+

+ +

Processing of criminal data

+

+ Processing of criminal data is pursuant to Article 11 (1) of the Firearms Regulation No. 258/2012. + The article stipulates that an + export authorisation (licence) must be refused if the applicant has a criminal record concerning + conduct constituting an offence, + punishable by a term of imprisonment of not less than four years. +

+

+ DBT has a duty to identify individuals that do not meet the criteria for licencing. +

+ +

Our legal basis for processing your data

+

+ DBT is the data controller for personal data you provide to us. We process the data on the lawful + basis of legal obligation and the + processing is necessary to comply with the law. +

+ +

How we may share your information

+

+ In line with the purpose your personal information may be shared with the following parties; +

+ +

+ These are: +

    +
  • Ministry of Defence
  • +
  • Foreign Commonwealth and Development Office
  • +
  • HM Revenue and Customs
  • +
  • Department for Energy Security and Net Zero
  • +
  • National Cyber Security Centre
  • +
  • UK Border Force – Home Office
  • +
  • Australia Group
  • +
  • Nuclear Suppliers Group
  • +
  • Wassenaar Arrangement
  • +
  • Missile Technology Control Regime
  • +
  • Europe Union
  • +
+

+

+ Aggregated analysis of data collected may be shared with the Information Commissioner’s Office (ICO) + the Government Internal + Audit Agency (GIAA), and the National Audit Office (NAO). +

+

+ We may also anonymise some personal data you provide to us to ensure that you cannot be identified + and use this data to allow + DBT to effectively target and plan the provision of services related to the purposes described + above. +

+

+ We will not: +

    +
  • sell or rent your data to third parties
  • +
  • share your data with third parties for marketing purposes
  • +
  • use your personal data in analytics
  • +
+

+

+ We will also share your data if we are required to do so by law or regulation, for example, by court + order, or to prevent fraud or + other crime. +

+ + +

How long we will keep your information

+

+ We will only retain your personal information for as long as necessary to fulfil the purposes we + collected it for, including for the + purposes of satisfying any legal, accounting, or reporting requirements. +

+

+ We will retain your personal information for as long as: +

    +
  • it is needed to fulfil the purposes set out in this document
  • +
  • the law requires us to do so
  • +
+

+

+ Subject to the paragraph above, we will only retain your personal data and criminal offence data for + as long as: +

    +
  • it is needed for the purposes set out in this document; or
  • +
  • the law requires us to
  • +
+

+

+ However, we conduct regular reviews to ensure we only keep information required for the purpose of + which it was collected. If + there is any indication of a business need to extend this retention period, we will robustly review + it and communicate any changes + in a revised notice. +

+ +

Your rights and access to your information

+

+ You have the right to request a copy of the information that we hold about you. The Data Protection + Act (DPA) also gives you + additional rights that refer to how DBT holds and uses your information. +

+

+ Under certain circumstances, by law you have the right to: +

    +
  • request information about how your personal data is processed
  • +
  • raise an objection about how your personal data is processed
  • +
+

+ +

Contact us

+

+ The Department for Business and Trade is registered as a Data Controller under the General Data + Protection Regulation and Data + Protection Act 2018. Our contact details are: +

+

+ Data Protection Officer
+ Old Admiralty Building
+ Whitehall
+ London
+ SW1A 2DY
+ Email: data.protection@businessandtrade.gov.uk
+

+ +

+ You have a right to complain to us if you think we have not complied with our obligation for + handling your personal information. You + can contact our Data Protection Officer using the same contact. +

+ +

Contact the Information Commissioner’s Office

+

+ If you are not satisfied with the DBT response you have a right to complain to the Information + Commissioner’s Office (ICO). You + can report a concern by contacting the ICO on the below details. +

+ +

+ Information Commissioner’s Office
+ Wycliffe House
+ Water Lane
+ Wilmslow
+ Cheshire
+ SK9 5AF
+
+ Email: casework@ico.org.uk +

+ Tel 0303 123 1113 +

+ Textphone 01625 545860
+ Monday to Friday 9am to 4:30pm +

+ For more information about your rights under the Data Protection Act or to request a copy of any + data held about you please + contact data.protection@businessandtrade.gov.uk. +

+ +

Confidentiality

+

+ If you wish the information you provide to be treated as confidential, please be aware that, in + accordance with the Freedom of + Information Act (FOIA), public authorities are required to comply with the FOIA. +

+ +

In view of this, it would be helpful if you have reasons for confidentially, if + you could explain to us why you wish that information to + be treated confidentially. If we receive a request for disclosure of information that has been + provided, we will take full account of + your explanation, but we cannot give an assurance that confidentiality can be maintained in all + circumstances. +

+ +

Changes to this privacy notice

+

+ We reserve the right to update this privacy notice at any time and we will provide you with a new + privacy notice when we make any + substantial updates. +

+ +
+
+
+
+ +{% endblock %} diff --git a/exporter/templates/layouts/base.html b/exporter/templates/layouts/base.html index f41e57482a..6b1a85c0ef 100644 --- a/exporter/templates/layouts/base.html +++ b/exporter/templates/layouts/base.html @@ -120,6 +120,11 @@

Support links

{% endif %} +
-
+
-
-

- Accessibility statement -

-
+

+ Accessibility statement +

This statement applies to {{ host }} @@ -26,7 +24,8 @@

standard individual export licences (SIELs).

- AbilityNet has advice on making your device easier to + AbilityNet has advice on making your device easier to use if you have a disability.

@@ -37,7 +36,7 @@

How accessible this website is

The below areas do not meet 2.1 AAA requirements, which were not in scope for the purposes of this audit: -

    +
    • there was an ambiguous link identified on two pages that may be difficult to understand for screen reader users browsing out of context
    • links that opened in a new window without informing users were identified
    • @@ -47,7 +46,7 @@

      How accessible this website is

      Feedback and contact information

      If you find any problems not listed on this page or think we do not meet accessibility requirements, - contact LITE.support@businessandtrade.gov.uk.

      @@ -59,6 +58,7 @@

      Enforcement procedure

      The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the 'accessibility regulations'). If you're not happy with how we respond to your complaint, contact the Equality Advisory and Support Service (EASS).

      @@ -71,7 +71,8 @@

      Technical information about this website's accessibi

      Compliance status

      - This website is fully compliant with the Web Content + This website is fully compliant with the Web Content Accessibility Guidelines version 2.1 AA standard.

      @@ -98,7 +99,7 @@

      Preparation of this accessibility statement

      This website was last tested on 30 May 2023 and was checked for compliance with the WCAG 2.1 - AA standard. The test was carried out by the Digital Accessibility Centre (DAC).

      From f39424d4b8886e85d38c7da2ca63b022f1311dc4 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 8 Feb 2024 10:27:36 +0000 Subject: [PATCH 06/15] Address review comments --- exporter/templates/core/privacy_notice.html | 6 +++--- unit_tests/exporter/core/test_views.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exporter/templates/core/privacy_notice.html b/exporter/templates/core/privacy_notice.html index 866f7555d7..56d1d149ef 100644 --- a/exporter/templates/core/privacy_notice.html +++ b/exporter/templates/core/privacy_notice.html @@ -4,7 +4,7 @@ Back {% endblock %} -{% block title %}Data Privacy Notices{% endblock %} +{% block title %}Privacy notice{% endblock %} {% block body %}
      @@ -45,7 +45,7 @@

      Purpose of privacy notice

      The information you provide will be processed by DBT and shared with third parties for the purpose - of processing licencing or + of processing licensing or clearance application for controlled strategic goods and services.

      @@ -75,7 +75,7 @@

      Processing of criminal data

      punishable by a term of imprisonment of not less than four years.

      - DBT has a duty to identify individuals that do not meet the criteria for licencing. + DBT has a duty to identify individuals that do not meet the criteria for licensing.

      Our legal basis for processing your data

      diff --git a/unit_tests/exporter/core/test_views.py b/unit_tests/exporter/core/test_views.py index 95c4567ed1..8d80f0e24f 100644 --- a/unit_tests/exporter/core/test_views.py +++ b/unit_tests/exporter/core/test_views.py @@ -109,4 +109,4 @@ def test_privacy_notice_view(authorized_client): soup = BeautifulSoup(response.content, "html.parser") assert soup.find("h1").string.strip() == "Privacy notice" - assert soup.title.string.strip() == "Data Privacy Notices - LITE - GOV.UK" + assert soup.title.string.strip() == "Privacy notice - LITE - GOV.UK" From e845f273b53b8febb2359e08cc640dc644fc5c54 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 8 Feb 2024 11:32:15 +0000 Subject: [PATCH 07/15] Update content following feedback --- exporter/templates/core/privacy_notice.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/templates/core/privacy_notice.html b/exporter/templates/core/privacy_notice.html index 56d1d149ef..4efb65f8cd 100644 --- a/exporter/templates/core/privacy_notice.html +++ b/exporter/templates/core/privacy_notice.html @@ -46,7 +46,7 @@

      Purpose of privacy notice

      The information you provide will be processed by DBT and shared with third parties for the purpose of processing licensing or - clearance application for controlled strategic goods and services. + clearance applications for controlled strategic goods and services.

      The information you provide will be processed on a lawful basis to enable DBT to perform a task in From 322190b918a6d4a0225b087ddaf80bf9f4781465 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 8 Feb 2024 13:43:07 +0000 Subject: [PATCH 08/15] Add error message to be displayed to the user when response is empty --- caseworker/cases/forms/queries.py | 1 + caseworker/templates/case/close-query.html | 6 ++- .../cases/forms/test_ecju_queries.py | 22 +++++++++ unit_tests/caseworker/cases/test_views.py | 47 ++++++++++++++++--- 4 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 unit_tests/caseworker/cases/forms/test_ecju_queries.py diff --git a/caseworker/cases/forms/queries.py b/caseworker/cases/forms/queries.py index b506c6a2fd..0cb25da1ce 100644 --- a/caseworker/cases/forms/queries.py +++ b/caseworker/cases/forms/queries.py @@ -8,6 +8,7 @@ class CloseQueryForm(forms.Form): reason_for_closing_query = forms.CharField( label="Why are you closing the query? This will not be visible to the exporter.", widget=forms.Textarea, + error_messages={"required": "Enter a reason why you are closing the query"}, ) def __init__(self, *args, **kwargs): diff --git a/caseworker/templates/case/close-query.html b/caseworker/templates/case/close-query.html index b112766921..a1092f159e 100644 --- a/caseworker/templates/case/close-query.html +++ b/caseworker/templates/case/close-query.html @@ -23,8 +23,10 @@

      Close query

      -
      - {{ query.question }} +
      +
      + {{ query.question }} +
      {% crispy form %}
      diff --git a/unit_tests/caseworker/cases/forms/test_ecju_queries.py b/unit_tests/caseworker/cases/forms/test_ecju_queries.py new file mode 100644 index 0000000000..cc17ffae2a --- /dev/null +++ b/unit_tests/caseworker/cases/forms/test_ecju_queries.py @@ -0,0 +1,22 @@ +import pytest + + +from caseworker.cases.forms.queries import CloseQueryForm + + +@pytest.mark.parametrize( + "data, is_valid, errors", + ( + ({}, False, {"reason_for_closing_query": ["Enter a reason why you are closing the query"]}), + ( + {"reason_for_closing_query": ""}, + False, + {"reason_for_closing_query": ["Enter a reason why you are closing the query"]}, + ), + ({"reason_for_closing_query": "closing response"}, True, {}), + ), +) +def test_ecju_queries_close_query_form(data, is_valid, errors): + form = CloseQueryForm(data=data) + assert form.is_valid() == is_valid + assert form.errors == errors diff --git a/unit_tests/caseworker/cases/test_views.py b/unit_tests/caseworker/cases/test_views.py index c60e95e856..ec76888ea4 100644 --- a/unit_tests/caseworker/cases/test_views.py +++ b/unit_tests/caseworker/cases/test_views.py @@ -505,9 +505,6 @@ def mock_get_queries(requests_mock, standard_case_pk, data_ecju_queries_gov_seri ) -@pytest.mark.parametrize( - ("reason_for_closing_query", "expected_status"), [("closing this query because xyz", 302), ("", 302)] -) def test_close_query_view_post_success( authorized_client, requests_mock, @@ -516,8 +513,6 @@ def test_close_query_view_post_success( data_ecju_queries_gov_serializer, data_query_closed_by_caseworker, mock_get_queries, - reason_for_closing_query, - expected_status, ): # see that the query is in the open queries section url = reverse("cases:case", kwargs={"queue_pk": queue_pk, "pk": standard_case_pk, "tab": "ecju-queries"}) @@ -533,9 +528,47 @@ def test_close_query_view_post_success( "cases:close_query", kwargs={"queue_pk": queue_pk, "pk": standard_case_pk, "query_pk": query_pk} ) response = authorized_client.post( - cases_close_query_url, data={f"{query_pk}-reason_for_closing_query": reason_for_closing_query} + cases_close_query_url, + data={ + f"{query_pk}-reason_for_closing_query": "Exporter clarified, closing this query", + }, + ) + assert response.status_code == 302 + + +def test_close_query_without_response_gives_error( + authorized_client, + requests_mock, + queue_pk, + standard_case_pk, + data_ecju_queries_gov_serializer, + data_query_closed_by_caseworker, + mock_get_queries, +): + # see that the query is in the open queries section + url = reverse("cases:case", kwargs={"queue_pk": queue_pk, "pk": standard_case_pk, "tab": "ecju-queries"}) + response = authorized_client.get(url) + soup = BeautifulSoup(response.content, "html.parser") + open_queries = soup.find(id="open-queries") + assert data_ecju_queries_gov_serializer["ecju_queries"][0]["question"] in str(open_queries) + + # close the query + query_pk = data_ecju_queries_gov_serializer["ecju_queries"][0]["id"] + requests_mock.put(client._build_absolute_uri(f"/cases/{standard_case_pk}/ecju-queries/{query_pk}/"), json={}) + cases_close_query_url = reverse( + "cases:close_query", kwargs={"queue_pk": queue_pk, "pk": standard_case_pk, "query_pk": query_pk} + ) + response = authorized_client.post( + cases_close_query_url, + data={ + f"{query_pk}-reason_for_closing_query": "", + }, ) - assert response.status_code == expected_status + assert response.status_code == 200 + + error_message = "Enter a reason why you are closing the query" + assert error_message in response.content.decode("utf-8") + assert response.context["form"].errors["reason_for_closing_query"] == [error_message] def test_close_query_view_show_closed_queries_on_page( From f73b9ae9bcee668d33d8e5f0ca48ff071d13a35b Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 8 Feb 2024 15:27:04 +0000 Subject: [PATCH 09/15] Add test to fix coverage error --- unit_tests/caseworker/cases/test_views.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/unit_tests/caseworker/cases/test_views.py b/unit_tests/caseworker/cases/test_views.py index ec76888ea4..ec0fe9d40f 100644 --- a/unit_tests/caseworker/cases/test_views.py +++ b/unit_tests/caseworker/cases/test_views.py @@ -571,6 +571,19 @@ def test_close_query_without_response_gives_error( assert response.context["form"].errors["reason_for_closing_query"] == [error_message] +def test_close_invalid_query_raises_error( + authorized_client, + queue_pk, + standard_case_pk, + mock_get_queries, +): + # try to close query with invalid id + query_pk = str(uuid.uuid4()) + url = reverse("cases:close_query", kwargs={"queue_pk": queue_pk, "pk": standard_case_pk, "query_pk": query_pk}) + response = authorized_client.post(url, data={f"{query_pk}-reason_for_closing_query": ""}) + assert response.status_code == 404 + + def test_close_query_view_show_closed_queries_on_page( authorized_client, requests_mock, From ec5f7fe27cff76264fee7bd800815138d5b58410 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Fri, 9 Feb 2024 11:16:01 +0000 Subject: [PATCH 10/15] Add title to close query form --- caseworker/cases/views/queries.py | 1 + 1 file changed, 1 insertion(+) diff --git a/caseworker/cases/views/queries.py b/caseworker/cases/views/queries.py index a0840ec09e..6522244c5d 100644 --- a/caseworker/cases/views/queries.py +++ b/caseworker/cases/views/queries.py @@ -53,6 +53,7 @@ def get_context_data(self, *args, **kwargs): if not query: raise Http404 + context["title"] = "Close query" context["query"] = query return context From 2511d19b2b61282d20f398d33d9393e63da6887d Mon Sep 17 00:00:00 2001 From: Stuart Axon Date: Thu, 8 Feb 2024 16:57:53 +0000 Subject: [PATCH 11/15] Set bottom margin of close query button to 0. --- caseworker/cases/forms/queries.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/caseworker/cases/forms/queries.py b/caseworker/cases/forms/queries.py index 74f584b58d..8378bd26d4 100644 --- a/caseworker/cases/forms/queries.py +++ b/caseworker/cases/forms/queries.py @@ -14,4 +14,6 @@ class CloseQueryForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() - self.helper.layout = Layout("reason_for_closing_query", Button("submit", "Submit")) + self.helper.layout = Layout( + "reason_for_closing_query", Button("submit", "Submit", css_class="govuk-!-margin-bottom-0") + ) From ddc6755e4204ee45b8e3b040ec8a20bd3d7e5936 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Fri, 9 Feb 2024 11:21:15 +0000 Subject: [PATCH 12/15] Use url tag to specify location in template --- exporter/templates/layouts/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/templates/layouts/base.html b/exporter/templates/layouts/base.html index 6b1a85c0ef..ba52aefbd7 100644 --- a/exporter/templates/layouts/base.html +++ b/exporter/templates/layouts/base.html @@ -121,7 +121,7 @@

      Support links

      {% endif %} From 171d8240e12b720dbe8e26813509899eff1b9347 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Fri, 9 Feb 2024 12:30:20 +0000 Subject: [PATCH 13/15] Add UI test for caseworker manually closing a query with response --- .../caseworker/features/ecju_queries.feature | 17 +++++++++++++++++ ui_tests/caseworker/pages/ecju_queries_pages.py | 10 ++++++++++ .../caseworker/step_defs/test_ecju_queries.py | 13 +++++++++++++ 3 files changed, 40 insertions(+) diff --git a/ui_tests/caseworker/features/ecju_queries.feature b/ui_tests/caseworker/features/ecju_queries.feature index b34e4e1e8b..10eafe5548 100644 --- a/ui_tests/caseworker/features/ecju_queries.feature +++ b/ui_tests/caseworker/features/ecju_queries.feature @@ -22,3 +22,20 @@ Feature: I want to create ECJU queries When I go to application previously created And I click the queries tab Then I see "Some unique response" as the response under closed queries + + @caseworker_close + Scenario: Caseworker manually closing query with a response + # Caseworker creates query + Given I sign in to SSO or am signed into SSO + And I create standard application or standard application has been previously created + When I go to application previously created + And I assign myself to the case + And I click the queries tab + And I click "Send a query to the exporter" + And I enter "Provide data sheet for line item1" as the query + And I click send + Then I see "Provide data sheet for line item1" as the query under open queries + # Caseworker adds response and closes query + When I click close query to manually close the query + And I enter "required details provided by exporter" as the query response and submit + Then I see "required details provided by exporter" as the response under closed queries diff --git a/ui_tests/caseworker/pages/ecju_queries_pages.py b/ui_tests/caseworker/pages/ecju_queries_pages.py index 86c4fa2a2f..19f93d3abf 100644 --- a/ui_tests/caseworker/pages/ecju_queries_pages.py +++ b/ui_tests/caseworker/pages/ecju_queries_pages.py @@ -14,6 +14,16 @@ class EcjuQueriesPages(BasePage): def enter_question_text(self, text): self.driver.find_element(by=By.ID, value=self.TEXTAREA_QUESTION_ID).send_keys(text) + def enter_response_and_submit(self, response_text): + open_queries = self.driver.find_element(by=By.ID, value="open-queries") + element = open_queries.find_element(by=By.CLASS_NAME, value="govuk-textarea") + element.clear() + element.send_keys(response_text) + + # submit response + submit = open_queries.find_element(by=By.ID, value="id_submit") + submit.click() + def click_new_query_button(self): self.driver.find_element(by=By.ID, value=self.BUTTON_NEW_QUERY_ID).click() diff --git a/ui_tests/caseworker/step_defs/test_ecju_queries.py b/ui_tests/caseworker/step_defs/test_ecju_queries.py index 15e02ffa45..6d5a51f58f 100644 --- a/ui_tests/caseworker/step_defs/test_ecju_queries.py +++ b/ui_tests/caseworker/step_defs/test_ecju_queries.py @@ -1,6 +1,7 @@ from uuid import uuid4 from pytest_bdd import when, then, scenarios, given, parsers +from selenium.webdriver.common.by import By from ui_tests.caseworker.pages.shared import Shared from ui_tests.caseworker.pages.application_page import ApplicationPage @@ -83,3 +84,15 @@ def response_in_closed_list(driver, response, context): closed_text = EcjuQueriesPages(driver).get_closed_queries_text() assert context.ecju_question in closed_text assert response in closed_text + + +@when("I click close query to manually close the query") +def click_to_manually_close_query(driver): + open_queries = driver.find_element(by=By.ID, value="open-queries") + open_queries.find_element(by=By.CSS_SELECTOR, value=".govuk-details__summary").click() + + +@when(parsers.parse('I enter "{response}" as the query response and submit')) +def i_enter_query_response(driver, response): + ecju_queries_pages = EcjuQueriesPages(driver) + ecju_queries_pages.enter_response_and_submit(response) From 0eade2264ce23b6e40e827b3f94bfb47f5c30099 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 13 Feb 2024 11:32:51 +0000 Subject: [PATCH 14/15] Update accessibility template to address feedback - show site as a link --- core/templates/accessibility/accessibility.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/templates/accessibility/accessibility.html b/core/templates/accessibility/accessibility.html index 6e3e36bfdb..402485aa51 100644 --- a/core/templates/accessibility/accessibility.html +++ b/core/templates/accessibility/accessibility.html @@ -16,7 +16,7 @@

      - This statement applies to {{ host }} + This statement applies to {{ host }}

      This service is run by the Department for Business and Trade (DBT). It is currently in private beta @@ -84,7 +84,7 @@

      Content that’s not within the scope of the accessi

      What we're doing to improve accessibility

      - We will schedule another accessibility audit in late 2024 to identify any issues that do not meet + We will schedule another accessibility audit in 2024 to identify any issues that do not meet the WCAG 2.2. success criteria.

      From 339427c1cc639a0dc4596a37e0c8820c71fd1b98 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Wed, 14 Feb 2024 09:24:57 +0000 Subject: [PATCH 15/15] Correct licences spelling in Privacy notice as per feedback --- exporter/templates/core/privacy_notice.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter/templates/core/privacy_notice.html b/exporter/templates/core/privacy_notice.html index 4efb65f8cd..0f75f797eb 100644 --- a/exporter/templates/core/privacy_notice.html +++ b/exporter/templates/core/privacy_notice.html @@ -39,7 +39,7 @@

      Purpose of privacy notice

      - This online service is for applying for export licenses and clearances, related to goods that + This online service is for applying for export licences and clearances, related to goods that require government permission to be exported from the UK or traded between countries.

      @@ -194,7 +194,7 @@

      Contact us

      You have a right to complain to us if you think we have not complied with our obligation for handling your personal information. You - can contact our Data Protection Officer using the same contact. + can contact our Data Protection Officer using the same contact details.

      Contact the Information Commissioner’s Office