Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion manage_breast_screening/clinics/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def check_in(request, pk, appointment_pk):
appointment = provider.appointments.get(pk=appointment_pk)
except Appointment.DoesNotExist:
raise Http404("Appointment not found")
appointment.statuses.create(state=AppointmentStatus.CHECKED_IN)
appointment.statuses.create(name=AppointmentStatus.CHECKED_IN)

return redirect("clinics:show", pk=pk)

Expand Down
12 changes: 11 additions & 1 deletion manage_breast_screening/data/west_tester_today_clinic_data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ clinic:
statuses:
- CONFIRMED
- CHECKED_IN
- STARTED
screening_episode:
id: b33ce2c9-6b96-4975-9439-3beb60333d4e
participant:
Expand Down Expand Up @@ -73,6 +74,8 @@ clinic:
statuses:
- CONFIRMED
- CHECKED_IN
- STARTED
- IDENTITY_CONFIRMED
screening_episode:
id: 9bbdccba-ce84-4cc6-b980-da147c0d6d15
participant:
Expand Down Expand Up @@ -107,6 +110,9 @@ clinic:
statuses:
- CONFIRMED
- CHECKED_IN
- STARTED
- IDENTITY_CONFIRMED
- MEDICAL_INFORMATION_REVIEWED
screening_episode:
id: 3b6b2da9-9dda-415d-89d7-f4c5b5ec029a
participant:
Expand Down Expand Up @@ -141,6 +147,10 @@ clinic:
statuses:
- CONFIRMED
- CHECKED_IN
- STARTED
- IDENTITY_CONFIRMED
- MEDICAL_INFORMATION_REVIEWED
- IMAGES_TAKEN
screening_episode:
id: 0314777f-907c-4372-a137-e067f15a7662
participant:
Expand Down Expand Up @@ -696,7 +706,7 @@ clinic:
appointment:
id: 0a382d89-0042-49b8-87ba-fa0d9c817fd3
statuses:
- IN_PROGRESS
- STARTED
screening_episode:
id: 1ddfad46-b4de-47b9-b2ce-50a76e2d1a57
participant:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ def save(self):
self.instance.stopped_reasons = reasons_json
self.instance.reinvite = self.cleaned_data["decision"]
self.instance.save()
self.instance.statuses.create(state=AppointmentStatus.ATTENDED_NOT_SCREENED)
self.instance.statuses.create(name=AppointmentStatus.ATTENDED_NOT_SCREENED)

return self.instance
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def can_be_made_special(self):

@cached_property
def can_be_checked_in(self):
return self._appointment.current_status.state == AppointmentStatus.CONFIRMED
return self._appointment.current_status.name == AppointmentStatus.CONFIRMED

@cached_property
def active(self):
Expand All @@ -89,17 +89,21 @@ def special_appointment_tag_properties(self):
@cached_property
def current_status(self):
current_status = self._appointment.current_status

colour = status_colour(current_status.state)
colour = status_colour(current_status)
display_text = (
"In progress"
if current_status.is_in_progress()
else current_status.get_name_display()
)

return {
"classes": (
f"nhsuk-tag--{colour} app-u-nowrap" if colour else "app-u-nowrap"
),
"text": current_status.get_state_display(),
"key": current_status.state,
"is_confirmed": current_status.state == AppointmentStatus.CONFIRMED,
"is_screened": current_status.state == AppointmentStatus.SCREENED,
"text": display_text,
"key": current_status.name,
"is_confirmed": current_status.name == AppointmentStatus.CONFIRMED,
"is_screened": current_status.name == AppointmentStatus.SCREENED,
}

@cached_property
Expand All @@ -108,7 +112,7 @@ def status_attribution(self):
return (
"with " + self._appointment.current_status.created_by.get_short_name()
)
elif self._appointment.current_status.is_final_state():
elif self._appointment.current_status.is_final_status():
return "by " + self._appointment.current_status.created_by.get_short_name()
else:
return None
Expand All @@ -135,7 +139,7 @@ def show_status_bar_for(self, user):
# The appointment status bar should only display if the current user is the one that has the appointment 'in progress'
current_status = self.appointment._appointment.current_status
return (
current_status.state == AppointmentStatus.IN_PROGRESS
current_status.is_in_progress()
and user.nhs_uid == current_status.created_by.nhs_uid
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class ActionNotPermitted(Exception):
"""


class InvalidState(Exception):
class InvalidStatus(Exception):
"""
The appointment is not in a valid state to perform the action.
The appointment is not in a valid status to perform the action.
"""


Expand All @@ -26,8 +26,7 @@ class ActionPerformedByDifferentUser(Exception):

class AppointmentStatusUpdater:
"""
Transition an appointment to another state.
Each state is logged in AppointmentStatusHistory and associated with a user.
Transition an appointment to another status.
"""

def __init__(self, appointment, current_user):
Expand All @@ -36,13 +35,13 @@ def __init__(self, appointment, current_user):

def check_in(self):
return self._transition(
to_state=AppointmentStatus.CHECKED_IN,
from_states=(AppointmentStatus.CONFIRMED,),
to_status=AppointmentStatus.CHECKED_IN,
from_statuses=(AppointmentStatus.CONFIRMED,),
)

@staticmethod
def is_startable(appointment):
return appointment is not None and appointment.current_status.state in (
return appointment is not None and appointment.current_status.name in (
AppointmentStatus.CONFIRMED,
AppointmentStatus.CHECKED_IN,
)
Expand All @@ -54,46 +53,46 @@ def start(self):
raise ActionNotPermitted(self.appointment.current_status)

return self._transition(
to_state=AppointmentStatus.IN_PROGRESS,
from_states=(AppointmentStatus.CONFIRMED, AppointmentStatus.CHECKED_IN),
to_status=AppointmentStatus.STARTED,
from_statuses=(AppointmentStatus.CONFIRMED, AppointmentStatus.CHECKED_IN),
)

def cancel(self):
return self._transition(
to_state=AppointmentStatus.CANCELLED,
from_states=(AppointmentStatus.CONFIRMED,),
to_status=AppointmentStatus.CANCELLED,
from_statuses=(AppointmentStatus.CONFIRMED,),
)

def mark_did_not_attend(self):
return self._transition(
to_state=AppointmentStatus.DID_NOT_ATTEND,
from_states=(AppointmentStatus.CONFIRMED,),
to_status=AppointmentStatus.DID_NOT_ATTEND,
from_statuses=(AppointmentStatus.CONFIRMED,),
)

def screen(self, partial=False):
return self._transition(
to_state=(
to_status=(
AppointmentStatus.PARTIALLY_SCREENED
if partial
else AppointmentStatus.SCREENED
),
from_states=(AppointmentStatus.IN_PROGRESS,),
from_statuses=(AppointmentStatus.STARTED,),
)

def _transition(self, to_state, from_states):
current_state = self.appointment.current_status.state
if current_state != to_state and current_state not in from_states:
raise InvalidState(self.appointment.current_status)
def _transition(self, to_status, from_statuses):
current_status = self.appointment.current_status.name
if current_status != to_status and current_status not in from_statuses:
raise InvalidStatus(self.appointment.current_status)

return self._get_or_create(state=to_state)
return self._get_or_create(status=to_status)

def _get_or_create(self, state):
def _get_or_create(self, status):
"""
Make operations idempotent, providing that we're not changing
the created_by user.
"""
new_status, created = self.appointment.statuses.get_or_create(
state=state,
name=status,
defaults=dict(created_by=self.current_user),
)

Expand Down
Loading