Skip to content

Commit b8e178f

Browse files
authored
Merge branch 'main' into dependabot/pip/phonenumbers-8.13.37
2 parents c24dc4e + 52c9b5c commit b8e178f

34 files changed

+2698
-1994
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
pip install coverage
3535
- name: Run Tests
3636
run: |
37-
coverage run --source=appointment manage.py test appointment.tests --verbosity=1
37+
coverage run --source=appointment manage.py test appointment.tests --parallel=10 --shuffle --verbosity=1
3838
coverage report
3939
coverage xml
4040
- name: Upload to Codecov

appointment/models.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import random
1111
import string
1212
import uuid
13+
from decimal import Decimal, InvalidOperation
1314

1415
from babel.numbers import get_currency_symbol
1516
from django.conf import settings
@@ -67,7 +68,7 @@ class Service(models.Model):
6768
name = models.CharField(max_length=100, blank=False)
6869
description = models.TextField(blank=True, null=True)
6970
duration = models.DurationField(validators=[MinValueValidator(datetime.timedelta(seconds=1))])
70-
price = models.DecimalField(max_digits=6, decimal_places=2, validators=[MinValueValidator(0)])
71+
price = models.DecimalField(max_digits=8, decimal_places=2, validators=[MinValueValidator(0)])
7172
down_payment = models.DecimalField(max_digits=6, decimal_places=2, default=0, validators=[MinValueValidator(0)])
7273
image = models.ImageField(upload_to='services/', blank=True, null=True)
7374
currency = models.CharField(max_length=3, default='USD', validators=[MaxLengthValidator(3), MinLengthValidator(3)])
@@ -435,7 +436,7 @@ class Appointment(models.Model):
435436
want_reminder = models.BooleanField(default=False)
436437
additional_info = models.TextField(blank=True, null=True)
437438
paid = models.BooleanField(default=False)
438-
amount_to_pay = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
439+
amount_to_pay = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
439440
id_request = models.CharField(max_length=100, blank=True, null=True)
440441

441442
# meta datas
@@ -596,7 +597,7 @@ def is_owner(self, staff_user_id):
596597
def to_dict(self):
597598
return {
598599
"id": self.id,
599-
"client_name": self.client.get_full_name(),
600+
"client_name": self.get_client_name(),
600601
"client_email": self.client.email,
601602
"start_time": self.appointment_request.start_time.strftime('%Y-%m-%d %H:%M'),
602603
"end_time": self.appointment_request.end_time.strftime('%Y-%m-%d %H:%M'),
@@ -664,6 +665,10 @@ def clean(self):
664665
if self.lead_time is not None and self.finish_time is not None:
665666
if self.lead_time >= self.finish_time:
666667
raise ValidationError(_("Lead time must be before finish time"))
668+
if self.appointment_buffer_time is not None and self.appointment_buffer_time < 0:
669+
raise ValidationError(_("Appointment buffer time cannot be negative"))
670+
if self.slot_duration is not None and self.slot_duration <= 0:
671+
raise ValidationError(_("Slot duration must be greater than 0"))
667672

668673
def save(self, *args, **kwargs):
669674
self.clean()

appointment/tests/base/base_test.py

Lines changed: 71 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,84 @@
22

33
from django.test import TestCase
44

5+
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
56
from appointment.tests.mixins.base_mixin import (
67
AppointmentMixin, AppointmentRequestMixin, AppointmentRescheduleHistoryMixin, ServiceMixin, StaffMemberMixin,
78
UserMixin
89
)
10+
from appointment.utils.db_helpers import get_user_model
911

1012

11-
class BaseTest(TestCase, UserMixin, StaffMemberMixin, ServiceMixin, AppointmentRequestMixin, AppointmentMixin,
12-
AppointmentRescheduleHistoryMixin):
13-
def setUp(self):
14-
# Users
15-
self.user1 = self.create_user_(email="[email protected]", username="tester1")
16-
self.user2 = self.create_user_(first_name="Tester2", email="[email protected]", username="tester2")
17-
self.client1 = self.create_user_(first_name="Client1", email="[email protected]", username="client1")
18-
self.client2 = self.create_user_(first_name="Client2", email="[email protected]", username="client2")
13+
class BaseTest(TestCase, UserMixin, StaffMemberMixin, ServiceMixin, AppointmentRequestMixin,
14+
AppointmentMixin, AppointmentRescheduleHistoryMixin):
15+
service1 = None
16+
service2 = None
17+
staff_member1 = None
18+
staff_member2 = None
19+
users = None
1920

20-
# Services
21-
self.service1 = self.create_service_()
22-
self.service2 = self.create_service_(name="Service 2")
21+
USER_SPECS = {
22+
'staff1': {"first_name": "Daniel", "email": "[email protected]",
23+
"username": "daniel.jackson"},
24+
'staff2': {"first_name": "Samantha", "email": "[email protected]",
25+
"username": "samantha.carter"},
26+
'client1': {"first_name": "Georges", "email": "[email protected]",
27+
"username": "georges.hammond"},
28+
'client2': {"first_name": "Tealc", "email": "[email protected]", "username": "tealc.kree"},
29+
'superuser': {"first_name": "Jack", "email": "[email protected]", "username": "jack.o.neill"},
30+
}
2331

24-
# Staff Members
25-
self.staff_member1 = self.create_staff_member_(user=self.user1, service=self.service1)
26-
self.staff_member2 = self.create_staff_member_(user=self.user2, service=self.service2)
32+
@classmethod
33+
def setUpTestData(cls):
34+
cls.users = {key: cls.create_user_(**details) for key, details in cls.USER_SPECS.items()}
35+
cls.service1 = cls.create_service_(
36+
name="Stargate Activation", duration=timedelta(hours=1), price=100000, description="Activate the Stargate")
37+
cls.service2 = cls.create_service_(
38+
name="Dial Home Device Repair", duration=timedelta(hours=2), price=200000, description="Repair the DHD")
39+
# Mapping services to staff members
40+
cls.staff_member1 = cls.create_staff_member_(user=cls.users['staff1'], service=cls.service1)
41+
cls.staff_member2 = cls.create_staff_member_(user=cls.users['staff2'], service=cls.service2)
2742

28-
def create_appt_request_for_sm1(self, **kwargs):
43+
@classmethod
44+
def tearDownClass(cls):
45+
super().tearDownClass()
46+
# Clean up any class-level resources
47+
cls.clean_all_data()
48+
49+
@classmethod
50+
def clean_all_data(cls):
51+
Appointment.objects.all().delete()
52+
AppointmentRequest.objects.all().delete()
53+
StaffMember.objects.all().delete()
54+
Service.objects.all().delete()
55+
get_user_model().objects.all().delete()
56+
57+
def create_appt_request_for_sm1(self, service=None, staff_member=None, **kwargs):
2958
"""Create an appointment request for staff_member1."""
30-
return self.create_appointment_request_(service=self.service1, staff_member=self.staff_member1, **kwargs)
59+
service = service or self.service1
60+
staff_member = staff_member or self.staff_member1
61+
return self.create_appointment_request_(service=service, staff_member=staff_member, **kwargs)
3162

32-
def create_appt_request_for_sm2(self, **kwargs):
63+
def create_appt_request_for_sm2(self, service=None, staff_member=None, **kwargs):
3364
"""Create an appointment request for staff_member2."""
34-
return self.create_appointment_request_(service=self.service2, staff_member=self.staff_member2, **kwargs)
65+
service = service or self.service2
66+
staff_member = staff_member or self.staff_member2
67+
return self.create_appointment_request_(service=service, staff_member=staff_member, **kwargs)
3568

36-
def create_appointment_for_user1(self, appointment_request=None):
69+
def create_appt_for_sm1(self, appointment_request=None):
3770
if not appointment_request:
3871
appointment_request = self.create_appt_request_for_sm1()
39-
return self.create_appointment_(user=self.client1, appointment_request=appointment_request)
72+
return self.create_appointment_(user=self.users['client1'], appointment_request=appointment_request)
4073

41-
def create_appointment_for_user2(self, appointment_request=None):
74+
def create_appt_for_sm2(self, appointment_request=None):
4275
if not appointment_request:
4376
appointment_request = self.create_appt_request_for_sm2()
44-
return self.create_appointment_(user=self.client2, appointment_request=appointment_request)
77+
return self.create_appointment_(user=self.users['client2'], appointment_request=appointment_request)
4578

46-
def create_appointment_reschedule_for_user1(self, appointment_request=None, reason_for_rescheduling="Reason"):
79+
def create_appt_reschedule_for_sm1(self, appointment_request=None, reason_for_rescheduling="Gate Malfunction"):
4780
if not appointment_request:
4881
appointment_request = self.create_appt_request_for_sm1()
49-
date_ = appointment_request.date + timedelta(days=1)
82+
date_ = appointment_request.date + timedelta(days=7)
5083
return self.create_reschedule_history_(
5184
appointment_request=appointment_request,
5285
date_=date_,
@@ -59,23 +92,21 @@ def create_appointment_reschedule_for_user1(self, appointment_request=None, reas
5992
def need_normal_login(self):
6093
self.client.force_login(self.create_user_())
6194

62-
def need_staff_login(self, user=None):
63-
if user is not None:
64-
user.is_staff = True
65-
user.save()
66-
self.client.force_login(user)
67-
self.user1.is_staff = True
68-
self.user1.save()
69-
self.client.force_login(self.user1)
95+
def need_staff_login(self):
96+
self.staff = self.users['staff1']
97+
self.staff.is_staff = True
98+
self.staff.save()
99+
self.client.force_login(self.staff)
70100

71101
def need_superuser_login(self):
72-
self.user1.is_superuser = True
73-
self.user1.save()
74-
self.client.force_login(self.user1)
102+
self.superuser = self.users['superuser']
103+
self.superuser.is_superuser = True
104+
self.superuser.save()
105+
self.client.force_login(self.superuser)
75106

76-
def clean_staff_member_objects(self, user=None):
107+
def clean_staff_member_objects(self, staff=None):
77108
"""Delete all AppointmentRequests and Appointments linked to the StaffMember instance of self.user1."""
78-
if user is None:
79-
user = self.user1
80-
self.clean_appointment_for_user(user)
81-
self.clean_appt_request_for_user(user)
109+
if staff is None:
110+
staff = self.users['staff1']
111+
self.clean_appointment_for_user_(staff)
112+
self.clean_appt_request_for_user_(staff)

appointment/tests/mixins/base_mixin.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ def __init__(self):
1111
pass
1212

1313
@classmethod
14-
def create_user_(cls, first_name="Tester", email="[email protected]", username="test_user",
15-
password="Kfdqi3!?n"):
16-
user_model = get_user_model()
17-
return user_model.objects.create_user(
14+
def create_user_(cls, first_name="Janet", email="[email protected]", username="janet.fraiser",
15+
password="G0a'uld$Emp1re"):
16+
return get_user_model().objects.create_user(
1817
first_name=first_name,
1918
email=email,
2019
username=username,
@@ -27,11 +26,13 @@ def __init__(self):
2726
pass
2827

2928
@classmethod
30-
def create_service_(cls, name="Test Service", duration=timedelta(hours=1), price=100):
29+
def create_service_(cls, name="Quantum Mirror Assessment", duration=timedelta(hours=1), price=50000,
30+
description="Assess the Quantum Mirror"):
3131
return Service.objects.create(
3232
name=name,
3333
duration=duration,
34-
price=price
34+
price=price,
35+
description=description
3536
)
3637

3738

@@ -62,7 +63,7 @@ def create_appointment_request_(cls, service, staff_member, date_=date.today(),
6263
)
6364

6465
@classmethod
65-
def clean_appt_request_for_user(cls, user):
66+
def clean_appt_request_for_user_(cls, user):
6667
AppointmentRequest.objects.filter(staff_member__user=user).delete()
6768

6869

@@ -71,7 +72,8 @@ def __init__(self):
7172
pass
7273

7374
@classmethod
74-
def create_appointment_(cls, user, appointment_request, phone="1234567890", address="Some City, Some State"):
75+
def create_appointment_(cls, user, appointment_request, phone="+12392340543",
76+
address="Stargate Command, Cheyenne Mountain Complex, Colorado Springs, CO"):
7577
return Appointment.objects.create(
7678
client=user,
7779
appointment_request=appointment_request,
@@ -80,7 +82,7 @@ def create_appointment_(cls, user, appointment_request, phone="1234567890",
8082
)
8183

8284
@classmethod
83-
def clean_appointment_for_user(cls, user):
85+
def clean_appointment_for_user_(cls, user):
8486
Appointment.objects.filter(client=user).delete()
8587

8688

@@ -90,7 +92,7 @@ def __init__(self):
9092

9193
@classmethod
9294
def create_reschedule_history_(cls, appointment_request, date_, start_time, end_time, staff_member,
93-
reason_for_rescheduling=""):
95+
reason_for_rescheduling="Zat'nik'tel Discharge"):
9496
return AppointmentRescheduleHistory.objects.create(
9597
appointment_request=appointment_request,
9698
date=date_,

0 commit comments

Comments
 (0)