Skip to content

Commit 9655825

Browse files
authored
Merge pull request #778 from NHSDigital/11529-update-benign-lumps
Medical history — update benign lumps history
2 parents 3c42f05 + 936b5d0 commit 9655825

File tree

8 files changed

+312
-25
lines changed

8 files changed

+312
-25
lines changed

manage_breast_screening/mammograms/forms/benign_lump_history_item_form.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,33 @@ class BenignLumpHistoryItemForm(FormWithConditionalFields):
105105
)
106106

107107
def __init__(self, *args, **kwargs):
108+
self.instance = kwargs.pop("instance", None)
109+
110+
if self.instance:
111+
kwargs["initial"] = self.initial_values(self.instance)
112+
108113
super().__init__(*args, **kwargs)
109114

110115
for location, detail_field in self.LOCATION_DETAIL_FIELDS.items():
111116
self.given_field_value("procedure_location", location).require_field(
112117
detail_field
113118
)
114119

120+
def initial_values(self, instance):
121+
initial = {
122+
"left_breast_procedures": instance.left_breast_procedures,
123+
"right_breast_procedures": instance.right_breast_procedures,
124+
"procedure_year": instance.procedure_year,
125+
"procedure_location": instance.procedure_location,
126+
"additional_details": instance.additional_details,
127+
}
128+
129+
detail_field = self.LOCATION_DETAIL_FIELDS.get(instance.procedure_location)
130+
if detail_field:
131+
initial[detail_field] = instance.procedure_location_details
132+
133+
return initial
134+
115135
def create(self, appointment, request):
116136
auditor = Auditor.from_request(request)
117137

@@ -131,6 +151,27 @@ def create(self, appointment, request):
131151

132152
return benign_lump_history_item
133153

154+
def update(self, request):
155+
auditor = Auditor.from_request(request)
156+
157+
self.instance.left_breast_procedures = self.cleaned_data.get(
158+
"left_breast_procedures", []
159+
)
160+
self.instance.right_breast_procedures = self.cleaned_data.get(
161+
"right_breast_procedures", []
162+
)
163+
self.instance.procedure_year = self.cleaned_data.get("procedure_year")
164+
self.instance.procedure_location = self.cleaned_data["procedure_location"]
165+
self.instance.procedure_location_details = self._get_selected_location_details()
166+
self.instance.additional_details = self.cleaned_data.get(
167+
"additional_details", ""
168+
)
169+
170+
self.instance.save()
171+
auditor.audit_update(self.instance)
172+
173+
return self.instance
174+
134175
@property
135176
def location_detail_fields(self):
136177
return tuple(self.LOCATION_DETAIL_FIELDS.items())

manage_breast_screening/mammograms/jinja2/mammograms/record_medical_information.jinja

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
{% set benign_lump_history_html %}
9696
{% for presented_item in presenter.benign_lump_history %}
9797
{{ summaryList(presented_item.summary_list_params) }}
98+
<p><a href="{{ presented_item.change_link.href }}" class="nhsuk-link nhsuk-link--no-visited-state">{{ presented_item.change_link.text }}</a></p>
9899
{% endfor %}
99100
<a href="{{ presenter.add_benign_lump_history_link.href }}" class="nhsuk-link nhsuk-link--no-visited-state">{{ presenter.add_benign_lump_history_link.text }}</a><br>
100101
{% endset %}

manage_breast_screening/mammograms/presenters/benign_lump_history_item_presenter.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from django.urls import reverse
2+
13
from manage_breast_screening.core.template_helpers import multiline_content, nl2br
24
from manage_breast_screening.participants.models.benign_lump_history_item import (
35
BenignLumpHistoryItem,
@@ -20,7 +22,6 @@ def __init__(self, benign_lump_history_item):
2022

2123
@property
2224
def summary_list_params(self):
23-
# This is a placeholder until we have a properly formatted table.
2425
return {
2526
"rows": [
2627
{
@@ -48,7 +49,20 @@ def summary_list_params(self):
4849
"key": {"text": "Additional details"},
4950
"value": {"html": self.additional_details},
5051
},
51-
],
52+
]
53+
}
54+
55+
@property
56+
def change_link(self):
57+
return {
58+
"href": reverse(
59+
"mammograms:change_benign_lump_history_item",
60+
kwargs={
61+
"pk": self._item.appointment_id,
62+
"history_item_pk": self._item.id,
63+
},
64+
),
65+
"text": "Change",
5266
}
5367

5468
def _format_multiple_choices(self, choices, ChoiceClass):

manage_breast_screening/mammograms/tests/forms/test_benign_lump_history_item_form.py

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
from django.http import QueryDict
66
from django.test import RequestFactory
77

8-
from manage_breast_screening.core.models import AuditLog
98
from manage_breast_screening.mammograms.forms.benign_lump_history_item_form import (
109
BenignLumpHistoryItemForm,
1110
)
1211
from manage_breast_screening.participants.models.benign_lump_history_item import (
1312
BenignLumpHistoryItem,
1413
)
15-
from manage_breast_screening.participants.tests.factories import AppointmentFactory
14+
from manage_breast_screening.participants.tests.factories import (
15+
AppointmentFactory,
16+
BenignLumpHistoryItemFactory,
17+
)
1618

1719

1820
def _form_data(data):
@@ -85,7 +87,7 @@ def test_procedure_year_must_be_within_range(
8587
assert not form.is_valid()
8688
assert form.errors.get("procedure_year") == [expected_message]
8789

88-
def test_create_persists_data_and_audits(self, clinical_user):
90+
def test_create_persists_data(self, clinical_user):
8991
appointment = AppointmentFactory()
9092
request = RequestFactory().post("/test-form")
9193
request.user = clinical_user
@@ -110,13 +112,7 @@ def test_create_persists_data_and_audits(self, clinical_user):
110112
form = BenignLumpHistoryItemForm(_form_data(data))
111113
assert form.is_valid()
112114

113-
existing_log_count = AuditLog.objects.count()
114115
obj = form.create(appointment=appointment, request=request)
115-
assert AuditLog.objects.count() == existing_log_count + 1
116-
audit_log = AuditLog.objects.filter(
117-
object_id=obj.pk, operation=AuditLog.Operations.CREATE
118-
).first()
119-
assert audit_log.actor == clinical_user
120116

121117
obj.refresh_from_db()
122118
assert obj.appointment == appointment
@@ -132,3 +128,75 @@ def test_create_persists_data_and_audits(self, clinical_user):
132128
)
133129
assert obj.procedure_location_details == "St Thomas' Hospital"
134130
assert obj.additional_details == "Additional details."
131+
132+
def test_initial_values_populated_from_instance(self):
133+
instance = BenignLumpHistoryItemFactory(
134+
left_breast_procedures=[
135+
BenignLumpHistoryItem.Procedure.NEEDLE_BIOPSY,
136+
BenignLumpHistoryItem.Procedure.LUMP_REMOVED,
137+
],
138+
right_breast_procedures=[BenignLumpHistoryItem.Procedure.NO_PROCEDURES],
139+
procedure_year=2020,
140+
procedure_location=BenignLumpHistoryItem.ProcedureLocation.OUTSIDE_UK,
141+
procedure_location_details="Hospital in France",
142+
additional_details="Some additional notes",
143+
)
144+
145+
form = BenignLumpHistoryItemForm(instance=instance)
146+
147+
assert form.initial["left_breast_procedures"] == [
148+
BenignLumpHistoryItem.Procedure.NEEDLE_BIOPSY,
149+
BenignLumpHistoryItem.Procedure.LUMP_REMOVED,
150+
]
151+
assert form.initial["right_breast_procedures"] == [
152+
BenignLumpHistoryItem.Procedure.NO_PROCEDURES
153+
]
154+
assert form.initial["procedure_year"] == 2020
155+
assert form.initial["procedure_location"] == (
156+
BenignLumpHistoryItem.ProcedureLocation.OUTSIDE_UK
157+
)
158+
assert form.initial["outside_uk_details"] == "Hospital in France"
159+
assert form.initial["additional_details"] == "Some additional notes"
160+
161+
def test_update_persists_changes(self, clinical_user):
162+
instance = BenignLumpHistoryItemFactory(
163+
left_breast_procedures=[BenignLumpHistoryItem.Procedure.NEEDLE_BIOPSY],
164+
right_breast_procedures=[BenignLumpHistoryItem.Procedure.NO_PROCEDURES],
165+
procedure_year=2020,
166+
procedure_location=BenignLumpHistoryItem.ProcedureLocation.NHS_HOSPITAL,
167+
procedure_location_details="Original Hospital",
168+
additional_details="Original details",
169+
)
170+
request = RequestFactory().post("/test-form")
171+
request.user = clinical_user
172+
173+
data = [
174+
("left_breast_procedures", BenignLumpHistoryItem.Procedure.LUMP_REMOVED),
175+
(
176+
"right_breast_procedures",
177+
BenignLumpHistoryItem.Procedure.NEEDLE_BIOPSY,
178+
),
179+
("procedure_year", 2021),
180+
(
181+
"procedure_location",
182+
BenignLumpHistoryItem.ProcedureLocation.PRIVATE_CLINIC_UK,
183+
),
184+
("private_clinic_uk_details", "Private Hospital Updated"),
185+
("additional_details", "Updated details"),
186+
]
187+
form = BenignLumpHistoryItemForm(_form_data(data), instance=instance)
188+
assert form.is_valid()
189+
updated_obj = form.update(request=request)
190+
assert updated_obj.pk == instance.pk
191+
assert updated_obj.left_breast_procedures == [
192+
BenignLumpHistoryItem.Procedure.LUMP_REMOVED
193+
]
194+
assert updated_obj.right_breast_procedures == [
195+
BenignLumpHistoryItem.Procedure.NEEDLE_BIOPSY
196+
]
197+
assert updated_obj.procedure_year == 2021
198+
assert updated_obj.procedure_location == (
199+
BenignLumpHistoryItem.ProcedureLocation.PRIVATE_CLINIC_UK
200+
)
201+
assert updated_obj.procedure_location_details == "Private Hospital Updated"
202+
assert updated_obj.additional_details == "Updated details"

manage_breast_screening/mammograms/tests/presenters/test_benign_lump_history_item_presenter.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ def test_summary_list_params(self):
2525

2626
presenter = BenignLumpHistoryItemPresenter(item)
2727

28-
assert presenter.summary_list_params == {
28+
result = presenter.summary_list_params
29+
assert result == {
2930
"rows": [
3031
{
3132
"key": {"text": "Procedures"},
@@ -52,3 +53,13 @@ def test_summary_list_params(self):
5253
},
5354
],
5455
}
56+
57+
def test_change_link(self):
58+
item = BenignLumpHistoryItemFactory.build()
59+
presenter = BenignLumpHistoryItemPresenter(item)
60+
61+
result = presenter.change_link
62+
assert result == {
63+
"href": f"/mammograms/{item.appointment_id}/record-medical-information/benign-lump-history/{item.id}/",
64+
"text": "Change",
65+
}

manage_breast_screening/mammograms/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@
175175
benign_lump_history_item_views.AddBenignLumpHistoryItemView.as_view(),
176176
name="add_benign_lump_history_item",
177177
),
178+
path(
179+
"<uuid:pk>/record-medical-information/benign-lump-history/<uuid:history_item_pk>/",
180+
benign_lump_history_item_views.UpdateBenignLumpHistoryItemView.as_view(),
181+
name="change_benign_lump_history_item",
182+
),
178183
path(
179184
"<uuid:pk>/record-medical-information/mastectomy-or-lumpectomy-history/",
180185
mastectomy_or_lumpectomy_history_view.AddMastectomyOrLumpectomyHistoryView.as_view(),

manage_breast_screening/mammograms/views/benign_lump_history_item_views.py

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
1+
import logging
2+
from typing import Any
3+
14
from django.contrib import messages
5+
from django.http import Http404
6+
from django.shortcuts import redirect
27
from django.urls import reverse
38
from django.views.generic import FormView
49

510
from manage_breast_screening.mammograms.forms.benign_lump_history_item_form import (
611
BenignLumpHistoryItemForm,
712
)
13+
from manage_breast_screening.participants.models.benign_lump_history_item import (
14+
BenignLumpHistoryItem,
15+
)
816

917
from .mixins import InProgressAppointmentMixin
1018

19+
logger = logging.getLogger(__name__)
1120

12-
class AddBenignLumpHistoryItemView(InProgressAppointmentMixin, FormView):
21+
22+
class BaseBenignLumpHistoryItemView(InProgressAppointmentMixin, FormView):
1323
form_class = BenignLumpHistoryItemForm
1424
template_name = "mammograms/medical_information/medical_history/forms/benign_lump_history_item_form.jinja"
1525

16-
def form_valid(self, form):
17-
form.create(appointment=self.appointment, request=self.request)
18-
19-
messages.add_message(
20-
self.request,
21-
messages.SUCCESS,
22-
"Benign lump history added",
23-
)
24-
25-
return super().form_valid(form)
26-
2726
def get_success_url(self):
2827
return reverse(
2928
"mammograms:record_medical_information", kwargs={"pk": self.appointment.pk}
@@ -48,9 +47,80 @@ def get_context_data(self, **kwargs):
4847
"back_link_params": self.get_back_link_params(),
4948
"caption": participant.full_name,
5049
"participant_first_name": participant.first_name,
50+
},
51+
)
52+
53+
return context
54+
55+
56+
class AddBenignLumpHistoryItemView(BaseBenignLumpHistoryItemView):
57+
def form_valid(self, form):
58+
form.create(appointment=self.appointment, request=self.request)
59+
60+
messages.add_message(
61+
self.request,
62+
messages.SUCCESS,
63+
"Benign lumps added",
64+
)
65+
66+
return super().form_valid(form)
67+
68+
def get_context_data(self, **kwargs):
69+
context = super().get_context_data(**kwargs)
70+
context.update(
71+
{
5172
"heading": "Add details of benign lumps",
5273
"page_title": "Add details of benign lumps",
5374
},
5475
)
76+
return context
77+
78+
79+
class UpdateBenignLumpHistoryItemView(BaseBenignLumpHistoryItemView):
80+
def get_instance(self):
81+
try:
82+
return BenignLumpHistoryItem.objects.get(
83+
pk=self.kwargs["history_item_pk"],
84+
appointment_id=self.kwargs["pk"],
85+
)
86+
except BenignLumpHistoryItem.DoesNotExist:
87+
logger.exception("History item does not exist for kwargs=%s", self.kwargs)
88+
return None
89+
90+
def get(self, request, *args, **kwargs):
91+
self.instance = self.get_instance()
92+
if self.instance is None:
93+
return redirect(self.get_success_url())
94+
return super().get(request, *args, **kwargs)
95+
96+
def post(self, request, *args, **kwargs):
97+
self.instance = self.get_instance()
98+
if self.instance is None:
99+
raise Http404
100+
return super().post(request, *args, **kwargs)
101+
102+
def get_form_kwargs(self) -> dict[str, Any]:
103+
kwargs = super().get_form_kwargs()
104+
kwargs["instance"] = self.instance
105+
return kwargs
106+
107+
def form_valid(self, form):
108+
form.update(request=self.request)
109+
110+
messages.add_message(
111+
self.request,
112+
messages.SUCCESS,
113+
"Benign lumps updated",
114+
)
55115

116+
return super().form_valid(form)
117+
118+
def get_context_data(self, **kwargs):
119+
context = super().get_context_data(**kwargs)
120+
context.update(
121+
{
122+
"heading": "Change details of benign lumps",
123+
"page_title": "Change details of benign lumps",
124+
},
125+
)
56126
return context

0 commit comments

Comments
 (0)