Skip to content

Commit 2abe19a

Browse files
authored
Merge pull request #699 from NHSDigital/11559-benign-lumps-model-demo-data
Add BenignLumpHistoryItem
2 parents b4b7d24 + ff605f0 commit 2abe19a

File tree

11 files changed

+238
-0
lines changed

11 files changed

+238
-0
lines changed

manage_breast_screening/data/east_tester_one_week_ago_clinic_data.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ clinic:
7171
systemic_treatments: NO_RADIOTHERAPY
7272
intervention_location: NHS_HOSPITAL
7373
intervention_location_details: East Tester Hospital
74+
7475
- id: c19bf83e-a1b5-4374-a84d-ab29d24e995d
7576
duration_in_minutes: 8
7677
starts_at_time: 09:16

manage_breast_screening/data/east_tester_today_clinic_data.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ clinic:
5555
procedure_details: Lorem ipsum dolor sit amet
5656
procedure_year: 2018
5757
additional_details: No complications
58+
benign_lump_history_items:
59+
- id: 271E4B10-BBB2-4FCD-A777-5CE7E9411FEC
60+
right_breast_procedures: [NEEDLE_BIOPSY, LUMP_REMOVED]
61+
left_breast_procedures: [LUMP_REMOVED]
62+
procedure_year: 2005
63+
procedure_location: NHS_HOSPITAL
64+
procedure_location_details: East Tester Hospital
65+
additional_details: Lorem ipsum dolor sit amet
5866
- id: aa1b4c5c-3742-4f97-aa68-04a6f3bd631b
5967
duration_in_minutes: 8
6068
starts_at_time: 09:08

manage_breast_screening/mammograms/jinja2/mammograms/record_medical_information.jinja

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@
6060
{% set non_cancerous_lump_diagnosis_link %}
6161
<a class="nhsuk-link" href="#">Enter non-cancerous lump diagnosis</a>
6262
{% endset %}
63+
{% set benign_lump_history_html %}
64+
{% for presented_item in presenter.benign_lump_history %}
65+
{{ summaryList(presented_item.summary_list_params) }}
66+
{% endfor %}
67+
{% endset %}
6368
{% set chest_procedures_link %}
6469
<a class="nhsuk-link" href="#">Enter other breast or chest procedures</a>
6570
{% endset %}
@@ -109,6 +114,17 @@
109114
"items": []
110115
}
111116
},
117+
{
118+
"key": {
119+
"text": "Benign lump history"
120+
},
121+
"value": {
122+
"html": benign_lump_history_html
123+
},
124+
"actions": {
125+
"items": []
126+
}
127+
},
112128
{
113129
"key": {
114130
"text": "Non-cancerous lump diagnosis"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from manage_breast_screening.core.template_helpers import multiline_content, nl2br
2+
from manage_breast_screening.participants.models.benign_lump_history_item import (
3+
BenignLumpHistoryItem,
4+
)
5+
6+
7+
class BenignLumpHistoryItemPresenter:
8+
def __init__(self, benign_lump_history_item):
9+
self._item = benign_lump_history_item
10+
self.right_breast_procedures = self._format_multiple_choices(
11+
self._item.right_breast_procedures, BenignLumpHistoryItem.Procedure
12+
)
13+
self.left_breast_procedures = self._format_multiple_choices(
14+
self._item.left_breast_procedures, BenignLumpHistoryItem.Procedure
15+
)
16+
self.procedure_year = str(self._item.procedure_year)
17+
self.procedure_location = self._item.get_procedure_location_display()
18+
self.procedure_location_details = self._item.procedure_location_details
19+
self.additional_details = nl2br(self._item.additional_details)
20+
21+
@property
22+
def summary_list_params(self):
23+
# This is a placeholder until we have a properly formatted table.
24+
return {
25+
"rows": [
26+
{
27+
"key": {"text": "Procedures"},
28+
"value": {
29+
"html": multiline_content(
30+
[
31+
f"Right breast: {self.right_breast_procedures}",
32+
f"Left breast: {self.left_breast_procedures}",
33+
]
34+
)
35+
},
36+
},
37+
{
38+
"key": {"text": "Procedure year"},
39+
"value": {"html": self.procedure_year},
40+
},
41+
{
42+
"key": {"text": "Procedure location"},
43+
"value": {
44+
"html": f"{self.procedure_location}: {self.procedure_location_details}"
45+
},
46+
},
47+
{
48+
"key": {"text": "Additional details"},
49+
"value": {"html": self.additional_details},
50+
},
51+
],
52+
}
53+
54+
def _format_multiple_choices(self, choices, ChoiceClass):
55+
return ", ".join(ChoiceClass(choice).label for choice in choices)

manage_breast_screening/mammograms/presenters/medical_information_presenter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from django.urls import reverse
22

3+
from manage_breast_screening.mammograms.presenters.benign_lump_history_item_presenter import (
4+
BenignLumpHistoryItemPresenter,
5+
)
36
from manage_breast_screening.mammograms.presenters.breast_augmentation_history_item_presenter import (
47
BreastAugmentationHistoryItemPresenter,
58
)
@@ -43,6 +46,10 @@ def __init__(self, appointment):
4346
OtherProcedureHistoryItemPresenter(item)
4447
for item in appointment.other_procedure_history_items.all()
4548
]
49+
self.benign_lump_history = [
50+
BenignLumpHistoryItemPresenter(item)
51+
for item in appointment.benign_lump_history_items.all()
52+
]
4653
self.existing_symptom_type_ids = {
4754
symptom.symptom_type_id for symptom in symptoms
4855
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from manage_breast_screening.mammograms.presenters.benign_lump_history_item_presenter import (
2+
BenignLumpHistoryItemPresenter,
3+
)
4+
from manage_breast_screening.participants.models.benign_lump_history_item import (
5+
BenignLumpHistoryItem,
6+
)
7+
from manage_breast_screening.participants.tests.factories import (
8+
BenignLumpHistoryItemFactory,
9+
)
10+
11+
12+
class TestBenignLumpHistoryItemPresenter:
13+
def test_summary_list_params(self):
14+
item = BenignLumpHistoryItemFactory.build(
15+
right_breast_procedures=[
16+
BenignLumpHistoryItem.Procedure.NEEDLE_BIOPSY,
17+
BenignLumpHistoryItem.Procedure.LUMP_REMOVED,
18+
],
19+
left_breast_procedures=[BenignLumpHistoryItem.Procedure.NO_PROCEDURES],
20+
procedure_year=2015,
21+
procedure_location=BenignLumpHistoryItem.ProcedureLocation.PRIVATE_CLINIC_UK,
22+
procedure_location_details="Harley Street Clinic",
23+
additional_details="First line\nSecond line",
24+
)
25+
26+
presenter = BenignLumpHistoryItemPresenter(item)
27+
28+
assert presenter.summary_list_params == {
29+
"rows": [
30+
{
31+
"key": {"text": "Procedures"},
32+
"value": {
33+
"html": (
34+
"Right breast: Needle biopsy, Lump removed<br>"
35+
"Left breast: No procedures"
36+
)
37+
},
38+
},
39+
{
40+
"key": {"text": "Procedure year"},
41+
"value": {"html": "2015"},
42+
},
43+
{
44+
"key": {"text": "Procedure location"},
45+
"value": {
46+
"html": ("At a private clinic in the UK: Harley Street Clinic")
47+
},
48+
},
49+
{
50+
"key": {"text": "Additional details"},
51+
"value": {"html": "First line<br>Second line"},
52+
},
53+
],
54+
}

manage_breast_screening/nonprod/management/commands/seed_demo_data.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from manage_breast_screening.participants.models import (
2424
Appointment,
2525
AppointmentStatus,
26+
BenignLumpHistoryItem,
2627
BreastAugmentationHistoryItem,
2728
BreastCancerHistoryItem,
2829
ImplantedMedicalDeviceHistoryItem,
@@ -36,6 +37,7 @@
3637
from manage_breast_screening.participants.tests.factories import (
3738
AppointmentFactory,
3839
AppointmentStatusFactory,
40+
BenignLumpHistoryItemFactory,
3941
BreastAugmentationHistoryItemFactory,
4042
BreastCancerHistoryItemFactory,
4143
ImplantedMedicalDeviceHistoryItemFactory,
@@ -198,6 +200,11 @@ def create_medical_information(self, appointment, medical_information_key):
198200
appointment, implanted_medical_device_history_item
199201
)
200202

203+
for benign_lump_history_item in medical_information_key.get(
204+
"benign_lump_history_items", []
205+
):
206+
self.create_benign_lump_history_item(appointment, benign_lump_history_item)
207+
201208
for breast_augmentation_history_item in medical_information_key.get(
202209
"breast_augmentation_history_items", []
203210
):
@@ -236,6 +243,11 @@ def create_other_procedure_history_item(
236243
appointment=appointment, **other_procedure_history_item
237244
)
238245

246+
def create_benign_lump_history_item(self, appointment, benign_lump_history_item):
247+
BenignLumpHistoryItemFactory(
248+
appointment=appointment, **benign_lump_history_item
249+
)
250+
239251
def create_participant(self, **participant_key):
240252
address_key = participant_key.pop("address", None)
241253
previous_mammograms_key = participant_key.pop("previous_mammograms", [])
@@ -275,6 +287,7 @@ def reset_db(self):
275287
BreastCancerHistoryItem.objects.all().delete()
276288
ImplantedMedicalDeviceHistoryItem.objects.all().delete()
277289
OtherProcedureHistoryItem.objects.all().delete()
290+
BenignLumpHistoryItem.objects.all().delete()
278291
AppointmentStatus.objects.all().delete()
279292
Appointment.objects.all().delete()
280293
ParticipantReportedMammogram.objects.all().delete()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Generated by Django 5.2.7 on 2025-11-11 13:56
2+
3+
import django.contrib.postgres.fields
4+
import django.db.models.deletion
5+
import uuid
6+
from django.db import migrations, models
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
('participants', '0037_otherprocedurehistoryitem'),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name='BenignLumpHistoryItem',
18+
fields=[
19+
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
20+
('created_at', models.DateTimeField(auto_now_add=True)),
21+
('updated_at', models.DateTimeField(auto_now=True)),
22+
('right_breast_procedures', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(choices=[('NEEDLE_BIOPSY', 'Needle biopsy'), ('LUMP_REMOVED', 'Lump removed'), ('NO_PROCEDURES', 'No procedures')]), default=list, size=None)),
23+
('left_breast_procedures', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(choices=[('NEEDLE_BIOPSY', 'Needle biopsy'), ('LUMP_REMOVED', 'Lump removed'), ('NO_PROCEDURES', 'No procedures')]), default=list, size=None)),
24+
('procedure_year', models.IntegerField(null=True)),
25+
('procedure_location', models.CharField(choices=[('NHS_HOSPITAL', 'At an NHS hospital'), ('PRIVATE_CLINIC_UK', 'At a private clinic in the UK'), ('OUTSIDE_UK', 'Outside the UK'), ('MULTIPLE_LOCATIONS', 'In multiple locations'), ('EXACT_LOCATION_UNKNOWN', 'Exact location unknown')])),
26+
('procedure_location_details', models.CharField(blank=True, default='')),
27+
('additional_details', models.TextField(blank=True, default='')),
28+
('appointment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='benign_lump_history_items', to='participants.appointment')),
29+
],
30+
options={
31+
'abstract': False,
32+
},
33+
),
34+
]

manage_breast_screening/participants/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .appointment import Appointment, AppointmentStatus
2+
from .benign_lump_history_item import BenignLumpHistoryItem
23
from .breast_augmentation_history_item import BreastAugmentationHistoryItem
34
from .breast_cancer_history_item import BreastCancerHistoryItem
45
from .ethnicity import Ethnicity
@@ -12,6 +13,7 @@
1213
__all__ = [
1314
"Appointment",
1415
"AppointmentStatus",
16+
"BenignLumpHistoryItem",
1517
"BreastAugmentationHistoryItem",
1618
"BreastCancerHistoryItem",
1719
"ImplantedMedicalDeviceHistoryItem",
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from django.contrib.postgres.fields import ArrayField
2+
from django.db import models
3+
4+
from ...core.models import BaseModel
5+
from .appointment import Appointment
6+
7+
8+
class BenignLumpHistoryItem(BaseModel):
9+
class Procedure(models.TextChoices):
10+
NEEDLE_BIOPSY = "NEEDLE_BIOPSY", "Needle biopsy"
11+
LUMP_REMOVED = "LUMP_REMOVED", "Lump removed"
12+
NO_PROCEDURES = "NO_PROCEDURES", "No procedures"
13+
14+
class ProcedureLocation(models.TextChoices):
15+
NHS_HOSPITAL = "NHS_HOSPITAL", "At an NHS hospital"
16+
PRIVATE_CLINIC_UK = "PRIVATE_CLINIC_UK", "At a private clinic in the UK"
17+
OUTSIDE_UK = "OUTSIDE_UK", "Outside the UK"
18+
MULTIPLE_LOCATIONS = "MULTIPLE_LOCATIONS", "In multiple locations"
19+
EXACT_LOCATION_UNKNOWN = "EXACT_LOCATION_UNKNOWN", "Exact location unknown"
20+
21+
appointment = models.ForeignKey(
22+
Appointment,
23+
on_delete=models.PROTECT,
24+
related_name="benign_lump_history_items",
25+
)
26+
right_breast_procedures = ArrayField(
27+
base_field=models.CharField(choices=Procedure),
28+
default=list,
29+
)
30+
left_breast_procedures = ArrayField(
31+
base_field=models.CharField(choices=Procedure),
32+
default=list,
33+
)
34+
procedure_year = models.IntegerField(null=True)
35+
procedure_location = models.CharField(choices=ProcedureLocation)
36+
procedure_location_details = models.CharField(blank=True, null=False, default="")
37+
additional_details = models.TextField(blank=True, null=False, default="")

0 commit comments

Comments
 (0)