Skip to content

Commit d7f1e57

Browse files
committed
wip add extract info to appointments on creation
to do: tidy up file name extraction tidy up different .dat files and testing scenarios
1 parent 82458d1 commit d7f1e57

File tree

4 files changed

+70
-5
lines changed

4 files changed

+70
-5
lines changed

manage_breast_screening/notifications/management/commands/create_appointments.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Appointment,
1515
AppointmentStatusChoices,
1616
Clinic,
17+
Extract,
1718
)
1819
from manage_breast_screening.notifications.services.blob_storage import BlobStorage
1920

@@ -53,6 +54,15 @@ def handle(self, *args, **options):
5354

5455
data_frame = self.raw_data_to_data_frame(blob_content)
5556

57+
file_headers = self.get_file_header(blob_content)
58+
59+
extract = Extract.objects.create(
60+
sequence_number=int(file_headers[1].strip()),
61+
filename=blob.name,
62+
bso_code=data_frame.iloc[0]["BSO"],
63+
record_count=file_headers[4],
64+
)
65+
5666
for idx, row in data_frame.iterrows():
5767
if self.is_not_holding_clinic(row):
5868
clinic, clinic_created = self.find_or_create_clinic(row)
@@ -62,6 +72,9 @@ def handle(self, *args, **options):
6272
appt, appt_created = self.update_or_create_appointment(
6373
row, clinic
6474
)
75+
76+
extract.appointments.add(appt) if appt is not None else None
77+
6578
logger.info("Processed %s rows from %s", len(data_frame), blob.name)
6679

6780
def is_not_holding_clinic(self, row):
@@ -79,6 +92,9 @@ def raw_data_to_data_frame(self, raw_data: str) -> pandas.DataFrame:
7992
skipfooter=1,
8093
)
8194

95+
def get_file_header(self, raw_data: str) -> pandas.Series:
96+
return raw_data.split("\n")[0].replace('"', "").split("|")
97+
8298
def find_or_create_clinic(self, row: pandas.Series) -> tuple[Clinic, bool]:
8399
return Clinic.objects.get_or_create(
84100
bso_code=row["BSO"],
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"NBSSAPPT_HDR"|"00000013"|"20250128"|"170922"|"000003"
1+
"NBSSAPPT_HDR"|"00000014"|"20250128"|"170922"|"000003"
22
"NBSSAPPT_FLDS"|"Sequence"|"BSO"|"Action"|"Clinic Code"|"Holding Clinic"|"Status"|"Attended Not Scr"|"Appointment ID"|"NHS Num"|"Episode Type"|"Episode Start"|"Batch ID"|"Screen or Asses"|"Screen Appt num"|"Booked By"|"Cancelled By"|"Appt Date"|"Appt Time"|"Location"|"Clinic Name"|"Clinic Name (Let)"|"Clinic Address 1"|"Clinic Address 2"|"Clinic Address 3"|"Clinic Address 4"|"Clinic Address 5"|"Postcode"|"Action Timestamp"
33
"NBSSAPPT_DATA"|"000001"|"KMK"|"C"|"BU011"|"N"|"C"|"N"|"BU011-67278-RA1-DN-Y1111-1"|"9449305552"|"F"|"20250128"|"KMK001326"|"S"|"1"|"H"|"C"|"20250314"|"1345"|"MKGH"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250128-175555"
44
"NBSSAPPT_END"|"00000013"|"20250128"|"17:09:22"|"000003"

manage_breast_screening/notifications/tests/fixtures/ABC_20241202091521_APPT_109.dat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"NBSSAPPT_HDR"|"00000013"|"20250128"|"170922"|"000003"
1+
"NBSSAPPT_HDR"|"00000014"|"20250128"|"170922"|"000003"
22
"NBSSAPPT_FLDS"|"Sequence"|"BSO"|"Action"|"Clinic Code"|"Holding Clinic"|"Status"|"Attended Not Scr"|"Appointment ID"|"NHS Num"|"Episode Type"|"Episode Start"|"Batch ID"|"Screen or Asses"|"Screen Appt num"|"Booked By"|"Cancelled By"|"Appt Date"|"Appt Time"|"Location"|"Clinic Name"|"Clinic Name (Let)"|"Clinic Address 1"|"Clinic Address 2"|"Clinic Address 3"|"Clinic Address 4"|"Clinic Address 5"|"Postcode"|"Action Timestamp"
33
"NBSSAPPT_DATA"|"000007"|"KMK"|"B"|"BU011"|"N"|"A"|"N"|"BU011-67278-RA1-DN-Y1111-1"|"9449305552"|"S"|"20250128"|"KMK001326"|"S"|"1"|"H"|""|"20250314"|"1345"|"MKGH"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250128-154003"
44
"NBSSAPPT_DATA"|"000008"|"KMK"|"B"|"BU011"|"N"|"D"|""|"BU011-67278-RA1-DN-X0000-1"|"9449306621"|"F"|"20250128"|"KMK001326"|"S"|"1"|"H"|""|"20250314"|"1445"|"MKGH"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250128-154004"

manage_breast_screening/notifications/tests/management/commands/test_create_appointments.py

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
from contextlib import contextmanager
33
from datetime import datetime, timezone
4-
from unittest.mock import Mock, PropertyMock, patch
4+
from unittest.mock import Mock, patch
55

66
import pytest
77
from azure.storage.blob import BlobProperties
@@ -10,7 +10,12 @@
1010
from manage_breast_screening.notifications.management.commands.create_appointments import (
1111
Command,
1212
)
13-
from manage_breast_screening.notifications.models import ZONE_INFO, Appointment, Clinic
13+
from manage_breast_screening.notifications.models import (
14+
ZONE_INFO,
15+
Appointment,
16+
Clinic,
17+
Extract,
18+
)
1419
from manage_breast_screening.notifications.tests.factories import (
1520
AppointmentFactory,
1621
ClinicFactory,
@@ -44,7 +49,7 @@ def stored_blob_data(prefix_dir: str, filenames: list[str]):
4449
mock_blob_contents = []
4550
for filename in filenames:
4651
mock_blob = Mock(spec=BlobProperties)
47-
mock_blob.name = PropertyMock(return_value=f"{prefix_dir}/{filename}")
52+
mock_blob.name = f"{prefix_dir}/{filename}"
4853
mock_blobs.append(mock_blob)
4954
mock_blob_contents.append(open(fixture_file_path(filename)).read())
5055

@@ -118,6 +123,9 @@ def test_handle_creates_records(self):
118123

119124
assert appointments[1].assessment is True
120125

126+
assert Extract.objects.count() == 1
127+
assert Extract.objects.first().appointments.count() == 2
128+
121129
def test_handles_holding_clinics(self):
122130
"""Test does not create appointments for valid NBSS data marked as a Holding Clinic"""
123131
today_dirname = datetime.today().strftime("%Y-%m-%d")
@@ -318,3 +326,44 @@ def test_calls_command_handler(
318326
Command().handle(**{"date_str": "2000-01-01"})
319327

320328
mock_command_handler.assert_called_with("CreateAppointments")
329+
330+
def test_create_extract_and_cancel(self):
331+
"""Test Extract creation for new booked appointments in NBSS data, stored in Azure storage blob"""
332+
today_dirname = datetime.now().strftime("%Y-%m-%d")
333+
334+
with stored_blob_data(today_dirname, [VALID_DATA_FILE]):
335+
Command().handle(**{"date_str": today_dirname})
336+
337+
assert Extract.objects.count() == 1
338+
first_extract = Extract.objects.all()[0]
339+
assert first_extract.appointments.count() == 2
340+
assert first_extract.sequence_number == 13
341+
assert first_extract.bso_code == "KMK"
342+
assert first_extract.filename == f"{today_dirname}/{VALID_DATA_FILE}"
343+
assert first_extract.record_count == 3
344+
345+
with stored_blob_data(today_dirname, [UPDATED_APPOINTMENT_FILE]):
346+
Command().handle(**{"date_str": today_dirname})
347+
348+
assert Extract.objects.count() == 2
349+
second_extract = Extract.objects.all()[1]
350+
351+
assert (
352+
first_extract.appointments.first().id
353+
== second_extract.appointments.get().id
354+
)
355+
356+
@pytest.mark.django_db(transaction=True)
357+
def test_errors_when_same_extract(self):
358+
today_dirname = datetime.now().strftime("%Y-%m-%d")
359+
360+
with stored_blob_data(today_dirname, [VALID_DATA_FILE]):
361+
Command().handle(**{"date_str": today_dirname})
362+
363+
assert Appointment.objects.count() == 2
364+
365+
with stored_blob_data(today_dirname, [VALID_DATA_FILE]):
366+
with pytest.raises(CommandError):
367+
Command().handle(**{"date_str": today_dirname})
368+
369+
assert Appointment.objects.count() == 2

0 commit comments

Comments
 (0)