Skip to content

Commit 7df895a

Browse files
authored
Merge pull request #943 from NHSDigital/DTOSS-11825-record-images-taken
Record images taken (are the images standard or not)
2 parents d451701 + 229a4e5 commit 7df895a

File tree

23 files changed

+447
-58
lines changed

23 files changed

+447
-58
lines changed

manage_breast_screening/mammograms/forms/images/__init__.py

Whitespace-only changes.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from django.db.models import TextChoices
2+
from django.forms import Form
3+
4+
from manage_breast_screening.nhsuk_forms.fields.choice_fields import ChoiceField
5+
6+
7+
class RecordImagesTakenForm(Form):
8+
class StandardImagesChoices(TextChoices):
9+
YES_TWO_CC_AND_TWO_MLO = "YES_TWO_CC_AND_TWO_MLO", "Yes, 2 CC and 2 MLO"
10+
NO_ADD_ADDITIONAL = (
11+
"NO_ADD_ADDITIONAL",
12+
"No, add other information",
13+
)
14+
NO_IMAGES_TAKEN = "NO_IMAGES_TAKEN", "No images taken"
15+
16+
standard_images = ChoiceField(
17+
choices=StandardImagesChoices,
18+
required=True,
19+
choice_hints={
20+
StandardImagesChoices.NO_ADD_ADDITIONAL: "Such as too few or additional images",
21+
StandardImagesChoices.NO_IMAGES_TAKEN: "The appointment cannot proceed",
22+
},
23+
label="Have you taken a standard set of images?",
24+
error_messages={
25+
"required": "Select whether you have taken a standard set of images or not"
26+
},
27+
)
28+
29+
def save(self, study_service):
30+
if (
31+
self.cleaned_data["standard_images"]
32+
== self.StandardImagesChoices.YES_TWO_CC_AND_TWO_MLO
33+
):
34+
study_service.create_with_default_series()
35+
else:
36+
study_service.remove_existing_study_and_series()

manage_breast_screening/mammograms/jinja2/mammograms/awaiting_images.jinja

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{% extends "workflow_step.jinja" %}
2+
3+
{% set active_workflow_step = 'TAKE_IMAGES' %}
4+
5+
{% block form %}
6+
{% do form.standard_images.add_divider_after("NO_ADD_ADDITIONAL", "or") %}
7+
{{ form.standard_images.as_field_group() }}
8+
{% endblock %}

manage_breast_screening/mammograms/presenters/appointment_presenters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def workflow_steps(self, active_workflow_step):
9292
case AppointmentWorkflowStepCompletion.StepNames.REVIEW_MEDICAL_INFORMATION:
9393
view_name = "record_medical_information"
9494
case AppointmentWorkflowStepCompletion.StepNames.TAKE_IMAGES:
95-
view_name = "awaiting_images"
95+
view_name = "take_images"
9696
case AppointmentWorkflowStepCompletion.StepNames.CHECK_INFORMATION:
9797
view_name = "check_information"
9898

manage_breast_screening/mammograms/tests/forms/images/__init__.py

Whitespace-only changes.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from unittest.mock import MagicMock
2+
from urllib.parse import urlencode
3+
4+
import pytest
5+
from django.http import QueryDict
6+
7+
from manage_breast_screening.mammograms.forms.images.record_images_taken_form import (
8+
RecordImagesTakenForm,
9+
)
10+
from manage_breast_screening.manual_images.services import StudyService
11+
12+
13+
@pytest.fixture
14+
def mock_study_service():
15+
return MagicMock(spec=StudyService)
16+
17+
18+
def test_invalid_form():
19+
form = RecordImagesTakenForm(QueryDict())
20+
assert not form.is_valid()
21+
assert form.errors == {
22+
"standard_images": [
23+
"Select whether you have taken a standard set of images or not"
24+
]
25+
}
26+
27+
28+
def test_valid_form():
29+
form = RecordImagesTakenForm(
30+
QueryDict(
31+
urlencode(
32+
{
33+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.YES_TWO_CC_AND_TWO_MLO
34+
}
35+
)
36+
)
37+
)
38+
assert form.is_valid()
39+
40+
41+
def test_save_with_yes_answer(mock_study_service):
42+
form = RecordImagesTakenForm(
43+
QueryDict(
44+
urlencode(
45+
{
46+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.YES_TWO_CC_AND_TWO_MLO
47+
}
48+
)
49+
)
50+
)
51+
form.is_valid()
52+
form.save(mock_study_service)
53+
54+
mock_study_service.create_with_default_series.assert_called_once()
55+
56+
57+
def test_save_with_no_answer(mock_study_service):
58+
form = RecordImagesTakenForm(
59+
QueryDict(
60+
urlencode(
61+
{
62+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.NO_ADD_ADDITIONAL
63+
}
64+
)
65+
)
66+
)
67+
form.is_valid()
68+
form.save(mock_study_service)
69+
70+
mock_study_service.remove_existing_study_and_series.assert_called_once()

manage_breast_screening/mammograms/tests/presenters/test_appointment_presenters.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ def test_workflow_steps_confirm_identity(self, mock_appointment):
368368
"current": False,
369369
"disabled": True,
370370
"classes": "app-workflow-side-nav__item app-workflow-side-nav__item--disabled",
371-
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/awaiting-images/",
371+
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/take-images/",
372372
},
373373
{
374374
"label": "Check information",
@@ -412,7 +412,7 @@ def test_workflow_steps_review_medical_information(self, mock_appointment):
412412
"current": False,
413413
"disabled": True,
414414
"classes": "app-workflow-side-nav__item app-workflow-side-nav__item--disabled",
415-
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/awaiting-images/",
415+
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/take-images/",
416416
},
417417
{
418418
"label": "Check information",
@@ -455,7 +455,7 @@ def test_workflow_steps_take_images(self, mock_appointment):
455455
"current": True,
456456
"disabled": False,
457457
"classes": "app-workflow-side-nav__item app-workflow-side-nav__item--current",
458-
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/awaiting-images/",
458+
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/take-images/",
459459
},
460460
{
461461
"label": "Check information",
@@ -501,7 +501,7 @@ def test_workflow_steps_check_information(self, mock_appointment):
501501
"current": False,
502502
"disabled": False,
503503
"classes": "app-workflow-side-nav__item app-workflow-side-nav__item--completed",
504-
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/awaiting-images/",
504+
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/take-images/",
505505
},
506506
{
507507
"label": "Check information",
@@ -549,7 +549,7 @@ def test_workflow_steps_on_review_medical_information_when_already_reviewed(
549549
"current": False,
550550
"disabled": False,
551551
"classes": "app-workflow-side-nav__item",
552-
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/awaiting-images/",
552+
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/take-images/",
553553
},
554554
{
555555
"label": "Check information",
@@ -597,7 +597,7 @@ def test_workflow_steps_on_confirm_identity_when_already_taken_images(
597597
"current": False,
598598
"disabled": False,
599599
"classes": "app-workflow-side-nav__item app-workflow-side-nav__item--completed",
600-
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/awaiting-images/",
600+
"url": "/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/take-images/",
601601
},
602602
{
603603
"label": "Check information",

manage_breast_screening/mammograms/tests/views/test_appointment_views.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
from manage_breast_screening.config.settings import LOGIN_URL
66
from manage_breast_screening.core.models import AuditLog
7+
from manage_breast_screening.mammograms.forms.images.record_images_taken_form import (
8+
RecordImagesTakenForm,
9+
)
710
from manage_breast_screening.participants.models import MedicalInformationReview
811
from manage_breast_screening.participants.models.appointment import (
912
AppointmentWorkflowStepCompletion,
@@ -117,6 +120,100 @@ def test_records_completion(self, clinical_user_client):
117120
)
118121

119122

123+
@pytest.mark.django_db
124+
class TestTakeImages:
125+
def test_renders_response(self, clinical_user_client, appointment):
126+
response = clinical_user_client.http.get(
127+
reverse(
128+
"mammograms:take_images",
129+
kwargs={"pk": appointment.pk},
130+
)
131+
)
132+
assert response.status_code == 200
133+
134+
def test_no_images_redirects_to_cannot_continue(
135+
self, clinical_user_client, appointment
136+
):
137+
response = clinical_user_client.http.post(
138+
reverse(
139+
"mammograms:take_images",
140+
kwargs={"pk": appointment.pk},
141+
),
142+
{
143+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.NO_IMAGES_TAKEN
144+
},
145+
)
146+
assertRedirects(
147+
response,
148+
reverse(
149+
"mammograms:appointment_cannot_go_ahead", kwargs={"pk": appointment.pk}
150+
),
151+
)
152+
153+
@pytest.mark.xfail(reason="The additional details view is not implemented yet")
154+
def test_additional_info_redirects_to_additional_details(
155+
self, clinical_user_client, appointment
156+
):
157+
response = clinical_user_client.http.post(
158+
reverse(
159+
"mammograms:take_images",
160+
kwargs={"pk": appointment.pk},
161+
),
162+
{
163+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.NO_ADD_ADDITIONAL
164+
},
165+
)
166+
assertRedirects(
167+
response,
168+
reverse(
169+
"mammograms:additional_image_details", kwargs={"pk": appointment.pk}
170+
),
171+
)
172+
173+
def test_yes_marks_the_step_complete_and_redirects_to_check_info(
174+
self, clinical_user_client, appointment
175+
):
176+
response = clinical_user_client.http.post(
177+
reverse(
178+
"mammograms:take_images",
179+
kwargs={"pk": appointment.pk},
180+
),
181+
{
182+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.YES_TWO_CC_AND_TWO_MLO
183+
},
184+
)
185+
assertRedirects(
186+
response,
187+
reverse("mammograms:check_information", kwargs={"pk": appointment.pk}),
188+
)
189+
assertQuerySetEqual(
190+
appointment.completed_workflow_steps.filter(
191+
created_by=clinical_user_client.user
192+
)
193+
.values_list("step_name", flat=True)
194+
.distinct(),
195+
[AppointmentWorkflowStepCompletion.StepNames.TAKE_IMAGES],
196+
)
197+
198+
def test_yes_creates_the_study(self, clinical_user_client, appointment):
199+
clinical_user_client.http.post(
200+
reverse(
201+
"mammograms:take_images",
202+
kwargs={"pk": appointment.pk},
203+
),
204+
{
205+
"standard_images": RecordImagesTakenForm.StandardImagesChoices.YES_TWO_CC_AND_TWO_MLO
206+
},
207+
)
208+
assertQuerySetEqual(
209+
appointment.study.series_set.values_list(
210+
"view_position", "laterality", "count"
211+
),
212+
{("CC", "L", 1), ("CC", "R", 1), ("MLO", "L", 1), ("MLO", "R", 1)},
213+
ordered=False,
214+
)
215+
216+
120217
@pytest.mark.django_db
121218
class TestCheckIn:
122219
def test_known_redirect(self, clinical_user_client):

manage_breast_screening/mammograms/urls.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.urls import path
2+
from django.views.decorators.http import require_http_methods
23

34
from manage_breast_screening.mammograms.views import mammogram_views
45

@@ -21,6 +22,12 @@
2122

2223
app_name = "mammograms"
2324

25+
26+
@require_http_methods(["GET"])
27+
def not_implemented_view(request, pk):
28+
raise NotImplementedError()
29+
30+
2431
urlpatterns = [
2532
path(
2633
"<uuid:pk>/check-in/",
@@ -68,9 +75,9 @@
6875
name="mark_section_reviewed",
6976
),
7077
path(
71-
"<uuid:pk>/awaiting-images/",
72-
appointment_views.AwaitingImages.as_view(),
73-
name="awaiting_images",
78+
"<uuid:pk>/take-images/",
79+
appointment_views.TakeImages.as_view(),
80+
name="take_images",
7481
),
7582
path(
7683
"<uuid:pk>/cannot-go-ahead/",
@@ -282,6 +289,11 @@
282289
mammogram_views.check_information,
283290
name="check_information",
284291
),
292+
path(
293+
"<uuid:pk>/image-details/new",
294+
not_implemented_view,
295+
name="new_image_details",
296+
),
285297
path(
286298
"<uuid:pk>/complete-screening/",
287299
mammogram_views.complete_screening,

0 commit comments

Comments
 (0)