Skip to content
Open
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
12 changes: 12 additions & 0 deletions care/emr/api/viewsets/scheduling/availability.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ def convert_availability_and_exceptions_to_slots(availabilities, exceptions, day

def lock_create_appointment(token_slot, patient, created_by, note):
with Lock(f"booking:resource:{token_slot.resource.id}"), transaction.atomic():
if (
token_slot.resource.resource_type
== SchedulableResourceTypeOptions.healthcare_service.value
):
healthcare_service = token_slot.resource.healthcare_service
if (
not healthcare_service
or healthcare_service.internal_type != "scheduling"
):
raise ValidationError(
"Appointments should have only healthcare service of type schedulable"
)
if token_slot.end_datetime < timezone.now():
raise ValidationError("Slot is already past")
if token_slot.allocated >= token_slot.availability.tokens_per_slot:
Expand Down
156 changes: 156 additions & 0 deletions care/emr/tests/test_booking_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from care.emr.models import (
Availability,
AvailabilityException,
HealthcareService,
SchedulableResource,
Schedule,
TokenBooking,
Expand Down Expand Up @@ -827,6 +828,161 @@ def test_over_booking_a_slot(self):
)
self.assertContains(response, status_code=400, text="Slot is already full")

def test_create_appointment_with_healthcare_service_schedulable_type(self):
"""Users can create appointment with healthcare service of type schedulable."""
permissions = [SchedulePermissions.can_write_booking.name]
role = self.create_role_with_permissions(permissions)
self.attach_role_facility_organization_user(self.organization, self.user, role)

healthcare_service = HealthcareService.objects.create(
facility=self.facility,
name="Test Healthcare Service",
internal_type="scheduling",
)
resource = SchedulableResource.objects.create(
resource_type=SchedulableResourceTypeOptions.healthcare_service.value,
healthcare_service=healthcare_service,
facility=self.facility,
)
schedule = Schedule.objects.create(
resource=resource,
name="Healthcare Service Schedule",
valid_from=datetime.now(UTC) - timedelta(days=30),
valid_to=datetime.now(UTC) + timedelta(days=30),
is_public=True,
)
availability = Availability.objects.create(
schedule=schedule,
name="Test Availability",
slot_type=SlotTypeOptions.appointment.value,
slot_size_in_minutes=30,
tokens_per_slot=1,
create_tokens=False,
reason="Regular schedule",
availability=[
{"day_of_week": 0, "start_time": "09:00:00", "end_time": "13:00:00"},
],
)
slot = TokenSlot.objects.create(
resource=resource,
availability=availability,
start_datetime=datetime.now(UTC) + timedelta(minutes=30),
end_datetime=datetime.now(UTC) + timedelta(minutes=60),
allocated=0,
)

data = self.get_appointment_data()
response = self.client.post(
self._get_create_appointment_url(slot.external_id), data, format="json"
)
self.assertEqual(response.status_code, 200)

def test_create_appointment_with_healthcare_service_non_schedulable_type(self):
"""Users cannot create appointment with healthcare service of non-schedulable type."""
permissions = [SchedulePermissions.can_write_booking.name]
role = self.create_role_with_permissions(permissions)
self.attach_role_facility_organization_user(self.organization, self.user, role)

healthcare_service = HealthcareService.objects.create(
facility=self.facility,
name="Test Healthcare Service",
internal_type="lab",
)
resource = SchedulableResource.objects.create(
resource_type=SchedulableResourceTypeOptions.healthcare_service.value,
healthcare_service=healthcare_service,
facility=self.facility,
)
schedule = Schedule.objects.create(
resource=resource,
name="Healthcare Service Schedule",
valid_from=datetime.now(UTC) - timedelta(days=30),
valid_to=datetime.now(UTC) + timedelta(days=30),
is_public=True,
)
availability = Availability.objects.create(
schedule=schedule,
name="Test Availability",
slot_type=SlotTypeOptions.appointment.value,
slot_size_in_minutes=30,
tokens_per_slot=1,
create_tokens=False,
reason="Regular schedule",
availability=[
{"day_of_week": 0, "start_time": "09:00:00", "end_time": "13:00:00"},
],
)
slot = TokenSlot.objects.create(
resource=resource,
availability=availability,
start_datetime=datetime.now(UTC) + timedelta(minutes=30),
end_datetime=datetime.now(UTC) + timedelta(minutes=60),
allocated=0,
)

data = self.get_appointment_data()
response = self.client.post(
self._get_create_appointment_url(slot.external_id), data, format="json"
)
self.assertContains(
response,
"Appointments should have only healthcare service of type schedulable",
status_code=400,
)

def test_create_appointment_with_healthcare_service_no_internal_type(self):
"""Users cannot create appointment with healthcare service without internal type."""
permissions = [SchedulePermissions.can_write_booking.name]
role = self.create_role_with_permissions(permissions)
self.attach_role_facility_organization_user(self.organization, self.user, role)

healthcare_service = HealthcareService.objects.create(
facility=self.facility,
name="Test Healthcare Service",
internal_type=None,
)
resource = SchedulableResource.objects.create(
resource_type=SchedulableResourceTypeOptions.healthcare_service.value,
healthcare_service=healthcare_service,
facility=self.facility,
)
schedule = Schedule.objects.create(
resource=resource,
name="Healthcare Service Schedule",
valid_from=datetime.now(UTC) - timedelta(days=30),
valid_to=datetime.now(UTC) + timedelta(days=30),
is_public=True,
)
availability = Availability.objects.create(
schedule=schedule,
name="Test Availability",
slot_type=SlotTypeOptions.appointment.value,
slot_size_in_minutes=30,
tokens_per_slot=1,
create_tokens=False,
reason="Regular schedule",
availability=[
{"day_of_week": 0, "start_time": "09:00:00", "end_time": "13:00:00"},
],
)
slot = TokenSlot.objects.create(
resource=resource,
availability=availability,
start_datetime=datetime.now(UTC) + timedelta(minutes=30),
end_datetime=datetime.now(UTC) + timedelta(minutes=60),
allocated=0,
)

data = self.get_appointment_data()
response = self.client.post(
self._get_create_appointment_url(slot.external_id), data, format="json"
)
self.assertContains(
response,
"Appointments should have only healthcare service of type schedulable",
status_code=400,
)


@ignore_warnings(category=RuntimeWarning, message=r".*received a naive datetime.*")
class TestSlotViewSetSlotStatsApis(CareAPITestBase):
Expand Down