Skip to content

Commit 59e51f9

Browse files
authored
Merge pull request #941 from NHSDigital/DTOSS-12063-complete-screening
Add submit button to check information page
2 parents 5300394 + 3b5d122 commit 59e51f9

File tree

5 files changed

+236
-8
lines changed

5 files changed

+236
-8
lines changed

manage_breast_screening/mammograms/jinja2/mammograms/check_information.jinja

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,15 @@
33
{% set active_workflow_step = 'CHECK_INFORMATION' %}
44

55
{% block step_content %}
6+
<p>Before concluding this appointment, confirm that the information recorded is correct.</p>
7+
{% endblock %}
68

9+
{% block wizard_form %}
10+
<form action="{{ url('mammograms:complete_screening', kwargs={'pk': presented_appointment.pk}) }}" method="post" novalidate>
11+
{{ csrf_input }}
12+
{{ button({
13+
"text": "Complete screening and return to clinic",
14+
"classes": "nhsuk-u-margin-bottom-4"
15+
}) }}
16+
</form>
717
{% endblock %}

manage_breast_screening/mammograms/tests/views/test_participant_reported_mammogram_views.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@
44
from dateutil.relativedelta import relativedelta
55
from django.contrib import messages
66
from django.urls import reverse
7-
from pytest_django.asserts import assertInHTML, assertMessages, assertRedirects
7+
from pytest_django.asserts import (
8+
assertInHTML,
9+
assertMessages,
10+
assertQuerySetEqual,
11+
assertRedirects,
12+
)
813

914
from manage_breast_screening.participants.forms import ParticipantReportedMammogramForm
1015
from manage_breast_screening.participants.models import ParticipantReportedMammogram
1116
from manage_breast_screening.participants.models.appointment import (
1217
AppointmentStatusNames,
18+
AppointmentWorkflowStepCompletion,
1319
)
1420
from manage_breast_screening.participants.tests.factories import (
1521
AppointmentFactory,
22+
ParticipantFactory,
1623
ParticipantReportedMammogramFactory,
1724
)
1825

@@ -471,3 +478,70 @@ def test_valid_post_redirects_to_appointment(
471478
),
472479
)
473480
assert_success_message(response, "Updated a previous mammogram")
481+
482+
483+
@pytest.mark.django_db
484+
class TestCompleteScreening:
485+
def test_renders_response(self, clinical_user_client, appointment):
486+
response = clinical_user_client.http.get(
487+
reverse(
488+
"mammograms:check_information",
489+
kwargs={
490+
"pk": appointment.pk,
491+
},
492+
)
493+
)
494+
assert response.status_code == 200
495+
496+
def test_valid_transition(self, clinical_user_client):
497+
participant = ParticipantFactory.create(
498+
first_name="<b>J</b>ane", last_name="S<i>m</>i&th"
499+
)
500+
appointment = AppointmentFactory.create(
501+
screening_episode__participant=participant,
502+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
503+
current_status=AppointmentStatusNames.IN_PROGRESS,
504+
)
505+
506+
response = clinical_user_client.http.post(
507+
reverse(
508+
"mammograms:complete_screening",
509+
kwargs={
510+
"pk": appointment.pk,
511+
},
512+
),
513+
)
514+
assertRedirects(
515+
response,
516+
reverse(
517+
"clinics:show",
518+
kwargs={"pk": appointment.clinic_slot.clinic.pk},
519+
),
520+
)
521+
view_appointment_url = reverse(
522+
"mammograms:show_appointment",
523+
kwargs={
524+
"pk": appointment.pk,
525+
},
526+
)
527+
assert_success_message(
528+
response,
529+
f"""
530+
<p class=\"nhsuk-notification-banner__heading\">
531+
&lt;b&gt;J&lt;/b&gt;ane S&lt;i&gt;m&lt;/&gt;i&amp;th has been screened.
532+
<a href=\"{view_appointment_url}\" class=\"app-u-nowrap\">
533+
View their appointment
534+
</a>
535+
</p>
536+
""",
537+
)
538+
539+
assert appointment.current_status.name == AppointmentStatusNames.SCREENED
540+
assertQuerySetEqual(
541+
appointment.completed_workflow_steps.filter(
542+
created_by=clinical_user_client.user
543+
)
544+
.values_list("step_name", flat=True)
545+
.distinct(),
546+
[AppointmentWorkflowStepCompletion.StepNames.CHECK_INFORMATION],
547+
)

manage_breast_screening/mammograms/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,9 @@
282282
mammogram_views.check_information,
283283
name="check_information",
284284
),
285+
path(
286+
"<uuid:pk>/complete-screening/",
287+
mammogram_views.complete_screening,
288+
name="complete_screening",
289+
),
285290
]

manage_breast_screening/mammograms/views/mammogram_views.py

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import logging
22

3+
from django.contrib import messages
34
from django.contrib.auth.decorators import permission_required
45
from django.http import Http404
56
from django.shortcuts import redirect, render
67
from django.urls import reverse
8+
from django.utils.html import escape
9+
from django.utils.safestring import mark_safe
710
from django.views.decorators.http import require_http_methods
811
from rules.contrib.views import PermissionRequiredMixin
912

@@ -18,11 +21,16 @@
1821
)
1922
from manage_breast_screening.mammograms.views.mixins import AppointmentMixin
2023
from manage_breast_screening.participants.models import ParticipantReportedMammogram
21-
from manage_breast_screening.participants.models.appointment import Appointment
24+
from manage_breast_screening.participants.models.appointment import (
25+
Appointment,
26+
AppointmentWorkflowStepCompletion,
27+
)
2228
from manage_breast_screening.participants.views import parse_return_url
2329

2430
from ..forms.appointment_proceed_anyway_form import AppointmentProceedAnywayForm
2531

32+
APPOINTMENT_NOT_FOUND = "Appointment not found"
33+
2634
logger = logging.getLogger(__name__)
2735

2836

@@ -38,7 +46,7 @@ def appointment_should_not_proceed(
3846
"screening_episode__participant__address",
3947
).get(pk=appointment_pk)
4048
except Appointment.DoesNotExist:
41-
raise Http404("Appointment not found")
49+
raise Http404(APPOINTMENT_NOT_FOUND)
4250

4351
try:
4452
mammogram = appointment.reported_mammograms.get(
@@ -95,7 +103,7 @@ def attended_not_screened(request, appointment_pk):
95103
try:
96104
appointment = provider.appointments.get(pk=appointment_pk)
97105
except Appointment.DoesNotExist:
98-
raise Http404("Appointment not found")
106+
raise Http404(APPOINTMENT_NOT_FOUND)
99107

100108
AppointmentStatusUpdater(
101109
appointment, current_user=request.user
@@ -174,19 +182,67 @@ def get_context_data(self, **kwargs):
174182

175183

176184
@require_http_methods(["GET"])
185+
@permission_required(Permission.DO_MAMMOGRAM_APPOINTMENT)
177186
def check_information(request, pk):
178187
provider = request.user.current_provider
179-
appointment = provider.appointments.select_related(
180-
"screening_episode__participant",
181-
).get(pk=pk)
188+
try:
189+
appointment = provider.appointments.select_related(
190+
"screening_episode__participant",
191+
).get(pk=pk)
192+
except Appointment.DoesNotExist:
193+
raise Http404(APPOINTMENT_NOT_FOUND)
182194

183195
return render(
184196
request,
185197
"mammograms/check_information.jinja",
186198
context={
187-
"caption": appointment.screening_episode.participant.full_name,
188199
"page_title": "Check information",
189200
"heading": "Check information",
190201
"presented_appointment": AppointmentPresenter(appointment),
191202
},
192203
)
204+
205+
206+
@require_http_methods(["POST"])
207+
@permission_required(Permission.DO_MAMMOGRAM_APPOINTMENT)
208+
def complete_screening(request, pk):
209+
provider = request.user.current_provider
210+
try:
211+
appointment = provider.appointments.select_related(
212+
"clinic_slot__clinic",
213+
"screening_episode__participant",
214+
).get(pk=pk)
215+
except Appointment.DoesNotExist:
216+
raise Http404(APPOINTMENT_NOT_FOUND)
217+
218+
AppointmentStatusUpdater(
219+
appointment=appointment, current_user=request.user
220+
).screen()
221+
appointment.completed_workflow_steps.create(
222+
step_name=AppointmentWorkflowStepCompletion.StepNames.CHECK_INFORMATION,
223+
created_by=request.user,
224+
)
225+
226+
view_appointment_url = reverse(
227+
"mammograms:show_appointment",
228+
kwargs={
229+
"pk": appointment.pk,
230+
},
231+
)
232+
escaped_full_name = escape(appointment.screening_episode.participant.full_name)
233+
messages.add_message(
234+
request,
235+
messages.SUCCESS,
236+
mark_safe(
237+
f"""
238+
<p class=\"nhsuk-notification-banner__heading\">
239+
{escaped_full_name} has been screened.
240+
<a href=\"{view_appointment_url}\" class=\"app-u-nowrap\">
241+
View their appointment
242+
</a>
243+
</p>
244+
"""
245+
),
246+
)
247+
248+
return redirect("clinics:show", pk=appointment.clinic_slot.clinic.pk)
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import re
2+
from datetime import datetime, timezone
3+
4+
import pytest
5+
from django.urls import reverse
6+
from playwright.sync_api import expect
7+
8+
from manage_breast_screening.clinics.models import Clinic
9+
from manage_breast_screening.clinics.tests.factories import ClinicFactory
10+
from manage_breast_screening.participants.models.appointment import (
11+
AppointmentStatusNames,
12+
)
13+
from manage_breast_screening.participants.tests.factories import AppointmentFactory
14+
15+
from ..system_test_setup import SystemTestCase
16+
17+
18+
class TestCheckInformation(SystemTestCase):
19+
@pytest.fixture(autouse=True)
20+
def before(self):
21+
today = datetime.now(timezone.utc).replace(hour=9, minute=0)
22+
self.clinic_start_time = today
23+
24+
def test_check_information(self):
25+
self.given_i_am_logged_in_as_a_clinical_user()
26+
self.and_there_is_a_clinic_exists_that_is_run_by_my_provider()
27+
self.and_there_is_an_appointment_for_the_clinic()
28+
self.and_i_am_on_the_check_information_page()
29+
30+
self.and_i_click_on_complete_screening()
31+
self.then_i_should_be_on_the_clinic_page()
32+
self.and_the_message_says_image_details_added()
33+
34+
def test_accessibility(self):
35+
self.given_i_am_logged_in_as_a_clinical_user()
36+
self.and_there_is_a_clinic_exists_that_is_run_by_my_provider()
37+
self.and_there_is_an_appointment_for_the_clinic()
38+
self.and_i_am_on_the_check_information_page()
39+
self.then_the_accessibility_baseline_is_met()
40+
41+
def and_there_is_a_clinic_exists_that_is_run_by_my_provider(self):
42+
user_assignment = self.current_user.assignments.first()
43+
self.clinic = ClinicFactory(
44+
starts_at=self.clinic_start_time,
45+
setting__name="West London BSS",
46+
setting__provider=user_assignment.provider,
47+
risk_type=Clinic.RiskType.ROUTINE_RISK,
48+
)
49+
50+
def and_there_is_an_appointment_for_the_clinic(self):
51+
self.appointment = AppointmentFactory(
52+
clinic_slot__clinic=self.clinic,
53+
clinic_slot__clinic__setting__provider=self.current_provider,
54+
current_status=AppointmentStatusNames.IN_PROGRESS,
55+
)
56+
57+
def and_i_am_on_the_check_information_page(self):
58+
self.page.goto(
59+
self.live_server_url
60+
+ reverse(
61+
"mammograms:check_information",
62+
kwargs={"pk": self.appointment.pk},
63+
)
64+
)
65+
self.expect_url("mammograms:check_information", pk=self.appointment.pk)
66+
67+
def and_i_click_on_complete_screening(self):
68+
self.page.get_by_text("Complete screening and return to clinic").click()
69+
70+
def then_i_should_be_on_the_clinic_page(self):
71+
path = reverse(
72+
"clinics:show",
73+
kwargs={"pk": self.clinic.pk},
74+
)
75+
expect(self.page).to_have_url(re.compile(path))
76+
self.assert_page_title_contains("Routine risk screening clinic")
77+
78+
def and_the_message_says_image_details_added(self):
79+
alert = self.page.get_by_role("alert")
80+
expect(alert).to_contain_text("Success")
81+
expect(alert).to_contain_text(
82+
f"{self.appointment.participant.full_name} has been screened"
83+
)

0 commit comments

Comments
 (0)