Skip to content

Commit 537bad9

Browse files
authored
Merge pull request #89 from NHSDigital/DTOSS-9211-participant-record
Refactor the app structure
2 parents 25de16f + bef5118 commit 537bad9

54 files changed

Lines changed: 525 additions & 343 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

manage_breast_screening/templates/.eslintrc.js renamed to .eslintrc.js

File renamed without changes.
Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,8 @@
11
from django.contrib import admin
22

3-
from .models import Appointment, Clinic, ClinicSlot, Provider, ScreeningEpisode, Setting
3+
from .models import Clinic, ClinicSlot, Provider, Setting
44

5-
6-
class AppointmentAdmin(admin.ModelAdmin):
7-
list_display = [
8-
"name",
9-
"clinic_slot__starts_at",
10-
"clinic_slot__duration_in_minutes",
11-
"status",
12-
]
13-
14-
@admin.display()
15-
def name(self, obj):
16-
return obj.screening_episode.participant.full_name
17-
18-
19-
admin.site.register(Appointment, AppointmentAdmin)
205
admin.site.register(Clinic)
216
admin.site.register(ClinicSlot)
227
admin.site.register(Provider)
23-
admin.site.register(ScreeningEpisode)
248
admin.site.register(Setting)

manage_breast_screening/clinics/fixtures/clinics.json

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -86,114 +86,5 @@
8686
"starts_at": "2025-05-01T13:00:00Z",
8787
"duration_in_minutes": 30
8888
}
89-
},
90-
{
91-
"model": "clinics.screeningepisode",
92-
"pk": "1c0009ed-8cee-422b-965d-4934b77c5294",
93-
"fields": {
94-
"created_at": "2022-04-25T11:15:00Z",
95-
"updated_at": "2025-04-25T11:15:00Z",
96-
"participant": "913bb98a-c31f-4c2b-9b81-73a8eb994c20"
97-
}
98-
},
99-
{
100-
"model": "clinics.screeningepisode",
101-
"pk": "3888ca4a-2b6c-43a3-bde2-4a92649c6648",
102-
"fields": {
103-
"created_at": "2025-04-25T11:15:00Z",
104-
"updated_at": "2025-04-25T11:15:00Z",
105-
"participant": "6ffdc8dd-8f78-4fda-82a1-890f20eda7fd"
106-
}
107-
},
108-
{
109-
"model": "clinics.screeningepisode",
110-
"pk": "64cf6722-19f2-4519-89a3-cb127447c72a",
111-
"fields": {
112-
"created_at": "2025-04-25T11:15:00Z",
113-
"updated_at": "2025-04-25T11:15:00Z",
114-
"participant": "7c9d087a-63ce-4459-a3bf-8379837eb35d"
115-
}
116-
},
117-
{
118-
"model": "clinics.screeningepisode",
119-
"pk": "519593ee-6e44-41db-962a-862a09f807ad",
120-
"fields": {
121-
"created_at": "2025-04-25T11:15:00Z",
122-
"updated_at": "2025-04-25T11:15:00Z",
123-
"participant": "6f947d99-3f1f-42f4-b21c-ad7987c05d6d"
124-
}
125-
},
126-
{
127-
"model": "clinics.screeningepisode",
128-
"pk": "522fe2cb-1c41-40d5-a65d-c36695bf11b5",
129-
"fields": {
130-
"created_at": "2025-04-25T11:15:00Z",
131-
"updated_at": "2025-04-25T11:15:00Z",
132-
"participant": "2b87d44f-637b-44a7-9dfd-1e57f37d04ea"
133-
}
134-
},
135-
{
136-
"model": "clinics.screeningepisode",
137-
"pk": "ccad34c1-8e26-4c9e-a134-a0de8f997d89",
138-
"fields": {
139-
"created_at": "2025-04-25T11:15:00Z",
140-
"updated_at": "2025-04-25T11:15:00Z",
141-
"participant": "913bb98a-c31f-4c2b-9b81-73a8eb994c20"
142-
}
143-
},
144-
{
145-
"model": "clinics.appointment",
146-
"pk": "e7be35a3-8b7f-4522-9e9b-7b8e6829c1b8",
147-
"fields": {
148-
"created_at": "2025-04-25T11:20:00Z",
149-
"updated_at": "2025-04-25T11:20:00Z",
150-
"screening_episode": 6,
151-
"clinic_slot": "d1df208b-955a-4b2f-a908-2728aea6b29f",
152-
"status": "CONFIRMED"
153-
}
154-
},
155-
{
156-
"model": "clinics.appointment",
157-
"pk": "522fe2cb-1c41-40d5-a65d-c36695bf11b5",
158-
"fields": {
159-
"created_at": "2025-04-25T11:20:00Z",
160-
"updated_at": "2025-04-25T11:20:00Z",
161-
"screening_episode": "1c0009ed-8cee-422b-965d-4934b77c5294",
162-
"clinic_slot": "cc428100-3397-4263-b863-cee4326212b7",
163-
"status": "CHECKED_IN"
164-
}
165-
},
166-
{
167-
"model": "clinics.appointment",
168-
"pk": "ccad34c1-8e26-4c9e-a134-a0de8f997d89",
169-
"fields": {
170-
"created_at": "2025-04-25T11:20:00Z",
171-
"updated_at": "2025-04-25T11:20:00Z",
172-
"screening_episode": "3888ca4a-2b6c-43a3-bde2-4a92649c6648",
173-
"clinic_slot": "f657f049-a52f-4a23-ada4-834ea557336c",
174-
"status": "SCREENED"
175-
}
176-
},
177-
{
178-
"model": "clinics.appointment",
179-
"pk": "a3ad3cb1-d67a-499c-805c-845455deb60f",
180-
"fields": {
181-
"created_at": "2025-04-25T11:20:00Z",
182-
"updated_at": "2025-04-25T11:20:00Z",
183-
"screening_episode": "64cf6722-19f2-4519-89a3-cb127447c72a",
184-
"clinic_slot": "48bc626c-e8b1-44e7-a747-915c65fc2360",
185-
"status": "DID_NOT_ATTEND"
186-
}
187-
},
188-
{
189-
"model": "clinics.appointment",
190-
"pk": "e7be35a3-8b7f-4522-9e9b-7b8e6829c1b8",
191-
"fields": {
192-
"created_at": "2025-04-25T11:20:00Z",
193-
"updated_at": "2025-04-25T11:20:00Z",
194-
"screening_episode": "519593ee-6e44-41db-962a-862a09f807ad",
195-
"clinic_slot": "1c0009ed-8cee-422b-965d-4934b77c5294",
196-
"status": "CANCELLED"
197-
}
19889
}
19990
]

manage_breast_screening/templates/clinics/index.html renamed to manage_breast_screening/clinics/jinja2/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{% extends 'layout-app.html' %}
22

33
{% from 'tag/macro.jinja' import tag %}
4-
{% from '_components/count/macro.jinja' import appCount %}
5-
{% from '_components/secondary-navigation/macro.jinja' import app_secondary_navigation %}
4+
{% from 'components/count/macro.jinja' import appCount %}
5+
{% from 'components/secondary-navigation/macro.jinja' import app_secondary_navigation %}
66

77
{% block content %}
88
<h1>{{ presenter.heading }}</h1>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 5.2.1 on 2025-06-03 13:53
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("clinics", "0011_recreate_participants_linkage"),
10+
("participants", "0010_screeningepisode_appointment"),
11+
]
12+
13+
operations = [
14+
migrations.RemoveField(
15+
model_name="screeningepisode",
16+
name="participant",
17+
),
18+
migrations.DeleteModel(
19+
name="Appointment",
20+
),
21+
migrations.DeleteModel(
22+
name="ScreeningEpisode",
23+
),
24+
]

manage_breast_screening/clinics/models.py

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -145,60 +145,3 @@ class ClinicSlot(BaseModel):
145145
)
146146
starts_at = models.DateTimeField()
147147
duration_in_minutes = models.IntegerField()
148-
149-
150-
class ScreeningEpisode(BaseModel):
151-
participant = models.ForeignKey(
152-
"participants.Participant", on_delete=models.CASCADE
153-
)
154-
155-
def screening_history(self):
156-
"""
157-
Return all previous screening episodes, excluding this one, prefetching
158-
their appointment details as well.
159-
"""
160-
return (
161-
ScreeningEpisode.objects.prefetch_related(
162-
"appointment_set__clinic_slot__clinic__setting__provider"
163-
)
164-
.filter(participant__pk=self.participant.pk, pk__lt=self.pk)
165-
.order_by("-pk")
166-
)
167-
168-
def previous(self) -> "ScreeningEpisode | None":
169-
"""
170-
Return the last known screening episode
171-
"""
172-
try:
173-
return self.screening_history()[0]
174-
except IndexError:
175-
return None
176-
177-
178-
class Appointment(BaseModel):
179-
class Status:
180-
CONFIRMED = "CONFIRMED"
181-
CANCELLED = "CANCELLED"
182-
DID_NOT_ATTEND = "DID_NOT_ATTEND"
183-
CHECKED_IN = "CHECKED_IN"
184-
SCREENED = "SCREENED"
185-
PARTIALLY_SCREENED = "PARTIALLY_SCREENED"
186-
ATTENDED_NOT_SCREENED = "ATTENDED_NOT_SCREENED"
187-
188-
STATUS_CHOICES = {
189-
Status.CONFIRMED: "Confirmed",
190-
Status.CANCELLED: "Cancelled",
191-
Status.DID_NOT_ATTEND: "Did not attend",
192-
Status.CHECKED_IN: "Checked in",
193-
Status.SCREENED: "Screened",
194-
Status.PARTIALLY_SCREENED: "Partially screened",
195-
Status.ATTENDED_NOT_SCREENED: "Attended not screened",
196-
}
197-
198-
screening_episode = models.ForeignKey(ScreeningEpisode, on_delete=models.CASCADE)
199-
clinic_slot = models.ForeignKey(ClinicSlot, on_delete=models.CASCADE)
200-
status = models.CharField(
201-
choices=STATUS_CHOICES, max_length=50, default=Status.CONFIRMED
202-
)
203-
reinvite = models.BooleanField(default=False)
204-
stopped_reasons = models.JSONField(null=True, blank=True)

manage_breast_screening/clinics/tests/factories.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from factory.fuzzy import FuzzyChoice
66

77
from manage_breast_screening.clinics import models
8-
from manage_breast_screening.participants.tests.factories import ParticipantFactory
98

109

1110
class ProviderFactory(DjangoModelFactory):
@@ -49,18 +48,3 @@ class Meta:
4948
lambda n: datetime.datetime(2025, 1, 1, 9) + datetime.timedelta(hours=n)
5049
)
5150
duration_in_minutes = 15
52-
53-
54-
class ScreeningEpisodeFactory(DjangoModelFactory):
55-
class Meta:
56-
model = models.ScreeningEpisode
57-
58-
participant = SubFactory(ParticipantFactory)
59-
60-
61-
class AppointmentFactory(DjangoModelFactory):
62-
class Meta:
63-
model = models.Appointment
64-
65-
clinic_slot = SubFactory(ClinicSlotFactory)
66-
screening_episode = SubFactory(ScreeningEpisodeFactory)

manage_breast_screening/clinics/tests/test_models.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from manage_breast_screening.clinics import models
99

10-
from .factories import ClinicFactory, ScreeningEpisodeFactory
10+
from .factories import ClinicFactory
1111

1212

1313
def test_clinic_is_scheduled():
@@ -28,15 +28,3 @@ def test_status_filtering():
2828
assertQuerySetEqual(models.Clinic.objects.today(), {current}, ordered=False)
2929
assertQuerySetEqual(models.Clinic.objects.upcoming(), {future}, ordered=False)
3030
assertQuerySetEqual(models.Clinic.objects.completed(), {past}, ordered=False)
31-
32-
33-
@pytest.mark.django_db
34-
class TestScreeningEvent:
35-
def test_no_previous_screening_episode(self):
36-
episode = ScreeningEpisodeFactory.create()
37-
assert episode.previous() is None
38-
39-
def test_previous_screening_episode(self):
40-
episode = ScreeningEpisodeFactory.create()
41-
next_episode = ScreeningEpisodeFactory.create(participant=episode.participant)
42-
assert next_episode.previous() == episode

manage_breast_screening/clinics/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ def clinic_list(request, filter="today"):
1818

1919
return render(
2020
request,
21-
"clinics/index.html",
21+
"index.html",
2222
context={"presenter": presenter},
2323
)

manage_breast_screening/config/settings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def boolean_env(key, default=None):
5959
"django.contrib.staticfiles",
6060
"manage_breast_screening.clinics",
6161
"manage_breast_screening.participants",
62-
"manage_breast_screening.record_a_mammogram",
62+
"manage_breast_screening.mammograms",
6363
]
6464

6565
MIDDLEWARE = [
@@ -78,7 +78,7 @@ def boolean_env(key, default=None):
7878
TEMPLATES = [
7979
{
8080
"BACKEND": "django.template.backends.jinja2.Jinja2",
81-
"DIRS": [BASE_DIR / "templates"],
81+
"DIRS": [BASE_DIR / "jinja2"],
8282
"APP_DIRS": True,
8383
"OPTIONS": {
8484
"environment": "manage_breast_screening.config.jinja2_env.environment",

0 commit comments

Comments
 (0)