Skip to content

Commit aec0d49

Browse files
committed
use a form for available slots
1 parent 65ea1d5 commit aec0d49

File tree

5 files changed

+36
-23
lines changed

5 files changed

+36
-23
lines changed

appointment/forms.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
WorkingHours
1717
)
1818
from .utils.db_helpers import get_user_model
19+
from .utils.validators import not_in_the_past
20+
21+
22+
class SlotForm(forms.Form):
23+
selected_date = forms.DateField(validators=[not_in_the_past])
24+
staff_member = forms.ModelChoiceField(StaffMember.objects.all(), error_messages={'invalid_choice': 'Staff member does not exist'})
1925

2026

2127
class AppointmentRequestForm(forms.ModelForm):

appointment/static/js/appointments.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ function fetchNonWorkingDays(staffId, callback) {
158158
return; // Exit the function early
159159
}
160160
let ajaxData = {
161-
'staff_id': staffId,
161+
'staff_member': staffId,
162162
};
163163

164164
$.ajax({
@@ -231,7 +231,7 @@ function getAvailableSlots(selectedDate, staffId = null) {
231231

232232
let ajaxData = {
233233
'selected_date': selectedDate,
234-
'staff_id': staffId,
234+
'staff_member': staffId,
235235
};
236236
fetchNonWorkingDays(staffId, function (nonWorkingDays) {
237237
// Check if nonWorkingDays is an array
@@ -325,7 +325,7 @@ function requestNextAvailableSlot(serviceId) {
325325
return;
326326
}
327327
let ajaxData = {
328-
'staff_id': staffId,
328+
'staff_member': staffId,
329329
};
330330
$.ajax({
331331
url: requestNextAvailableSlotURL,

appointment/tests/test_views.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,23 @@ def setUp(self):
4343

4444
def test_get_available_slots_ajax(self):
4545
"""get_available_slots_ajax view should return a JSON response with available slots for the selected date."""
46-
response = self.client.get(self.url, {'selected_date': date.today().isoformat()},
46+
response = self.client.get(self.url, {'selected_date': date.today().isoformat(), 'staff_member': self.staff_member1.id},
4747
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
48-
self.assertEqual(response.status_code, 403)
4948
response_data = response.json()
5049
self.assertIn('date_chosen', response_data)
5150
self.assertIn('available_slots', response_data)
5251
self.assertFalse(response_data.get('error'))
5352

54-
def test_get_available_slots_ajax_past_date(self):
53+
def test_get_available_slots_ajax_invalid_form(self):
5554
"""get_available_slots_ajax view should return an error if the selected date is in the past."""
5655
past_date = (date.today() - timedelta(days=1)).isoformat()
5756
response = self.client.get(self.url, {'selected_date': past_date}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
58-
self.assertEqual(response.status_code, 200)
5957
self.assertEqual(response.json()['error'], True)
6058
self.assertEqual(response.json()['message'], 'Date is in the past')
59+
# invalid staff id
60+
response = self.client.get(self.url, {'selected_date': date.today(), 'staff_member': 999}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
61+
self.assertEqual(response.json()['error'], True)
62+
self.assertEqual(response.json()['message'], 'Staff member does not exist')
6163

6264

6365
class AppointmentRequestTestCase(BaseTest):

appointment/utils/validators.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.core.exceptions import ValidationError
2+
from django.utils.translation import gettext_lazy as _
3+
4+
5+
def not_in_the_past(date):
6+
if date < date.today():
7+
raise ValidationError(_('Date is in the past'))

appointment/views.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from django.utils.timezone import get_current_timezone_name
2222
from django.utils.translation import gettext as _
2323

24-
from appointment.forms import AppointmentForm, AppointmentRequestForm
24+
from appointment.forms import AppointmentForm, AppointmentRequestForm, SlotForm
2525
from appointment.logger_config import logger
2626
from appointment.models import (
2727
Appointment, AppointmentRequest, AppointmentRescheduleHistory, Config, DayOff, EmailVerificationCode,
@@ -57,28 +57,23 @@ def get_available_slots_ajax(request):
5757
:param request: The request instance.
5858
:return: A JSON response containing available slots, selected date, an error flag, and an optional error message.
5959
"""
60-
selected_date = convert_str_to_date(request.GET.get('selected_date'))
61-
staff_id = request.GET.get('staff_id')
6260

63-
if selected_date < date.today():
61+
slot_form = SlotForm(request.GET)
62+
if not slot_form.is_valid():
6463
custom_data = {'error': True, 'available_slots': [], 'date_chosen': ''}
65-
message = _('Date is in the past')
64+
if 'selected_date' in slot_form.errors:
65+
error_code = ErrorCode.PAST_DATE
66+
elif 'staff_member' in slot_form.errors:
67+
error_code = ErrorCode.STAFF_ID_REQUIRED
68+
message = list(slot_form.errors.as_data().items())[0][1][0].messages[0] # dirty way to keep existing behavior
6669
return json_response(message=message, custom_data=custom_data, success=False,
67-
error_code=ErrorCode.PAST_DATE)
70+
error_code=error_code)
6871

72+
selected_date = slot_form.cleaned_data['selected_date']
73+
sm = slot_form.cleaned_data['staff_member']
6974
date_chosen = selected_date.strftime("%a, %B %d, %Y")
7075
custom_data = {'date_chosen': date_chosen}
7176

72-
# If no staff_id provided, return an empty list of slots
73-
if not staff_id or staff_id == 'none':
74-
custom_data['available_slots'] = []
75-
custom_data['error'] = False
76-
message = _('No staff member selected')
77-
return json_response(message=message, custom_data=custom_data, success=False,
78-
error_code=ErrorCode.STAFF_ID_REQUIRED, status=403)
79-
80-
sm = get_object_or_404(StaffMember, pk=staff_id)
81-
custom_data['staff_member'] = sm.get_staff_member_name()
8277
days_off_exist = check_day_off_for_staff(staff_member=sm, date=selected_date)
8378
if days_off_exist:
8479
message = _("Day off. Please select another date!")
@@ -87,6 +82,8 @@ def get_available_slots_ajax(request):
8782
# if selected_date is not a working day for the staff, return an empty list of slots and 'message' is Day Off
8883
weekday_num = get_weekday_num_from_date(selected_date)
8984
is_working_day_ = is_working_day(staff_member=sm, day=weekday_num)
85+
86+
custom_data['staff_member'] = sm.get_staff_member_name()
9087
if not is_working_day_:
9188
message = _("Not a working day for {staff_member}. Please select another date!").format(
9289
staff_member=sm.get_staff_member_first_name())
@@ -108,6 +105,7 @@ def get_available_slots_ajax(request):
108105
return json_response(message='Successfully retrieved available slots', custom_data=custom_data, success=True)
109106

110107

108+
# TODO: service id and staff id are not checked
111109
@require_ajax
112110
def get_next_available_date_ajax(request, service_id):
113111
"""This view function handles AJAX requests to get the next available date for a service.

0 commit comments

Comments
 (0)