Skip to content

Commit d49da1d

Browse files
authored
Merge pull request #1181 from NHSDigital/DTOSS-124560-note-form
Appointment note page
2 parents 85f3461 + 5edee6a commit d49da1d

7 files changed

Lines changed: 315 additions & 39 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{% extends "layout-form.jinja" %}
2+
{% from 'nhsuk/components/button/macro.jinja' import button %}
3+
{% from 'nhsuk/components/inset-text/macro.jinja' import insetText %}
4+
5+
{% block form %}
6+
{% set inset_html %}
7+
<p>
8+
If adjustments are required,
9+
<a href="{{ presented_appointment.special_appointment_url }}?return_url={{ return_url }}" class="nhsuk-link nhsuk-link--no-visited-state">
10+
provide special appointment details instead
11+
</a>
12+
</p>
13+
{% endset %}
14+
{{ insetText({
15+
"html": inset_html
16+
}) }}
17+
18+
<input type="hidden" name="return_url" value="{{ return_url }}">
19+
{{ form.content.as_field_group() }}
20+
21+
<div class="nhsuk-button-group">
22+
{{ button({
23+
"text": "Save note"
24+
}) }}
25+
{% if form.instance_is_saved %}
26+
<p>
27+
<a href="{{ url('mammograms:delete_appointment_note', kwargs={'pk': presented_appointment.pk}) }}?return_url={{ return_url}}" class="nhsuk-link nhsuk-link--no-visited-state app-link--warning">
28+
Delete appointment note
29+
</a>
30+
</p>
31+
{% endif %}
32+
</div>
33+
{% endblock %}

manage_breast_screening/mammograms/presenters/appointment_presenters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def special_appointment_url(self):
6363
def appointment_note_url(self, return_url):
6464
return (
6565
reverse(
66-
"mammograms:appointment_note",
66+
"mammograms:appointment_note_review",
6767
kwargs={"pk": self._appointment.pk},
6868
)
6969
+ f"?return_url={return_url}"

manage_breast_screening/mammograms/tests/jinja2/test_appointment_details_card.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def test_appointment_details_empty(template, mock_appointment):
5454
Appointment note
5555
</dt>
5656
<dd class="nhsuk-summary-list__value">
57-
<a href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note/?return_url=" class="nhsuk-link">
57+
<a href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note-review/?return_url=" class="nhsuk-link">
5858
Enter appointment note
5959
</a>
6060
</dd>
@@ -120,7 +120,7 @@ def test_appointment_details_is_special_appointmet(template, mock_appointment):
120120
Appointment note
121121
</dt>
122122
<dd class="nhsuk-summary-list__value">
123-
<a href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note/?return_url=" class="nhsuk-link">
123+
<a href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note-review/?return_url=" class="nhsuk-link">
124124
Enter appointment note
125125
</a>
126126
</dd>
@@ -168,7 +168,7 @@ def test_appointment_details_has_appointment_note(template, mock_appointment):
168168
a note about<br>the appointment
169169
</dd>
170170
<dd class="nhsuk-summary-list__actions">
171-
<a class="nhsuk-link nhsuk-link--no-visited-state" href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note/?return_url=">
171+
<a class="nhsuk-link nhsuk-link--no-visited-state" href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note-review/?return_url=">
172172
Change<span class="nhsuk-u-visually-hidden"> appointment note</span>
173173
</a>
174174
</dd>
@@ -228,7 +228,7 @@ def test_appointment_details_special_appointment_with_note(template, mock_appoin
228228
Things to consider before &amp; during the appointment.
229229
</dd>
230230
<dd class="nhsuk-summary-list__actions">
231-
<a class="nhsuk-link nhsuk-link--no-visited-state" href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note/?return_url=">
231+
<a class="nhsuk-link nhsuk-link--no-visited-state" href="/mammograms/53ce8d3b-9e65-471a-b906-73809c0475d0/note-review/?return_url=">
232232
Change<span class="nhsuk-u-visually-hidden"> appointment note</span>
233233
</a>
234234
</dd>

manage_breast_screening/mammograms/tests/presenters/test_appointment_presenters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def test_appointment_note_action_with_note(self, mock_appointment):
279279
assert action["text"] == "Change"
280280
assert (
281281
action["href"]
282-
== "/mammograms/68d758d0-792d-430f-9c52-1e7a0c2aa1dd/note/?return_url=/return/"
282+
== "/mammograms/68d758d0-792d-430f-9c52-1e7a0c2aa1dd/note-review/?return_url=/return/"
283283
)
284284
assert action["visuallyHiddenText"] == "appointment note"
285285

manage_breast_screening/mammograms/tests/views/test_appointment_note_views.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
from django.urls import reverse
33
from pytest_django.asserts import assertRedirects
44

5+
from manage_breast_screening.core.tests.factories import UserFactory
6+
from manage_breast_screening.manual_images.tests.factories import StudyFactory
57
from manage_breast_screening.participants.models import AppointmentNote
8+
from manage_breast_screening.participants.models.appointment import (
9+
AppointmentStatusNames,
10+
)
611
from manage_breast_screening.participants.tests.factories import AppointmentFactory
712

813

@@ -101,6 +106,204 @@ def test_users_can_update_note(self, request, client_fixture):
101106
assert AppointmentNote.objects.count() == 1
102107

103108

109+
@pytest.mark.django_db
110+
class TestAppointmentNoteReviewView:
111+
def test_delete_link_not_shown_when_note_does_not_exist(
112+
self, clinical_user_client, clinical_user
113+
):
114+
appointment = AppointmentFactory.create(
115+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
116+
current_status_params={
117+
"name": AppointmentStatusNames.IN_PROGRESS,
118+
"created_by": clinical_user,
119+
},
120+
)
121+
response = clinical_user_client.http.get(
122+
reverse(
123+
"mammograms:appointment_note_review",
124+
kwargs={"pk": appointment.pk},
125+
)
126+
)
127+
assert response.status_code == 200
128+
assert "Appointment note" in response.content.decode()
129+
assert "app-status-bar" in response.content.decode()
130+
assert "Delete appointment note" not in response.content.decode()
131+
132+
def test_delete_link_shown_when_note_exists(self, clinical_user_client):
133+
appointment = AppointmentFactory.create(
134+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
135+
current_status=AppointmentStatusNames.SCHEDULED,
136+
)
137+
AppointmentNote.objects.create(appointment=appointment, content="Existing note")
138+
response = clinical_user_client.http.get(
139+
reverse(
140+
"mammograms:appointment_note_review",
141+
kwargs={"pk": appointment.pk},
142+
)
143+
)
144+
assert response.status_code == 200
145+
assert "Delete appointment note" in response.content.decode()
146+
147+
def test_users_can_save_note(self, clinical_user_client, clinical_user):
148+
appointment = AppointmentFactory.create(
149+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
150+
current_status_params={
151+
"name": AppointmentStatusNames.IN_PROGRESS,
152+
"created_by": clinical_user,
153+
},
154+
)
155+
StudyFactory.create(appointment=appointment)
156+
157+
note_content = "Participant prefers left arm blood pressure readings."
158+
response = clinical_user_client.http.post(
159+
reverse(
160+
"mammograms:appointment_note_review",
161+
kwargs={"pk": appointment.pk},
162+
),
163+
{"content": note_content},
164+
)
165+
166+
assertRedirects(
167+
response,
168+
reverse("mammograms:check_information", kwargs={"pk": appointment.pk}),
169+
)
170+
saved_note = AppointmentNote.objects.get(appointment=appointment)
171+
assert saved_note.content == note_content
172+
173+
def test_save_redirects_to_return_url(self, clinical_user_client, clinical_user):
174+
appointment = AppointmentFactory.create(
175+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
176+
current_status_params={
177+
"name": AppointmentStatusNames.IN_PROGRESS,
178+
"created_by": clinical_user,
179+
},
180+
)
181+
check_info_url = reverse(
182+
"mammograms:check_information", kwargs={"pk": appointment.pk}
183+
)
184+
response = clinical_user_client.http.post(
185+
reverse("mammograms:appointment_note_review", kwargs={"pk": appointment.pk})
186+
+ f"?return_url={check_info_url}",
187+
{"content": "Test note content"},
188+
)
189+
assertRedirects(response, check_info_url, fetch_redirect_response=False)
190+
191+
def test_users_can_update_note(self, clinical_user_client, clinical_user):
192+
appointment = AppointmentFactory.create(
193+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
194+
current_status_params={
195+
"name": AppointmentStatusNames.IN_PROGRESS,
196+
"created_by": clinical_user,
197+
},
198+
)
199+
StudyFactory.create(appointment=appointment)
200+
note = AppointmentNote.objects.create(
201+
appointment=appointment, content="Original note"
202+
)
203+
204+
updated_content = "Updated note content"
205+
response = clinical_user_client.http.post(
206+
reverse(
207+
"mammograms:appointment_note_review", kwargs={"pk": appointment.pk}
208+
),
209+
{"content": updated_content},
210+
)
211+
212+
assertRedirects(
213+
response,
214+
reverse("mammograms:check_information", kwargs={"pk": appointment.pk}),
215+
)
216+
updated_note = AppointmentNote.objects.get(pk=note.pk)
217+
assert updated_note.content == updated_content
218+
assert AppointmentNote.objects.count() == 1
219+
220+
def test_access_denied_for_administrative_users(
221+
self, administrative_user_client, clinical_user
222+
):
223+
appointment = AppointmentFactory.create(
224+
clinic_slot__clinic__setting__provider=administrative_user_client.current_provider,
225+
current_status_params={
226+
"name": AppointmentStatusNames.IN_PROGRESS,
227+
"created_by": clinical_user,
228+
},
229+
)
230+
note = AppointmentNote.objects.create(
231+
appointment=appointment, content="Original note"
232+
)
233+
234+
response = administrative_user_client.http.post(
235+
reverse(
236+
"mammograms:appointment_note_review", kwargs={"pk": appointment.pk}
237+
),
238+
{"content": "Updated note content"},
239+
)
240+
241+
assert response.status_code == 403
242+
updated_note = AppointmentNote.objects.get(pk=note.pk)
243+
assert updated_note.content == "Original note"
244+
assert AppointmentNote.objects.count() == 1
245+
246+
def test_access_denied_when_not_in_progress(
247+
self, clinical_user_client, clinical_user
248+
):
249+
appointment = AppointmentFactory.create(
250+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
251+
current_status_params={
252+
"name": AppointmentStatusNames.SCREENED,
253+
"created_by": UserFactory.create(),
254+
},
255+
)
256+
note = AppointmentNote.objects.create(
257+
appointment=appointment, content="Original note"
258+
)
259+
StudyFactory.create(appointment=appointment)
260+
261+
response = clinical_user_client.http.post(
262+
reverse(
263+
"mammograms:appointment_note_review", kwargs={"pk": appointment.pk}
264+
),
265+
{"content": "Updated note content"},
266+
)
267+
assertRedirects(
268+
response,
269+
reverse("mammograms:show_appointment", kwargs={"pk": appointment.pk}),
270+
)
271+
272+
updated_note = AppointmentNote.objects.get(pk=note.pk)
273+
assert updated_note.content == "Original note"
274+
assert AppointmentNote.objects.count() == 1
275+
276+
def test_access_denied_when_in_progress_with_another_user(
277+
self, clinical_user_client, clinical_user
278+
):
279+
appointment = AppointmentFactory.create(
280+
clinic_slot__clinic__setting__provider=clinical_user_client.current_provider,
281+
current_status_params={
282+
"name": AppointmentStatusNames.IN_PROGRESS,
283+
"created_by": UserFactory.create(),
284+
},
285+
)
286+
note = AppointmentNote.objects.create(
287+
appointment=appointment, content="Original note"
288+
)
289+
StudyFactory.create(appointment=appointment)
290+
291+
response = clinical_user_client.http.post(
292+
reverse(
293+
"mammograms:appointment_note_review", kwargs={"pk": appointment.pk}
294+
),
295+
{"content": "Updated note content"},
296+
)
297+
assertRedirects(
298+
response,
299+
reverse("mammograms:check_information", kwargs={"pk": appointment.pk}),
300+
)
301+
302+
updated_note = AppointmentNote.objects.get(pk=note.pk)
303+
assert updated_note.content == "Updated note content"
304+
assert AppointmentNote.objects.count() == 1
305+
306+
104307
@pytest.mark.django_db
105308
class TestDeleteAppointmentNoteView:
106309
def test_get_redirects_when_note_does_not_exist(self, clinical_user_client):

manage_breast_screening/mammograms/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ def not_implemented_view(request, pk):
8585
appointment_note_views.AppointmentNoteView.as_view(),
8686
name="appointment_note",
8787
),
88+
path(
89+
"<uuid:pk>/note-review/",
90+
appointment_note_views.AppointmentNoteReviewView.as_view(),
91+
name="appointment_note_review",
92+
),
8893
path(
8994
"<uuid:pk>/note/delete/",
9095
appointment_note_views.DeleteAppointmentNoteView.as_view(),

0 commit comments

Comments
 (0)