diff --git a/manage_breast_screening/mammograms/forms/mastectomy_or_lumpectomy_history_form.py b/manage_breast_screening/mammograms/forms/mastectomy_or_lumpectomy_history_form.py
index fe5d312b1..9b52244d4 100644
--- a/manage_breast_screening/mammograms/forms/mastectomy_or_lumpectomy_history_form.py
+++ b/manage_breast_screening/mammograms/forms/mastectomy_or_lumpectomy_history_form.py
@@ -90,7 +90,21 @@ class MastectomyOrLumpectomyHistoryForm(FormWithConditionalFields):
error_messages={"max_words": "Additional details must be 500 words or less"},
)
- def __init__(self, *args, participant, **kwargs):
+ def __init__(self, *args, **kwargs):
+ self.instance = kwargs.pop("instance", None)
+
+ if self.instance:
+ kwargs["initial"] = {
+ "left_breast_procedure": self.instance.left_breast_procedure,
+ "right_breast_procedure": self.instance.right_breast_procedure,
+ "left_breast_other_surgery": self.instance.left_breast_other_surgery,
+ "right_breast_other_surgery": self.instance.right_breast_other_surgery,
+ "year_of_surgery": self.instance.year_of_surgery,
+ "surgery_reason": self.instance.surgery_reason,
+ "surgery_other_reason_details": self.instance.surgery_other_reason_details,
+ "additional_details": self.instance.additional_details,
+ }
+
super().__init__(*args, **kwargs)
self.given_field_value(
@@ -132,3 +146,26 @@ def create(self, appointment, request):
auditor.audit_create(mastectomy_or_lumpectomy_history)
return mastectomy_or_lumpectomy_history
+
+ def update(self, request):
+ self.instance.left_breast_procedure = self.cleaned_data["left_breast_procedure"]
+ self.instance.right_breast_procedure = self.cleaned_data[
+ "right_breast_procedure"
+ ]
+ self.instance.left_breast_other_surgery = self.cleaned_data[
+ "left_breast_other_surgery"
+ ]
+ self.instance.right_breast_other_surgery = self.cleaned_data[
+ "right_breast_other_surgery"
+ ]
+ self.instance.year_of_surgery = self.cleaned_data["year_of_surgery"]
+ self.instance.surgery_reason = self.cleaned_data["surgery_reason"]
+ self.instance.surgery_other_reason_details = self.cleaned_data[
+ "surgery_other_reason_details"
+ ]
+ self.instance.additional_details = self.cleaned_data["additional_details"]
+ self.instance.save()
+
+ Auditor.from_request(request).audit_update(self.instance)
+
+ return self.instance
diff --git a/manage_breast_screening/mammograms/jinja2/mammograms/record_medical_information.jinja b/manage_breast_screening/mammograms/jinja2/mammograms/record_medical_information.jinja
index 62a50aaaf..6f516a47e 100644
--- a/manage_breast_screening/mammograms/jinja2/mammograms/record_medical_information.jinja
+++ b/manage_breast_screening/mammograms/jinja2/mammograms/record_medical_information.jinja
@@ -45,6 +45,9 @@
{% set mastectomy_or_lumpectomy_history_html %}
{% for presented_item in presenter.mastectomy_or_lumpectomy_history %}
+
+ {{ presented_item.change_link.text }}{{ presented_item.change_link.visually_hidden_text }}
+
{{ summaryList(presented_item.summary_list_params) }}
{% endfor %}
{{ presenter.add_mastectomy_or_lumpectomy_history_link.text }}
diff --git a/manage_breast_screening/mammograms/presenters/mastectomy_or_lumpectomy_history_item_presenter.py b/manage_breast_screening/mammograms/presenters/mastectomy_or_lumpectomy_history_item_presenter.py
index aac1954b4..87453cddd 100644
--- a/manage_breast_screening/mammograms/presenters/mastectomy_or_lumpectomy_history_item_presenter.py
+++ b/manage_breast_screening/mammograms/presenters/mastectomy_or_lumpectomy_history_item_presenter.py
@@ -1,3 +1,5 @@
+from django.urls import reverse
+
from manage_breast_screening.core.template_helpers import multiline_content, nl2br
from manage_breast_screening.participants.models.mastectomy_or_lumpectomy_history_item import (
MastectomyOrLumpectomyHistoryItem,
@@ -5,9 +7,13 @@
class MastectomyOrLumpectomyHistoryItemPresenter:
- def __init__(self, mastectomy_or_lumpectomy_history_item):
+ def __init__(self, mastectomy_or_lumpectomy_history_item, counter=None):
self._item = mastectomy_or_lumpectomy_history_item
+ # If there are more than one of these items, we add a counter to the
+ # visually hidden text
+ self.counter = counter
+
self.right_breast_procedure = self._item.get_right_breast_procedure_display()
self.left_breast_procedure = self._item.get_left_breast_procedure_display()
@@ -75,3 +81,21 @@ def summary_list_params(self):
def _format_multiple_choices(self, choices, ChoiceClass):
return ", ".join(ChoiceClass(choice).label for choice in choices)
+
+ @property
+ def change_link(self):
+ return {
+ "href": reverse(
+ "mammograms:change_mastectomy_or_lumpectomy_history_item",
+ kwargs={
+ "pk": self._item.appointment_id,
+ "history_item_pk": self._item.pk,
+ },
+ ),
+ "text": "Change",
+ "visually_hidden_text": (
+ f" mastectomy or lumpectomy item {self.counter}"
+ if self.counter
+ else " mastectomy or lumpectomy item"
+ ),
+ }
diff --git a/manage_breast_screening/mammograms/presenters/medical_information_presenter.py b/manage_breast_screening/mammograms/presenters/medical_information_presenter.py
index c1b34e913..0b0fb1182 100644
--- a/manage_breast_screening/mammograms/presenters/medical_information_presenter.py
+++ b/manage_breast_screening/mammograms/presenters/medical_information_presenter.py
@@ -41,25 +41,15 @@ def __init__(self, appointment):
BreastCancerHistoryItemPresenter,
)
- self.mastectomy_or_lumpectomy_history = [
- MastectomyOrLumpectomyHistoryItemPresenter(item)
- for item in appointment.mastectomy_or_lumpectomy_history_items.all()
- ]
+ self.mastectomy_or_lumpectomy_history = self._present_items(
+ appointment.mastectomy_or_lumpectomy_history_items.all(),
+ MastectomyOrLumpectomyHistoryItemPresenter,
+ )
- implanted_medical_device_history = list(
- appointment.implanted_medical_device_history_items.all()
+ self.implanted_medical_device_history = self._present_items(
+ appointment.implanted_medical_device_history_items.all(),
+ ImplantedMedicalDeviceHistoryItemPresenter,
)
- if len(implanted_medical_device_history) == 1:
- self.implanted_medical_device_history = [
- ImplantedMedicalDeviceHistoryItemPresenter(
- implanted_medical_device_history[0]
- )
- ]
- else:
- self.implanted_medical_device_history = [
- ImplantedMedicalDeviceHistoryItemPresenter(item, counter=counter)
- for counter, item in enumerate(implanted_medical_device_history, 1)
- ]
self.breast_augmentation_history = [
BreastAugmentationHistoryItemPresenter(item)
diff --git a/manage_breast_screening/mammograms/tests/forms/test_mastectomy_or_lumpectomy_history_form.py b/manage_breast_screening/mammograms/tests/forms/test_mastectomy_or_lumpectomy_history_form.py
index 55dd2aad1..8ddf7bace 100644
--- a/manage_breast_screening/mammograms/tests/forms/test_mastectomy_or_lumpectomy_history_form.py
+++ b/manage_breast_screening/mammograms/tests/forms/test_mastectomy_or_lumpectomy_history_form.py
@@ -9,23 +9,27 @@
from manage_breast_screening.participants.models.mastectomy_or_lumpectomy_history_item import (
MastectomyOrLumpectomyHistoryItem,
)
-from manage_breast_screening.participants.tests.factories import AppointmentFactory
+from manage_breast_screening.participants.tests.factories import (
+ AppointmentFactory,
+ MastectomyOrLumpectomyHistoryItemFactory,
+)
from ...forms.mastectomy_or_lumpectomy_history_form import (
MastectomyOrLumpectomyHistoryForm,
)
+@pytest.fixture
+def dummy_request(clinical_user):
+ request = RequestFactory().get("/test-form")
+ request.user = clinical_user
+ return request
+
+
@pytest.mark.django_db
class TestMastectomyOrLumpectomyHistoryItemForm:
- def test_missing_required_fields(self, clinical_user):
- appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
-
- form = MastectomyOrLumpectomyHistoryForm(
- QueryDict(), participant=appointment.participant
- )
+ def test_missing_required_fields(self):
+ form = MastectomyOrLumpectomyHistoryForm(QueryDict())
assert not form.is_valid()
assert form.errors == {
@@ -44,13 +48,7 @@ def test_missing_required_fields(self, clinical_user):
"surgery_reason": ["Select the reason for surgery"],
}
- def test_right_breast_other_surgery_no_other_surgery_and_others(
- self, clinical_user
- ):
- appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
-
+ def test_right_breast_other_surgery_no_other_surgery_and_others(self):
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(
urlencode(
@@ -70,7 +68,6 @@ def test_right_breast_other_surgery_no_other_surgery_and_others(
doseq=True,
),
),
- participant=appointment.participant,
)
assert not form.is_valid()
@@ -80,11 +77,7 @@ def test_right_breast_other_surgery_no_other_surgery_and_others(
],
}
- def test_left_breast_other_surgery_no_other_surgery_and_others(self, clinical_user):
- appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
-
+ def test_left_breast_other_surgery_no_other_surgery_and_others(self):
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(
urlencode(
@@ -103,7 +96,6 @@ def test_left_breast_other_surgery_no_other_surgery_and_others(self, clinical_us
doseq=True,
),
),
- participant=appointment.participant,
)
assert not form.is_valid()
@@ -123,11 +115,7 @@ def test_left_breast_other_surgery_no_other_surgery_and_others(self, clinical_us
3000,
],
)
- def test_year_of_surgery_outside_range(self, clinical_user, year_of_surgery):
- appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
-
+ def test_year_of_surgery_outside_range(self, year_of_surgery):
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(
urlencode(
@@ -146,7 +134,6 @@ def test_year_of_surgery_outside_range(self, clinical_user, year_of_surgery):
doseq=True,
),
),
- participant=appointment.participant,
)
assert not form.is_valid()
@@ -156,11 +143,7 @@ def test_year_of_surgery_outside_range(self, clinical_user, year_of_surgery):
],
}
- def test_year_of_surgery_invalid(self, clinical_user):
- appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
-
+ def test_year_of_surgery_invalid(self):
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(
urlencode(
@@ -179,7 +162,6 @@ def test_year_of_surgery_invalid(self, clinical_user):
doseq=True,
),
),
- participant=appointment.participant,
)
assert not form.is_valid()
@@ -187,11 +169,7 @@ def test_year_of_surgery_invalid(self, clinical_user):
"year_of_surgery": ["Enter a whole number."],
}
- def test_other_reason_without_details(self, clinical_user):
- appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
-
+ def test_other_reason_without_details(self):
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(
urlencode(
@@ -209,7 +187,6 @@ def test_other_reason_without_details(self, clinical_user):
doseq=True,
),
),
- participant=appointment.participant,
)
assert not form.is_valid()
@@ -217,10 +194,8 @@ def test_other_reason_without_details(self, clinical_user):
"surgery_other_reason_details": ["Provide details of the surgery"],
}
- def test_other_reason_details_when_not_other_reason(self, clinical_user):
+ def test_other_reason_details_when_not_other_reason(self, dummy_request):
appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(
@@ -240,12 +215,11 @@ def test_other_reason_details_when_not_other_reason(self, clinical_user):
doseq=True,
),
),
- participant=appointment.participant,
)
assert form.is_valid()
- obj = form.create(appointment=appointment, request=request)
+ obj = form.create(appointment=appointment, request=dummy_request)
obj.refresh_from_db()
assert obj.appointment == appointment
@@ -315,20 +289,17 @@ def test_other_reason_details_when_not_other_reason(self, clinical_user):
},
],
)
- def test_success(self, clinical_user, data):
+ def test_success(self, clinical_user, data, dummy_request):
appointment = AppointmentFactory()
- request = RequestFactory().get("/test-form")
- request.user = clinical_user
form = MastectomyOrLumpectomyHistoryForm(
QueryDict(urlencode(data, doseq=True)),
- participant=appointment.participant,
)
assert form.is_valid()
existing_log_count = AuditLog.objects.count()
- obj = form.create(appointment=appointment, request=request)
+ obj = form.create(appointment=appointment, request=dummy_request)
assert AuditLog.objects.count() == existing_log_count + 1
audit_log = AuditLog.objects.filter(
object_id=obj.pk, operation=AuditLog.Operations.CREATE
@@ -356,3 +327,84 @@ def create_year_outside_range_error_messsage(self, request_year):
if request_year > max_year
else (f"Year must be {min_year} or later")
)
+
+
+@pytest.mark.django_db
+class TestUpdateMastectomyOrLumpectomyHistoryForm:
+ @pytest.fixture
+ def instance(self):
+ return MastectomyOrLumpectomyHistoryItemFactory(
+ right_breast_procedure=MastectomyOrLumpectomyHistoryItem.Procedure.NO_PROCEDURE,
+ left_breast_procedure=MastectomyOrLumpectomyHistoryItem.Procedure.NO_PROCEDURE,
+ right_breast_other_surgery=[
+ MastectomyOrLumpectomyHistoryItem.Surgery.NO_OTHER_SURGERY,
+ ],
+ left_breast_other_surgery=[
+ MastectomyOrLumpectomyHistoryItem.Surgery.NO_OTHER_SURGERY,
+ ],
+ year_of_surgery=None,
+ surgery_reason=MastectomyOrLumpectomyHistoryItem.SurgeryReason.RISK_REDUCTION,
+ additional_details="",
+ )
+
+ def test_no_data(self, instance):
+ form = MastectomyOrLumpectomyHistoryForm(QueryDict(), instance=instance)
+
+ assert not form.is_valid()
+ assert form.errors == {
+ "right_breast_procedure": [
+ "Select which procedure they have had in the right breast",
+ ],
+ "left_breast_procedure": [
+ "Select which procedure they have had in the left breast",
+ ],
+ "right_breast_other_surgery": [
+ "Select any other surgery they have had in the right breast",
+ ],
+ "left_breast_other_surgery": [
+ "Select any other surgery they have had in the left breast",
+ ],
+ "surgery_reason": ["Select the reason for surgery"],
+ }
+
+ @pytest.mark.parametrize(
+ "data",
+ [
+ {
+ "right_breast_procedure": MastectomyOrLumpectomyHistoryItem.Procedure.LUMPECTOMY,
+ "left_breast_procedure": MastectomyOrLumpectomyHistoryItem.Procedure.LUMPECTOMY,
+ "right_breast_other_surgery": [
+ MastectomyOrLumpectomyHistoryItem.Surgery.RECONSTRUCTION
+ ],
+ "left_breast_other_surgery": [
+ MastectomyOrLumpectomyHistoryItem.Surgery.RECONSTRUCTION
+ ],
+ "year_of_surgery": datetime.date.today().year,
+ "surgery_reason": MastectomyOrLumpectomyHistoryItem.SurgeryReason.OTHER_REASON,
+ "surgery_other_reason_details": "surgery other details",
+ "additional_details": "additional details",
+ },
+ ],
+ )
+ def test_success(self, instance, data, dummy_request):
+ form = MastectomyOrLumpectomyHistoryForm(
+ QueryDict(urlencode(data, doseq=True)),
+ instance=instance,
+ )
+
+ assert form.is_valid()
+
+ obj = form.update(request=dummy_request)
+
+ obj.refresh_from_db()
+ assert obj.appointment == instance.appointment
+ assert obj.right_breast_procedure == data.get("right_breast_procedure")
+ assert obj.left_breast_procedure == data.get("left_breast_procedure")
+ assert obj.right_breast_other_surgery == data.get("right_breast_other_surgery")
+ assert obj.left_breast_other_surgery == data.get("left_breast_other_surgery")
+ assert obj.year_of_surgery == data.get("year_of_surgery", None)
+ assert obj.surgery_reason == data.get("surgery_reason", "")
+ assert obj.surgery_other_reason_details == data.get(
+ "surgery_other_reason_details", ""
+ )
+ assert obj.additional_details == data.get("additional_details", "")
diff --git a/manage_breast_screening/mammograms/tests/presenters/test_mastectomy_or_lumpectomy_history_item_presenter.py b/manage_breast_screening/mammograms/tests/presenters/test_mastectomy_or_lumpectomy_history_item_presenter.py
index 65783a21a..b330a561d 100644
--- a/manage_breast_screening/mammograms/tests/presenters/test_mastectomy_or_lumpectomy_history_item_presenter.py
+++ b/manage_breast_screening/mammograms/tests/presenters/test_mastectomy_or_lumpectomy_history_item_presenter.py
@@ -79,3 +79,27 @@ def test_single(self):
},
],
}
+
+ def test_change_link(self):
+ item = MastectomyOrLumpectomyHistoryItemFactory.build(
+ additional_details="Some additional details",
+ )
+
+ presenter = MastectomyOrLumpectomyHistoryItemPresenter(item)
+ assert presenter.change_link == {
+ "href": f"/mammograms/{item.appointment_id}/record-medical-information/mastectomy-or-lumpectomy-history/{item.pk}",
+ "text": "Change",
+ "visually_hidden_text": " mastectomy or lumpectomy item",
+ }
+
+ def test_change_link_with_counter(self):
+ item = MastectomyOrLumpectomyHistoryItemFactory.build(
+ additional_details="Some additional details",
+ )
+
+ presenter = MastectomyOrLumpectomyHistoryItemPresenter(item, counter=2)
+ assert presenter.change_link == {
+ "href": f"/mammograms/{item.appointment_id}/record-medical-information/mastectomy-or-lumpectomy-history/{item.pk}",
+ "text": "Change",
+ "visually_hidden_text": " mastectomy or lumpectomy item 2",
+ }
diff --git a/manage_breast_screening/mammograms/tests/presenters/test_medical_information_presenter.py b/manage_breast_screening/mammograms/tests/presenters/test_medical_information_presenter.py
index df043e5bf..15575bf82 100644
--- a/manage_breast_screening/mammograms/tests/presenters/test_medical_information_presenter.py
+++ b/manage_breast_screening/mammograms/tests/presenters/test_medical_information_presenter.py
@@ -11,6 +11,7 @@
AppointmentFactory,
CystHistoryItemFactory,
ImplantedMedicalDeviceHistoryItemFactory,
+ MastectomyOrLumpectomyHistoryItemFactory,
SymptomFactory,
)
@@ -223,3 +224,31 @@ def test_mastectomy_or_lumpectomy_history_link(self):
"href": f"/mammograms/{appointment.pk}/record-medical-information/mastectomy-or-lumpectomy-history/",
"text": "Add mastectomy or lumpectomy history",
}
+
+ def test_mastectomy_or_lumpectomy_history_items_have_a_counter(self):
+ appointment = AppointmentFactory()
+ MastectomyOrLumpectomyHistoryItemFactory.create_batch(
+ 2, appointment=appointment
+ )
+
+ counters = [
+ item.counter
+ for item in MedicalInformationPresenter(
+ appointment
+ ).mastectomy_or_lumpectomy_history
+ ]
+
+ assert counters == [1, 2]
+
+ def test_single_mastectomy_or_lumpectomy_history_item_has_no_counter(self):
+ appointment = AppointmentFactory()
+ MastectomyOrLumpectomyHistoryItemFactory.create(appointment=appointment)
+
+ counters = [
+ item.counter
+ for item in MedicalInformationPresenter(
+ appointment
+ ).mastectomy_or_lumpectomy_history
+ ]
+
+ assert counters == [None]
diff --git a/manage_breast_screening/mammograms/tests/views/test_mastectomy_or_lumpectomy_history_views.py b/manage_breast_screening/mammograms/tests/views/test_mastectomy_or_lumpectomy_history_views.py
index 24ca28908..dc8940fba 100644
--- a/manage_breast_screening/mammograms/tests/views/test_mastectomy_or_lumpectomy_history_views.py
+++ b/manage_breast_screening/mammograms/tests/views/test_mastectomy_or_lumpectomy_history_views.py
@@ -8,6 +8,7 @@
)
from manage_breast_screening.participants.tests.factories import (
AppointmentFactory,
+ MastectomyOrLumpectomyHistoryItemFactory,
)
@@ -89,3 +90,74 @@ def test_invalid_post_renders_response_with_errors(self, clinical_user_client):
""",
response.text,
)
+
+
+@pytest.mark.django_db
+class TestUpdateMastectomyOrLumpectomyHistoryView:
+ @pytest.fixture
+ def appointment(self, clinical_user_client):
+ return AppointmentFactory.create(
+ clinic_slot__clinic__setting__provider=clinical_user_client.current_provider
+ )
+
+ @pytest.fixture
+ def history_item(self, appointment):
+ return MastectomyOrLumpectomyHistoryItemFactory.create(
+ appointment=appointment,
+ right_breast_procedure=MastectomyOrLumpectomyHistoryItem.Procedure.NO_PROCEDURE,
+ left_breast_procedure=MastectomyOrLumpectomyHistoryItem.Procedure.NO_PROCEDURE,
+ right_breast_other_surgery=[
+ MastectomyOrLumpectomyHistoryItem.Surgery.NO_OTHER_SURGERY,
+ ],
+ left_breast_other_surgery=[
+ MastectomyOrLumpectomyHistoryItem.Surgery.NO_OTHER_SURGERY,
+ ],
+ year_of_surgery=None,
+ surgery_reason=MastectomyOrLumpectomyHistoryItem.SurgeryReason.RISK_REDUCTION,
+ additional_details="",
+ )
+
+ def test_renders_response(self, clinical_user_client, history_item):
+ response = clinical_user_client.http.get(
+ reverse(
+ "mammograms:change_mastectomy_or_lumpectomy_history_item",
+ kwargs={
+ "pk": history_item.appointment.pk,
+ "history_item_pk": history_item.pk,
+ },
+ )
+ )
+ assert response.status_code == 200
+
+ def test_valid_post_redirects_to_appointment(
+ self, clinical_user_client, appointment, history_item
+ ):
+ response = clinical_user_client.http.post(
+ reverse(
+ "mammograms:change_mastectomy_or_lumpectomy_history_item",
+ kwargs={"pk": appointment.pk, "history_item_pk": history_item.pk},
+ ),
+ {
+ "right_breast_procedure": "NO_PROCEDURE",
+ "left_breast_procedure": "NO_PROCEDURE",
+ "right_breast_other_surgery": "NO_OTHER_SURGERY",
+ "left_breast_other_surgery": "NO_OTHER_SURGERY",
+ "surgery_reason": "RISK_REDUCTION",
+ },
+ )
+ assertRedirects(
+ response,
+ reverse(
+ "mammograms:record_medical_information",
+ kwargs={"pk": appointment.pk},
+ ),
+ )
+ assertMessages(
+ response,
+ [
+ messages.Message(
+ level=messages.SUCCESS,
+ message="Details of mastectomy or lumpectomy updated",
+ )
+ ],
+ )
diff --git a/manage_breast_screening/mammograms/urls.py b/manage_breast_screening/mammograms/urls.py
index 2880e7961..0f847034d 100644
--- a/manage_breast_screening/mammograms/urls.py
+++ b/manage_breast_screening/mammograms/urls.py
@@ -170,4 +170,9 @@
mastectomy_or_lumpectomy_history_view.AddMastectomyOrLumpectomyHistoryView.as_view(),
name="add_mastectomy_or_lumpectomy_history_item",
),
+ path(
+ "/record-medical-information/mastectomy-or-lumpectomy-history/",
+ mastectomy_or_lumpectomy_history_view.UpdateMastectomyOrLumpectomyHistoryView.as_view(),
+ name="change_mastectomy_or_lumpectomy_history_item",
+ ),
]
diff --git a/manage_breast_screening/mammograms/views/mastectomy_or_lumpectomy_history_view.py b/manage_breast_screening/mammograms/views/mastectomy_or_lumpectomy_history_view.py
index eef6180c7..9988a68ad 100644
--- a/manage_breast_screening/mammograms/views/mastectomy_or_lumpectomy_history_view.py
+++ b/manage_breast_screening/mammograms/views/mastectomy_or_lumpectomy_history_view.py
@@ -1,21 +1,28 @@
+import logging
from functools import cached_property
from django.contrib import messages
+from django.http import Http404
+from django.shortcuts import redirect
from django.urls import reverse
from django.views.generic import FormView
from manage_breast_screening.mammograms.presenters.medical_information_presenter import (
MedicalInformationPresenter,
)
+from manage_breast_screening.participants.models.mastectomy_or_lumpectomy_history_item import (
+ MastectomyOrLumpectomyHistoryItem,
+)
from ..forms.mastectomy_or_lumpectomy_history_form import (
MastectomyOrLumpectomyHistoryForm,
)
from .mixins import InProgressAppointmentMixin
+logger = logging.getLogger(__name__)
-class AddMastectomyOrLumpectomyHistoryView(InProgressAppointmentMixin, FormView):
- form_class = MastectomyOrLumpectomyHistoryForm
+
+class BaseMastectomyOrLumpectomyHistoryView(InProgressAppointmentMixin, FormView):
template_name = "mammograms/medical_information/medical_history/forms/mastectomy_or_lumpectomy_history.jinja"
def get_success_url(self):
@@ -23,17 +30,6 @@ def get_success_url(self):
"mammograms:record_medical_information", kwargs={"pk": self.appointment.pk}
)
- def form_valid(self, form):
- form.create(appointment=self.appointment, request=self.request)
-
- messages.add_message(
- self.request,
- messages.SUCCESS,
- "Details of mastectomy or lumpectomy added",
- )
-
- return super().form_valid(form)
-
def get_back_link_params(self):
return {
"href": reverse(
@@ -53,8 +49,6 @@ def get_context_data(self, **kwargs):
"back_link_params": self.get_back_link_params(),
"caption": participant.full_name,
"participant_first_name": participant.first_name,
- "heading": "Add details of mastectomy or lumpectomy",
- "page_title": "Add details of mastectomy or lumpectomy",
"presenter": MedicalInformationPresenter(self.appointment),
},
)
@@ -65,7 +59,85 @@ def get_context_data(self, **kwargs):
def participant(self):
return self.appointment.participant
+
+class AddMastectomyOrLumpectomyHistoryView(BaseMastectomyOrLumpectomyHistoryView):
+ form_class = MastectomyOrLumpectomyHistoryForm
+
+ def form_valid(self, form):
+ form.create(appointment=self.appointment, request=self.request)
+
+ messages.add_message(
+ self.request,
+ messages.SUCCESS,
+ "Details of mastectomy or lumpectomy added",
+ )
+
+ return super().form_valid(form)
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data()
+
+ context.update(
+ {
+ "heading": "Add details of mastectomy or lumpectomy",
+ "page_title": "Add details of mastectomy or lumpectomy",
+ },
+ )
+
+ return context
+
+
+class UpdateMastectomyOrLumpectomyHistoryView(BaseMastectomyOrLumpectomyHistoryView):
+ form_class = MastectomyOrLumpectomyHistoryForm
+
+ def get_instance(self):
+ try:
+ return MastectomyOrLumpectomyHistoryItem.objects.get(
+ pk=self.kwargs["history_item_pk"],
+ appointment_id=self.kwargs["pk"],
+ )
+ except MastectomyOrLumpectomyHistoryItem.DoesNotExist:
+ logger.exception("History item does not exist for kwargs=%s", self.kwargs)
+ return None
+
+ def get(self, *args, **kwargs):
+ self.instance = self.get_instance()
+ if not self.instance:
+ # For a GET request, if the page shouldn't exist we can
+ # safely redirect to the hub page.
+ return redirect(self.get_success_url())
+ return super().get(*args, **kwargs)
+
+ def post(self, *args, **kwargs):
+ self.instance = self.get_instance()
+ if not self.instance:
+ raise Http404
+ return super().post(*args, **kwargs)
+
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
- kwargs["participant"] = self.participant
+ kwargs["instance"] = self.instance
return kwargs
+
+ def form_valid(self, form):
+ form.update(request=self.request)
+
+ messages.add_message(
+ self.request,
+ messages.SUCCESS,
+ "Details of mastectomy or lumpectomy updated",
+ )
+
+ return super().form_valid(form)
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data()
+
+ context.update(
+ {
+ "heading": "Edit details of mastectomy or lumpectomy",
+ "page_title": "Details of the mastectomy or lumpectomy",
+ },
+ )
+
+ return context
diff --git a/manage_breast_screening/participants/models/mastectomy_or_lumpectomy_history_item.py b/manage_breast_screening/participants/models/mastectomy_or_lumpectomy_history_item.py
index 91d0b3c9b..d02d57c8c 100644
--- a/manage_breast_screening/participants/models/mastectomy_or_lumpectomy_history_item.py
+++ b/manage_breast_screening/participants/models/mastectomy_or_lumpectomy_history_item.py
@@ -49,3 +49,7 @@ class SurgeryReason(models.TextChoices):
surgery_reason = models.CharField(choices=SurgeryReason)
surgery_other_reason_details = models.CharField(blank=True, null=False, default="")
additional_details = models.TextField(blank=True, null=False, default="")
+
+ @property
+ def participant(self):
+ return self.appointment.participant
diff --git a/manage_breast_screening/tests/system/clinical/test_mastectomy_or_lumpectomy_history.py b/manage_breast_screening/tests/system/clinical/test_mastectomy_or_lumpectomy_history.py
index ae25710ba..9b0216cc1 100644
--- a/manage_breast_screening/tests/system/clinical/test_mastectomy_or_lumpectomy_history.py
+++ b/manage_breast_screening/tests/system/clinical/test_mastectomy_or_lumpectomy_history.py
@@ -27,6 +27,14 @@ def test_adding_mastectomy_or_lumpectomy(self):
self.and_the_mastectomy_or_lumpectomy_is_listed()
self.and_the_message_says_mastectomy_or_lumpectomy_added()
+ self.when_i_click_change()
+ self.then_i_see_the_edit_mastectomy_or_lumpectomy_form()
+ self.when_i_update_additional_details()
+ self.and_i_click_save()
+ self.then_i_am_back_on_the_medical_information_page()
+ self.and_the_mastectomy_or_lumpectomy_is_updated()
+ self.and_the_message_says_mastectomy_or_lumpectomy_updated()
+
def test_accessibility(self):
self.given_i_am_logged_in_as_a_clinical_user()
self.and_there_is_an_appointment()
@@ -157,3 +165,33 @@ def and_the_message_says_mastectomy_or_lumpectomy_added(self):
expect(alert).to_contain_text("Success")
expect(alert).to_contain_text("Details of mastectomy or lumpectomy added")
+
+ def when_i_click_change(self):
+ self.page.get_by_text("Change mastectomy or lumpectomy item").click()
+
+ def then_i_see_the_edit_mastectomy_or_lumpectomy_form(self):
+ expect(
+ self.page.get_by_text("Edit details of mastectomy or lumpectomy")
+ ).to_be_visible()
+ self.assert_page_title_contains("Details of the mastectomy or lumpectomy")
+
+ def when_i_update_additional_details(self):
+ self.page.get_by_label("Additional details (optional)", exact=True).fill(
+ "updated additional details for test of mastectomy or lumpectomy details"
+ )
+
+ def and_the_mastectomy_or_lumpectomy_is_updated(self):
+ key = self.page.locator(
+ ".nhsuk-summary-list__key",
+ has=self.page.get_by_text("Mastectomy or lumpectomy history", exact=True),
+ )
+ row = self.page.locator(".nhsuk-summary-list__row").filter(has=key)
+ expect(row).to_contain_text(
+ "updated additional details for test of mastectomy or lumpectomy details"
+ )
+
+ def and_the_message_says_mastectomy_or_lumpectomy_updated(self):
+ alert = self.page.get_by_role("alert")
+
+ expect(alert).to_contain_text("Success")
+ expect(alert).to_contain_text("Details of mastectomy or lumpectomy updated")