Interview-Backend/WriteDB.py

157 lines
6.9 KiB
Python

import pandas as pd
import json
from openpyxl import load_workbook
from send_email import send_email
from filelock import FileLock
import datetime
"""
TODO make it work with the new template
TODO update names to be more clear
TODO try to remove pandas
"""
def ReadDatabase():
"""
Reads the Database to retrieve available interview slots
``REQUIRES``: None
``PROMISES``: JSON (Available interview slots)
``Developed by``: Ahmad, Brock
``Contact``: ahmad.ahmad1@ucalgary.ca, darkicewolf50@gmail.com
"""
year_donation = int(str(datetime.datetime.now().year)[2:]) + 1 # gets the last two digits of the current year then adds 1 for the current season
# name based off the 2025 naming system
file_path = f"OR{year_donation}-L-Interview Data.xlsx"
lock_path = f"OR{year_donation}-L-Interview Data.xlsx.lock"
# Use a file-based lock for thread-safe and process-safe access
with FileLock(lock_path):
# Load the Excel file into a pandas DataFrame with specific columns
df = pd.read_excel(file_path, usecols=['Date', 'Start Time', 'Slot', 'Interviewee Name', 'Interviewee Email', 'Meeting Duration'])
# Initialize the dictionary to store structured data for available slots
interview_data = {}
# Process each row in the DataFrame to structure data by date and time
for _, row in df.iterrows():
# Convert Date and Start Time to string format for easier comparison
date = str(row['Date']).split(" ")[0] # Format date to YYYY-MM-DD
start_time = str(row['Start Time'])
# Calculate the slot capacity and current number of interviewees
slot_capacity = int(row['Slot']) if not pd.isna(row['Slot']) else 0
interviewee_names = [name.strip() for name in str(row['Interviewee Name']).split(',') if name.strip()]
interviewee_count = len(interviewee_names) if interviewee_names != ["nan"] else 0
# Check if there are available slots for more interviewees
if interviewee_count < slot_capacity:
# Organize data by date and time, keeping track of available slots and meeting duration
if date not in interview_data:
interview_data[date] = {}
interview_data[date][start_time] = {
'Meeting Duration': row['Meeting Duration'],
'Available Slots': slot_capacity - interviewee_count
}
return interview_data
def AppendAppointment(date, start_time, interviewee_name, interviewee_email):
"""
Appends a new appointment with the interviewee's name and email if the slot is available.
``REQUIRES``: ``str`` date, ``str`` start_time, ``str`` interviewee_name, ``str`` interviewee_email
``PROMISES``: ``None`` Updates the Excel file with the new interviewee's name and email if there is an available slot. Returns Bool.
``Developed by``: Ahmad, Brock
``Contact``: ahmad.ahmad1@ucalgary.ca, darkicewolf50@gmail.com
"""
year_donation = int(str(datetime.datetime.now().year)[2:]) + 1 # gets the last two digits of the current year then adds 1 for the current season
# name based off the 2025 naming system
file_path = f"OR{year_donation}-L-Interview Data.xlsx"
lock_path = f"OR{year_donation}-L-Interview Data.xlsx.lock"
available_slots = ReadDatabase()
# Check if the requested slot is available in the `available_slots` structure
if date in available_slots and start_time in available_slots[date]:
with FileLock(lock_path): # Ensure process-safe access to the file
# Load workbook and select "Sheet1" for updating appointments
workbook = load_workbook(file_path)
sheet = workbook["Interview Timetable"]
df = pd.read_excel(file_path)
# Find and update the row that matches the provided date and start time
for index, row in df.iterrows():
row_date = str(row['Date']).split(" ")[0]
row_start_time = str(row['Start Time'])
if row_date == date and row_start_time == start_time:
# Current entries for names and emails, and append new data with comma and space
current_names = str(row['Interviewee Name']).strip()
current_emails = str(row['Interviewee Email']).strip()
updated_names = f"{current_names}, {interviewee_name}" if current_names != "nan" else interviewee_name
updated_emails = f"{current_emails}, {interviewee_email}" if current_emails != "nan" else interviewee_email
# Update the cells with new names and emails
name_cell = sheet.cell(row=index + 2, column=df.columns.get_loc('Interviewee Name') + 1)
email_cell = sheet.cell(row=index + 2, column=df.columns.get_loc('Interviewee Email') + 1)
name_cell.value = updated_names
email_cell.value = updated_emails
workbook.save(file_path)
send_email(interviewee_email, interviewee_name, date, start_time)
return True
# If no slots available, return that the slot is unavailable
return False
def run_tests():
"""
Executes test cases to verify appointment scheduling and slot availability.
``REQUIRES``: None
``PROMISES``: Prints test outcomes to validate successful booking or slot unavailability.
"""
print("Available Slots:")
available_slots = ReadDatabase()
print(json.dumps(available_slots, indent=4))
# Test Case 1: Append to an available slot on 2024-09-16 at 10:30:00
date_1 = "2024-09-16"
start_time_1 = "10:30:00"
interviewee_name_1 = "Alice Johnson"
interviewee_email_1 = "ahmadmuhammadofficial@gmail.com"
print(f"\nTest Case 1: Trying to book {date_1} at {start_time_1} for {interviewee_name_1} ({interviewee_email_1})")
AppendAppointment(date_1, start_time_1, interviewee_name_1, interviewee_email_1)
# Test Case 2: Append to an available slot on 2024-09-17 at 13:30:00
date_2 = "2024-09-17"
start_time_2 = "13:30:00"
interviewee_name_2 = "Bob Smith"
interviewee_email_2 = "bob.smith@example.com"
print(f"\nTest Case 2: Trying to book {date_2} at {start_time_2} for {interviewee_name_2} ({interviewee_email_2})")
AppendAppointment(date_2, start_time_2, interviewee_name_2, interviewee_email_2)
# Test Case 3: Attempting to book at 10:30:00 on 2024-09-16 for a different interviewee
date_3 = "2024-09-16"
start_time_3 = "10:30:00"
interviewee_name_3 = "Charlie Brown"
interviewee_email_3 = "charlie.brown@example.com"
print(f"\nTest Case 3: Trying to book {date_3} at {start_time_3} for {interviewee_name_3} ({interviewee_email_3})")
AppendAppointment(date_3, start_time_3, interviewee_name_3, interviewee_email_3)
# Run tests
if __name__ == "__main__":
run_tests()