def __init__(self, work_date): self.work_date = work_date self.work_day = self.is_valid() self.next_valid_day = None self.db = DBCommands() self.ii = InsertItem() self.db.connect()
class DTree(object): def __init__(self, work_day, path): self.work_day = work_day self.dtree = load(filename='./machine_learning/glasses_dtree.joblib') self.db = DBCommands() self.db.connect() def __del__(self): self.db.conn.close() def pull_patient_id(self): patient_list = [] patients = self.db.view_free( f"SELECT patient FROM schedule WHERE appt_date = '{self.work_day}' ORDER BY appt_time", slow=False) for patient in patients: patient_list.append(patient[0]) # Patients in order of appointment times return patient_list def pull_patient_data(self, patient): data = self.db.view_free(f"SELECT * FROM glasses_data WHERE id = {patient}", slow=False) return data def process_data(self, data): if len(data) == 0: return 'New' else: columns = ['id', 'patient_name', 'address', 'insurance', 'avg_dollar', 'age', 'gender', 'lat', 'lon', 'first_purchase', 'last_purchase', 'purchase_time', 'total_paid', 'used_ins', 'product_id', 'price', 'appt_type', 'buying_pattern'] # Getting column titles ready df = pd.DataFrame(data, columns=columns) df.drop_duplicates(inplace=True) df.drop(columns=['address', 'first_purchase', 'last_purchase', 'patient_name', 'purchase_time', 'id', 'lat', 'lon', 'buying_pattern'], axis=1, inplace=True) # Cleaning data # Getting categorical data, including missing columns then dropping first. gender = pd.get_dummies(df['gender']).reindex(columns=['female', 'male'], fill_value=0) exam_type = pd.get_dummies(df['appt_type']).reindex(columns=['Contacts', 'Glasses', 'Health'], fill_value=0) insurance = pd.get_dummies(df['insurance']).reindex(columns=['Good', 'Standard', 'Poor', 'None'], fill_value=0) gender.drop(columns=['female'], axis=1, inplace=True) exam_type.drop(columns=['Contacts'], axis=1, inplace=True) insurance.drop(columns=['Good'], axis=1, inplace=True) df.drop(columns=['gender', 'appt_type', 'insurance', 'used_ins'], axis=1, inplace=True) df2 = pd.concat([df, gender, exam_type, insurance], join='inner', axis=1) predictions = self.dtree.predict(df2) try: return mode(predictions) except StatisticsError: return predictions[0] def predict_pattern(self): pattern_list = [] for i in self.pull_patient_id(): pattern_list.append(self.process_data(self.pull_patient_data(i))) return pattern_list
def pull_data(): db = DBCommands() columns = [ 'ID', 'Name', 'Address', 'Ins', 'Average Dollar', 'Age', 'Gender', 'Latitude', 'Longitude', 'First Purchase', 'Last Purchase' ] data = db.view_free('SELECT * FROM patients WHERE avg_dollar IS NOT NULL') df = pd.DataFrame(data, columns=columns) return df
def __init__(self, patient): self.patient = patient self.db = DBCommands() self.db.connect() self.purchases = [ ] # This will be what is used for sales. Empty list will mean no purchase. self.patient_demographics = None # Pulled from "patients" table self.patient_auto = None # Pulled from "auto_patient" table self.patient_history = None # Pulled from "sale_item" table. Will need to have dates from "sale" table also. self.patient_history_dates = [] # Date of each sale self.patient_insurance = (0, 'None' ) # Separated to allow easier indexing. self.product_list = None
def __init__(self, patient_id, days_out, current_date=None, appt_type='Glasses'): self.patient_id = patient_id self.current_date = current_date if current_date else date.today() self.exam_date = self.days_to_date( days_out) # Date desired for appointment ( 02/05/2019 ) self.initial_exam_date = self.days_to_date(days_out) self.db = DBCommands() self.db.connect() # Connect this class to DB self.days = plogic.working_days self.time = plogic.business_hours self.appt_time = plogic.appt_slot self.appt_type = appt_type
class ProductPurchase(object): def __init__(self, patient): self.patient = patient self.db = DBCommands() self.db.connect() self.purchases = [ ] # This will be what is used for sales. Empty list will mean no purchase. self.patient_demographics = None # Pulled from "patients" table self.patient_auto = None # Pulled from "auto_patient" table self.patient_history = None # Pulled from "sale_item" table. Will need to have dates from "sale" table also. self.patient_history_dates = [] # Date of each sale self.patient_insurance = (0, 'None' ) # Separated to allow easier indexing. self.product_list = None def __del__(self): self.db.conn.close() # Nothing will be recorded in DB def pull_product_list(self): i = self.db.view('products', field='id, product', slow=False) self.product_list = i def pull_patient_demographics(self): i = self.db.view('patients', field='id, insurance, age, gender', conditional=('id', self.patient), slow=False) self.patient_demographics = i[0] def pull_patient_auto(self): i = self.db.view('auto_patient', conditional=('patient_id', self.patient), slow=False) self.patient_auto = i[0][1:] def pull_patient_history(self): i = self.db.view_free( f"SELECT sale_item.product_id, sale.purchase_time FROM sale_item INNER JOIN " f"sale ON sale_item.sale_id = sale.id WHERE sale.patient = {self.patient}", slow=False) if len(i) > 0: # If there is a history self.patient_history = {} # Change to dictionary dates = set() for item in i: # Pull dates from data dates.add(item[1]) self.patient_history_dates = list(dates) self.patient_history_dates.sort() for day in self.patient_history_dates: items = [] sales = [x for x in i if x[1] == day ] # Sort by dates to prevent massive list iterations for item in sales: # Pull sales data items.append(item[0]) self.patient_history[day] = items def pull_patient_data( self ): # Created to allow multiple ways to pull data in future if needed. self.pull_patient_demographics() self.pull_patient_auto() self.pull_patient_history() self.set_insurance() def run_sale(self): self.pull_patient_data() self.pull_product_list() self.purchases = [] # Reset purchase list to prevent doubles self.purchase_exam() self.purchase_contacts() count = self.purchase_glasses() if count > 0: self.purchases += self.glasses_type(count) def set_insurance(self): if self.patient_demographics: found = False patient_insurance = self.patient_demographics[1] for i in enumerate(insurance): if patient_insurance == i[1]: self.patient_insurance = i found = True if not found: self.patient_insurance = (0, 'None') def purchase_exam(self): # Used to populate exam ids, needs to run first. if self.patient_auto[2] == 'Health': self.purchases += [8, 5] elif self.patient_auto[2] == 'Contacts': if self.patient_history: found = False for i in reversed(self.patient_history_dates ): # Dictionary Date: [purchases] if 6 in self.patient_history[i]: self.purchases += [1, 5, 6] found = True break # Stop after first found elif 7 in self.patient_history[i]: self.purchases += [1, 5, 7] found = True break if not found: self.first_cl_exam() else: self.first_cl_exam() else: # Glasses purchase self.purchases += [1, 5] # Check for optimap purchase count = 0 if self.patient_history: for i in reversed(self.patient_history_dates): if count > 3 or count < -3: break if 9 in self.patient_history[i]: count += 1 else: count -= 1 chance = random.randint(1, 50) + (loyal_optimap * count) + optimap[int( self.patient_auto[1])] if chance >= 30: self.purchases += [9] def first_cl_exam(self): chance = random.randint(1, 100) exam_type = cl_exam_type if self.patient_demographics[2] >= 40: age = self.patient_demographics[2] - 30 special_fit = int(age / 10) * cl_age_factor exam_type -= special_fit if chance >= cl_exam_type: self.purchases += [1, 5, 7] else: self.purchases += [1, 5, 6] def pick_contacts(self): contact_type = None chance = random.randint(1, 100) for i in type_contacts: if chance <= type_contacts[i][int(self.patient_auto[1])]: contact_type = i break else: chance -= type_contacts[i][int(self.patient_auto[1])] return contact_type def purchase_contacts(self): if self.patient_auto[2] != 'Contacts': return None contact_type = None if self.patient_history: contacts = {26, 27, 28} count = 0 for i in reversed(self.patient_history_dates): if contact_type is None: contact_type = contacts.intersection( self.patient_history[i]) pass if contacts.intersection( self.patient_history[i]) == contact_type: count += 1 else: break # Stop looking after patient switched type if count >= abs(switch_contacts[1] / switch_contacts[0]): break # Stop looking after 0 % switch chance switch_chance = switch_contacts[1] - (switch_contacts[0] * count) if len(contact_type) > 0: contact_type = self.product_id(list(contact_type)[0], to_id=False) # Pull CL name else: contact_type = self.pick_contacts() if switch_chance > 0: chance = random.randint(1, 100) if chance < switch_chance: contact_type = self.pick_contacts() else: contact_type = self.pick_contacts() if contact_type is None: raise ValueError # Should be a string at this point else: ins_index = 1 if self.patient_insurance[0] > 0 else 0 amount_contacts = None chance = random.randint(1, 100) for i in buy_contacts: amount = buy_contacts[i][int(self.patient_auto[1])][ins_index] if chance > amount: chance -= amount else: try: amount_contacts = int(contacts_amount[i][contact_type]) except TypeError: print(contacts_amount[i]) break if amount_contacts is not None: for i in self.product_list: if contact_type == i[1]: contact_type = i[ 0] # Change to id number for quick sale self.purchases += [contact_type] * amount_contacts def purchase_glasses(self): purchase_chance = buy_glasses[int( self.patient_auto[1])][self.patient_insurance[0]] # Initial value bottom, top = random_glasses[int(self.patient_auto[1])] purchase_chance += random.randint(bottom, top) if self.patient_history: frames = {10, 11, 12} last_purchase = self.patient_history[ self.patient_history_dates[-1]] purchased_before = bool(frames.intersection(last_purchase)) if not purchased_before: if self.patient_insurance[0] > 0: purchase_chance += skip_glasses[int( self.patient_auto[1])][1] else: purchase_chance += skip_glasses[int( self.patient_auto[1])][0] if self.patient_auto[2] != 'Glasses': purchase_chance += non_glasses purchase_count = 0 while purchase_chance > 0: purchase = random.randint(1, 100) if purchase < purchase_chance: purchase_count += 1 # Purchased glasses purchase_chance -= glasses_threshold return purchase_count def glasses_type(self, count): # Puts together all the items on the glasses master_purchases = [] for x in range(count): purchase_list = [] purchase_list.append(self.product_id(self.pick_frame())) purchase_list.append(self.product_id(self.pick_lens_type())) purchase_list.append(self.product_id(self.pick_lens_material())) ar_purchased = self.pick_ar_type() if ar_purchased and ar_purchased != 'None': purchase_list.append(self.product_id(ar_purchased)) if x == 1: # Second pair polar_purchased = self.pick_polarized(multi=True) else: polar_purchased = self.pick_polarized() if polar_purchased: purchase_list.append(polar_purchased) if 25 not in purchase_list: trans_purchase = self.pick_transitions() if trans_purchase: purchase_list.append(trans_purchase) master_purchases += purchase_list return master_purchases def pick_frame(self): chance = random.randint( 1, 100 ) + frame_gender if self.patient_demographics[3] == 'female' else 0 for i in frame_type: if chance > frame_type[i][int( self.patient_auto[1])][self.patient_insurance[0]]: chance -= frame_type[i][int( self.patient_auto[1])][self.patient_insurance[0]] else: return i # String of frame def pick_lens_type(self): # Choose SV, BF, Prog if self.patient_demographics[2] < 40: return 'SV Lenses' else: pass patient_lens = None if self.patient_history: lenses = {13, 14, 15, 16, 17} count = 0 for i in reversed(self.patient_history_dates): if patient_lens is None: patient_lens = lenses.intersection( self.patient_history[i]) pass else: if patient_lens == lenses.intersection( self.patient_history[i]): count += 1 if count >= 3: break else: chance = random.randint(1, 100) if chance > switch_lens_type - (count * 5): break else: patient_lens = None # Jump to lens selection if patient_lens is None or len(patient_lens) == 0: chance = random.randint(1, 100) for i in lens_type: if chance > lens_type[i]: chance -= lens_type[i] else: if i == 'Progressives': chance = random.randint(1, 100) for x in progressive_type: if chance > progressive_type[x][int( self.patient_auto[1])][ self.patient_insurance[0]]: chance -= progressive_type[x][int( self.patient_auto[1])][ self.patient_insurance[0]] else: i = x return i return i # Returned as string, will have a separate function to change to id. return self.product_id(list(patient_lens)[0], to_id=False) def pick_lens_material(self): if self.patient_demographics[2] < 40: return 'Polycarbonate' else: chance = random.randint(1, 100) lenses = None if self.patient_history: types = {20: "Hi-Index", 19: "Polycarbonate", 18: "Plastic"} lens_types = {18, 19, 20} for i in reversed(self.patient_history_dates): lenses = lens_types.intersection(self.patient_history[i]) if len(lenses) > 1: lenses = types[list(lenses)[0]] break else: lenses = None chance += lens_insurance[ self.patient_insurance[0]] + lens_buy_pattern[int( self.patient_auto[1])] try: rx = lens_rx[self.patient_auto[6]] except IndexError: # Outside the high end of the Rx index rx = lens_rx[-1] chance += rx for i in lens_material: if lenses == i: chance += loyal_lens_material if chance >= lens_material[i]: return i return "Plastic" # 'Else' choice def pick_ar_type(self): chance = random.randint(1, 50) chance += ar_insurance[self.patient_insurance[0]] + ar_buy_pattern[int( self.patient_auto[1])] ar = None if self.patient_history: types = {21: 'Standard AR', 22: 'Good AR', 23: 'Great AR'} ar_types = {21, 22, 23} for i in reversed(self.patient_history_dates): ar = ar_types.intersection(self.patient_history[i]) if ar: ar = list(ar)[0] ar = types[ar] break for i in ar_type: if i == ar: chance += 20 if chance >= ar_type[i]: return i return None def pick_transitions(self): chance = random.randint( 1, 50) + trans_age if self.patient_demographics[2] < 20 else 0 chance += trans_insurance[ self.patient_insurance[0]] + trans_buy_pattern[int( self.patient_auto[1])] if self.patient_history and len(self.patient_history) > 1: count = 0 had_it = None glasses = {10, 11, 12} for i in reversed(self.patient_history_dates): purchased = glasses.intersection(self.patient_history[i]) if purchased: # Did they buy glasses last time? if had_it is None: if 24 in purchased: had_it = True elif 25 in purchased: # Polarized doesn't count pass else: count += 1 elif count == 1: if 24 in purchased: chance = 0 - trans_loyal # Did not buy it after having it, must hate it. break elif 25 in purchased: pass else: count += 1 elif had_it: if 24 in purchased: chance = 0 + trans_loyal # Bought it twice in a row, must like it break elif 25 in purchased: pass else: break if chance > trans_buy: return 24 # Purchased transitions def pick_polarized(self, multi=False): chance = random.randint(1, 50) chance += polar_insurance[ self.patient_insurance[0]] + polar_buy_pattern[int( self.patient_auto[1])] if multi: second_pair = 0 + second_pair_sun else: second_pair = 0 - (second_pair_sun * 2) if self.patient_history and not multi: for i in reversed(self.patient_history_dates): glasses = {10, 11, 12} purchased = glasses.intersection(self.patient_history[i]) if purchased: if 25 not in self.patient_history[i]: second_pair = 0 + second_pair_sun # Did not purchase sun last time. break if chance + second_pair > polar_buy: return 25 def product_id(self, product, to_id=True): # Turns str to id or id to str if to_id: if type(product) == str: for i in self.product_list: if product in i: return i[0] if not to_id: if type(product) == int: for i in self.product_list: if product in i: return i[1]
def setup_db(): ii = DBCommands() ii.connect() yield ii ii.conn.rollback() ii.conn.close()
def __init__(self, work_day, path): self.work_day = work_day self.dtree = load(filename='./machine_learning/glasses_dtree.joblib') self.db = DBCommands() self.db.connect()
def __init__(self): self.db = DBCommands()
class InsertItem(object): # This would connect to the front end to allow DB editing def __init__(self): self.db = DBCommands() def _id_lookup(self, table, column, item, slow=True): # Returns id of item id_key = None try: id_key = self.db.view(table, conditional=(column, item), field="id", slow=slow) except Exception: self.db.rollback() if id_key is None: print(f'DB Error, could not find id of {item}') else: return id_key[0][0] # Should never be none: Cannot sale to unknown, nor sale unknown item. def patient_insert(self, name, address='', gender='', age='', insurance='None'): # Needs a name try: self.db.insert(['patient', ('patient_name', name), ('address', address), ('gender', gender), ('age', age), ('insurance', insurance)]) except Exception: # Look at exceptions that could hinder insert. self.db.rollback() def insert_sale(self, patient, time=None, insurance='None', purchase_items=(('Test', 0))): # Slow and terrible, quick_sale will be the main input function. # Expects a nested list with [item, price] as each item. total_sum = 0 sale_time = time if time else dt.datetime.now() # Insert current time if none supplied patient_id = self._id_lookup('patients', 'patient_name', patient) items = [] for item in purchase_items: item_id = self._id_lookup('products', 'product', item[0]) total_sum += int(item[1]) items.append([item_id, item[1]]) # Change item name to item id # Create sale (patient, purchase_time, total_paid, used_ins) self.db.insert(['sale', ('patient', patient_id), ('purchase_time', sale_time), ('total_paid', total_sum), ('used_ins', insurance)]) sale_id = self.db.view(f"sale WHERE purchase_time = '{sale_time}' AND patient = {patient_id}", field="id") for item in items: # Creating sale_item table self.db.insert(['sale_item', ('product_id', item[0]), ('sale_id', sale_id[0][0]), ('price', item[1])]) self.db.update_avg_dollar(patient_id) self.db.update_timestamp(patient, sale_time) print(f"Patient {patient} recorded.") def quick_sale(self, patient_id, time, insurance, item_ids): # Used for quickly inputting sales for testing total_sum = 0 sale_time = time if time else dt.datetime.now() # Insert current time if none supplied items = [] for item_id in item_ids: items.append(self.db.view('products', field="id, cost", conditional=("id", item_id), slow=False)[0]) total_sum += int(items[0][1]) self.db.insert(['sale', ('patient', patient_id), ('purchase_time', sale_time), ('total_paid', total_sum), ('used_ins', insurance)], slow=False) sale_id = self.db.view(f"sale WHERE purchase_time = '{sale_time}' AND patient = {patient_id}", field="id", slow=False) for item in items: # Creating sale_item table self.db.insert(['sale_item', ('product_id', item[0]), ('sale_id', sale_id[0][0]), ('price', item[1])], slow=False) self.db.update_avg_dollar(patient_id,slow=False) self.db.update_timestamp(patient_id, sale_time, slow=False)
def __init__(self, number, current_day=None): self.number = number self.current_day = current_day if current_day else date.today() self.db = DBCommands() self.db.connect()
class NewPatient(object): """ Takes new patients and inserts them into the schedule. If patient does not have proper info, (Buying pattern, exam type) then it will fill those in. If no new patient exists, it will create one from scratch. Logic in a separate file for easier editing. """ def __init__(self, number, current_day=None): self.number = number self.current_day = current_day if current_day else date.today() self.db = DBCommands() self.db.connect() def __del__(self): self.db.commit_close() def patient_selector(self): # self.db.connect() new_patients = self.db.view_free( "SELECT patients.id, patients.age FROM patients WHERE NOT " "EXISTS(SELECT patient FROM schedule WHERE patients.id=schedule.patient)", slow=False) # Pull all patients that have never been seen. while len(new_patients) < self.number: self.create_patient() print("Not enough patients to add to scheduler.") break selected_patients = random.sample(new_patients, self.number) for patient in selected_patients: patient_id = patient[0] age = patient[1] info = self.db.view('auto_patient', field="buying_pattern, exam_type", conditional=["patient_id", patient_id], slow=False) # Check if patient exists in auto_table if len(info) == 0: # If patient not in auto patient buying_pattern = plogic.create_buying_pattern() exam_type = plogic.create_exam_type(age) rx_str = plogic.create_rx_strength() self.db.insert([ "auto_patient", ("patient_id", patient_id), ("buying_pattern", buying_pattern), ("exam_type", exam_type), ("rx_strength", rx_str) ], slow=False) insurance = plogic.create_insurance_type() self.db.update( ['patients', ('insurance', insurance), ('id', patient_id)], slow=False) days_out = random.randint(7, 14) # Set date for week to two weeks sch = Scheduler(patient_id, days_out, self.current_day, exam_type) sch.schedule_patient() # Put patient on schedule else: exam_type = info[0][1] print(exam_type) days_out = random.randint(7, 14) # Set date for week to two weeks sch = Scheduler(patient_id, days_out, self.current_day, exam_type) sch.schedule_patient() # Put patient on schedule # self.db.commit_close() def create_patient(self): # Create patient from scratch, calling all other info. ( Maybe turn into its own class / file ) # Eventually this will also auto make buying pattern and exam type as well. ( Full patient creation ) pass
class ProcessWorkDay(object): """ Does the work of running through each patient on that days schedule, deciding purchases, events and rescheduling. """ def __init__(self, work_date): self.work_date = work_date self.work_day = self.is_valid() self.next_valid_day = None self.db = DBCommands() self.ii = InsertItem() self.db.connect() def __del__(self): self.db.commit_close() def is_valid(self): if self.work_date.weekday() in plogic.working_days: return True # Used for sales that are outside of working days, such as medical or glasses broke. else: return False def process_day(self): if self.work_day: self.ii.db.connect() patients = self.db.view_schedule(self.work_date) patient_list = [] for patient in patients: # Seems messy, maybe easier way to do this? patient_list.append(patient[1]) for patient in patient_list: data = self.db.view('patients', conditional=('id', patient), field='insurance', slow=False)[0] insurance = data[0] auto_patient = self.db.view('auto_patient', ('patient_id', patient), slow=False) if len(auto_patient) == 0: print(f"Patient {patient} not in auto_patient." ) # Trying to catch a bug else: auto_product = ProductPurchase( auto_patient[0][1]) # Get id of patient auto_product.run_sale() purchase_list = auto_product.purchases if len(purchase_list) > 0: self.ii.quick_sale(patient, self.work_date, insurance, purchase_list) last_purchases = plogic.last_purchase(purchase_list) for item in last_purchases: # Something here is not working, insert test? self.db.cmd_free( f"UPDATE auto_patient SET {item} = '{self.work_date}' " f"WHERE patient_id = {patient}", slow=False) self.db.conn.commit() # Separate connections self.ii.db.commit_close() def check_future_appointments(self): for day in plogic.dates: back_date = self.work_date - timedelta(day) previous_patients = self.db.view('auto_patient', conditional=('last_exam_date', back_date), slow=False) for patient in previous_patients: _, patient_id, buying_pattern, exam_type, last_exam, last_glasses, last_contacts, rx_str = patient insurance = self.db.view('patients', field='insurance', conditional=('id', patient_id), slow=False)[0][0] has_insurance = False if insurance in plogic.insurances: has_insurance = True schedule = plogic.schedule(int(buying_pattern), exam_type, day, has_insurance) if schedule: days_out = random.randint(7, 14) sch = Scheduler(patient_id, days_out, self.work_date) sch.schedule_patient() def life_happens(self): # Use a separate file for logic # Go through patients, and see if any need special help # If so, run scheduler or sale based on need. # If not valid work day, then sale on next valid day ( automatically ) # Record events ( Just for testing ) pass def check_contacts(self): # Look through DB for all people who are overdue for CL's ( Look at last sale date, and CL type, times # boxes) # Check if exam is valid ( under a year ) # if exam valid: Based on buying pattern, purchase new CL's # if exam not valid: Schedule new exam # Make sure date is valid pass def record_day(self): # Turned off for the moment. self.db.connect() totals = self.db.view('sale', conditional=('purchase_time', self.work_date), slow=False) patients = len(totals) total_dollar = 0 for person in totals: total_dollar += person[3] with open('Daily_totals.txt', 'a') as file: file.write(f"On {self.work_date} there was {patients} " f"scheduled and we earned ${total_dollar/100}.\n") def run_day(self): # Puts everything together in order. self.process_day() self.check_future_appointments()
class Scheduler(object): """ Takes patient and will schedule them in an appropriate time slot. """ def __init__(self, patient_id, days_out, current_date=None, appt_type='Glasses'): self.patient_id = patient_id self.current_date = current_date if current_date else date.today() self.exam_date = self.days_to_date( days_out) # Date desired for appointment ( 02/05/2019 ) self.initial_exam_date = self.days_to_date(days_out) self.db = DBCommands() self.db.connect() # Connect this class to DB self.days = plogic.working_days self.time = plogic.business_hours self.appt_time = plogic.appt_slot self.appt_type = appt_type def __del__(self): self.db.commit_close() def schedule_patient(self): self.date_is_valid() appt_time = self.time_is_valid() try: self.db.insert([ 'schedule', ('patient', self.patient_id), ('appt_date', self.exam_date), ('appt_time', appt_time), ('appt_type', self.appt_type) ], slow=False) except Exception: self.db.rollback() def days_to_date(self, days_out): return self.current_date + timedelta(days_out) def date_is_valid(self): valid = False while not valid: if self.exam_date.weekday( ) in self.days: # If date is listed as open in self.days valid = True else: self.exam_date += timedelta(1) # Advance forward one day def time_is_valid(self): valid = False while not valid: appointments = self.db.view_schedule(self.exam_date) if len(appointments) == 0: # No appointments on that day. appt_time = [self.time[0], 0] # Book earliest appointment return time(appt_time[0], appt_time[1]) else: latest_hour = str(appointments[-1][2]).split(":")[0] latest_minute = str(appointments[-1][2]).split(":")[1] appt_time = [ int(latest_hour), int(latest_minute) + self.appt_time ] # Set next appointment if appt_time[1] >= 60: appt_time[0] += 1 # Goto next hour. appt_time[1] -= 60 if appt_time[0] >= self.time[1]: # Past work time self.exam_date += timedelta(1) # Try next day self.date_is_valid() # Make sure it's a business day else: return time(appt_time[0], appt_time[1]) # self.db.conn.close() # Check for earliest time available for date. ( 10 - 5 , in 30 minute intervals ) # If full, add a day and run date_is_valid again. def date_difference(self): difference = str(self.exam_date - self.initial_exam_date) if "," in difference: return int(difference.split(" ")[0]) # Get difference in days else: return 0 # Same day appointment