# coding=utf-8 import logging from django.test import TestCase from django.utils import timezone import datetime import pandas as pd from datetime import timedelta from functions import create_availability, create_visit, create_appointment, create_appointment_type from web.utils import get_weekdays_in_period from web.officeAvailability import OfficeAvailability from web.models.holiday import Holiday from web.models.availability import Availability from web.models.appointment import Appointment from web.models.appointment_type_link import AppointmentTypeLink from web.models.constants import AVAILABILITY_HOLIDAY, AVAILABILITY_EXTRA from web.tests.functions import create_worker logger = logging.getLogger(__name__) class OfficeAvailabilityTest(TestCase): def test_availability_cases(self): # today = timezone.now() start_date = datetime.datetime(today.year, today.month, today.day, tzinfo=today.tzinfo) #today midnight end_date = start_date + datetime.timedelta(days=1) office_availability = OfficeAvailability('FirstName LastName', start=start_date, end=end_date, office_start='8:00', office_end='18:00') #no availabilties added yet self.assertEqual(office_availability.is_available(), False) self.assertEqual(office_availability.is_available(only_working_hours=True), False) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 0.0) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 0.0) #add availabilty from 8:00 to 18:00 weekday = list(get_weekdays_in_period(start_date, end_date))[0] availability = create_availability(available_from='8:00', available_till='18:00', day_number=weekday) office_availability.consider_this(availability) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 100.0) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 41.70714781401804) # ((10*(60)+1)/(24*60.0+1))*100 That +1 is the zero minute #add holiday from 16:00 to 18:00 # 2 hours less availability start_date = datetime.datetime(today.year, today.month, today.day, 16, 00, tzinfo=today.tzinfo) end_date = start_date + datetime.timedelta(hours=2) holiday = Holiday(person=create_worker(), datetime_start=start_date, datetime_end=end_date, kind=AVAILABILITY_HOLIDAY) office_availability.consider_this(holiday) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 79.86688851913478) # ((8*60)/(10*60.0+1))*100 # the bordwer minute is 0, then no +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 33.31020124913255) # ((8*60)/(24*60.0+1))*100 #add extra availability from 17:00 to 18:00 # 1 hour more availability start_date = datetime.datetime(today.year, today.month, today.day, 17, 00, tzinfo=today.tzinfo) end_date = start_date + datetime.timedelta(hours=1) extra_availability = Holiday(person=create_worker(), datetime_start=start_date, datetime_end=end_date, kind=AVAILABILITY_EXTRA) office_availability.consider_this(extra_availability) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 90.01663893510815) # ((9*60+1)/(10*60.0+1))*100 # the border minute is now 1 then +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 37.543372657876475) #add appointment from 9:00 to 10:00 # 1 hour less availability #create visit visit_start_date = start_date - datetime.timedelta(days=31) visit_end_date = end_date + datetime.timedelta(days=31) visit = create_visit(subject=None, datetime_begin=visit_start_date, datetime_end=visit_end_date) #create appointment appointment_typeA = create_appointment_type(code='A', default_duration=40, description='test1') appointment_typeB = create_appointment_type(code='B', default_duration=20, description='test2') appointment_when = datetime.datetime(today.year, today.month, today.day, 9, 00, tzinfo=today.tzinfo) appointment = create_appointment(visit=visit, when=appointment_when, length=60) worker = create_worker() app_type_linkA = AppointmentTypeLink(appointment=appointment, date_when=appointment_when, appointment_type=appointment_typeA, worker=worker) app_type_linkB = AppointmentTypeLink(appointment=appointment, date_when=appointment_when+datetime.timedelta(minutes=20), appointment_type=appointment_typeB, worker=worker) appointment.save() #the availability percentage should be the same as before adding the extra availability office_availability.consider_this(appointment) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 79.86688851913478) # ((8*60)/(10*60.0+1))*100 # the bordwer minute is 0, then no +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 33.31020124913255) # ((8*60)/(24*60.0+1))*100 #consider the 2 AppointmentTypeLinks. The availability percentage shouldn't change office_availability.consider_this(app_type_linkA) office_availability.consider_this(app_type_linkB) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 79.86688851913478) # ((8*60)/(10*60.0+1))*100 # the bordwer minute is 0, then no +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 33.31020124913255) # ((8*60)/(24*60.0+1))*100 #force add availability from 9:00 to 10:00 # 1 hour more availability start_date = datetime.datetime(today.year, today.month, today.day, 9, 00, tzinfo=today.tzinfo).replace(second=0, microsecond=0) end_date = start_date + datetime.timedelta(hours=1) office_availability.add_availability(pd.date_range(start=start_date, end=end_date, freq='1T'), only_working_hours=False) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 90.01663893510815) # ((9*60+1)/(10*60.0+1))*100 # the border minute is now 1 then +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 37.543372657876475) #force remove availability from 9:00 to 12:00 # 3 hour less availability start_date = datetime.datetime(today.year, today.month, today.day, 9, 00, tzinfo=today.tzinfo).replace(second=0, microsecond=0) end_date = start_date + datetime.timedelta(hours=3) office_availability.remove_availability(pd.date_range(start=start_date, end=end_date, freq='1T'), only_working_hours=True) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 59.900166389351085) # ((6*60)/(10*60.0+1))*100 # the border minute is 0 then no +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 24.98265093684941) def test_availability_cases2(self): # today = timezone.now() start_date = datetime.datetime(today.year, today.month, today.day, tzinfo=today.tzinfo) #today midnight end_date = start_date + datetime.timedelta(days=1) first_name = u'âêîôûŵŷäëïöüẅÿà' last_name = u'èìòùẁỳáéíóúẃýćńóśźżąę' office_availability = OfficeAvailability(u'{} {}'.format(first_name, last_name), start=start_date, end=end_date, office_start='8:00', office_end='18:00') #no availabilties added yet self.assertEqual(office_availability.is_available(), False) self.assertEqual(office_availability.is_available(only_working_hours=True), False) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 0.0) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 0.0) #add availabilty from 8:00 to 18:00 weekday = list(get_weekdays_in_period(start_date, end_date))[0] availability = create_availability(available_from='8:00', available_till='18:00', day_number=weekday) office_availability.consider_this(availability) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 100.0) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 41.70714781401804) # ((10*(60)+1)/(24*60.0+1))*100 That +1 is the zero minute #add holiday (leave) from 30 days ago up to next 90 days starting with today in the middle start_date = datetime.datetime(today.year, today.month, today.day, 16, 00, tzinfo=today.tzinfo) end_date = start_date + datetime.timedelta(days=90) start_date = start_date - datetime.timedelta(days=30) holiday = Holiday(person=create_worker(), datetime_start=start_date, datetime_end=end_date, kind=AVAILABILITY_HOLIDAY) office_availability.consider_this(holiday) self.assertEqual(office_availability.is_available(only_working_hours=True), False) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 0) # ((8*60)/(10*60.0+1))*100 # the bordwer minute is 0, then no +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 0) # ((8*60)/(24*60.0+1))*100 def test_availability_cases3(self): # today = timezone.now() start_date = datetime.datetime(today.year, today.month, today.day, tzinfo=today.tzinfo) #today midnight end_date = start_date + datetime.timedelta(days=1) first_name = u'âêîôûŵŷäëïöüẅÿà' last_name = u'èìòùẁỳáéíóúẃýćńóśźżąę' office_availability = OfficeAvailability(u'{} {}'.format(first_name, last_name), start=start_date, end=end_date, office_start='8:00', office_end='18:00') #no availabilties added yet self.assertEqual(office_availability.is_available(), False) self.assertEqual(office_availability.is_available(only_working_hours=True), False) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 0.0) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 0.0) #add availabilty from 8:00 to 18:00 weekday = list(get_weekdays_in_period(start_date, end_date))[0] availability = create_availability(available_from='8:00', available_till='18:00', day_number=weekday) office_availability.consider_this(availability) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 100.0) self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 41.70714781401804) # ((10*(60)+1)/(24*60.0+1))*100 That +1 is the zero minute #add holiday (leave) from 90 days ago up to 60 days ago but without overlapping with today's date start_date = datetime.datetime(today.year, today.month, today.day, 16, 00, tzinfo=today.tzinfo) - datetime.timedelta(days=90) end_date = start_date + datetime.timedelta(days=30) holiday = Holiday(person=create_worker(), datetime_start=start_date, datetime_end=end_date, kind=AVAILABILITY_HOLIDAY) office_availability.consider_this(holiday) self.assertEqual(office_availability.is_available(only_working_hours=True), True) self.assertEqual(office_availability.is_available(), False) #less than 50% self.assertEqual(office_availability.get_availability_percentage(only_working_hours=True), 100.0) # ((8*60)/(10*60.0+1))*100 # the bordwer minute is 0, then no +1 self.assertEqual(office_availability.get_availability_percentage(only_working_hours=False), 41.70714781401804) # ((8*60)/(24*60.0+1))*100