diff --git a/GUI.py b/GUI.py
index 24a07765c9ff2997893cf70d8d3136fdd93d1837..979774088fe0783d2b7bd4eac73838e304bb626e 100644
--- a/GUI.py
+++ b/GUI.py
@@ -74,7 +74,7 @@ def open_dashboard(user):
     dashboard.geometry("500x400")
 
     # Display Welcome Message Using `user.username`
-    welcome_label = Label(dashboard, text=f"Welcome, {user['username']}!", font=("Arial", 16))
+    welcome_label = Label(dashboard, text=f"Welcome, {user.userName}!", font=("Arial", 16))
     welcome_label.pack(pady=20)
 
     if isinstance(user, StaffUser):
@@ -106,9 +106,10 @@ def gui_login():
 
     # Call loginAttempt() from main.py
     user = loginAttempt(username, password)  
+    #logging.debug(user)
 
     if user:
-        messagebox.showinfo("Login", f"Login successful! Welcome {user['username']}.")
+        messagebox.showinfo("Login", f"Login successful! Welcome {user.userName}.")
         window.destroy()  # Close login window
         open_dashboard(user)  # Open appropriate dashboard based on user role
     else:
diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc
index 219c7b89736cb328d9b6f143a51c28993ccb875c..70f66fef1605820f3ec72c7edf20cf23200504d0 100644
Binary files a/__pycache__/main.cpython-312.pyc and b/__pycache__/main.cpython-312.pyc differ
diff --git a/main.py b/main.py
index b9d3f43ad20d3b316a45af126b55c573ac602177..5ba6806690db4bfb51e7800bd67b0fcf87374ab6 100644
--- a/main.py
+++ b/main.py
@@ -1,8 +1,10 @@
 import logging
-logging.basicConfig(level=0, format="{asctime} - {levelname} - {message}", style="{", datefmt="%Y-%m-%d %H:%M")
+logging.basicConfig(level=logging.DEBUG, format="{asctime} - {levelname} - {message}", style="{", datefmt="%Y-%m-%d %H:%M")
 from src import *
 from src.dbfunc import get_connection
 import json
+import pandas as pd
+import datetime as dt
 from src.staffUser import StaffUser
 from src.adminUser import AdminUser
 from src.managerUser import ManagerUser
@@ -21,37 +23,37 @@ from src.managerUser import ManagerUser
 
 
 def loginAttempt(username: str, password: str):
-    """Check if the user exists in the database and return the appropriate user object"""
+    """Check if the user exists in the database and return the appropriate user object
     
-    conn = get_connection()
-    if conn:
-        cursor = conn.cursor(dictionary=True)
-        
-        # Fetch user details from the database
-        cursor.execute("SELECT username, password_hash, role FROM users WHERE username = %s AND password_hash = %s", 
-                       (username, password))
-        user_data = cursor.fetchone()
-        
-        cursor.close()
-        conn.close()
-        
-        if user_data:
-            logging.info(f"User {user_data['username']} logged in successfully.")
-
-            # Return an instance of the correct user class
-            if user_data['role'] == 'Staff':
-                return StaffUser(username=user_data['username'])
-            elif user_data['role'] == 'Admin':
-                return AdminUser(username=user_data['username'])
-            elif user_data['role'] == 'Manager':
-                return ManagerUser(username=user_data['username'])
-            else:
-                logging.error("Unknown role in database.")
-                return None
-        else:
-            logging.warning("Invalid username or password.")
+    Arguments:
+        username (str) -- username for login.
+        password (str) -- password for login, plaintext?
+    Returns:
+        User object of type: StaffUser or AdminUser or ManagerUser
+        or None if failed login.
+    """
+    # dbug shortcut
+    if username=="debug" and password=="debug":
+        return ManagerUser(15, "manager", "password", [1], "Manager")
+    # using dbfuncs to do this:   cursor.execute("SELECT username, password_hash, role FROM users WHERE username = %s AND password_hash = %s", (username, password)) 
+    user_data = select_from_table_where("tblUsers", f"username = {username} AND password_hash = {password}", "username", "password_hash", "role")
     
-    return None  # Return None if no user found
+    if user_data:
+        logging.info(f"User {user_data['username']} logged in successfully.")
+
+        # Return an instance of the correct user class
+        if user_data['role'] == 'Staff':
+            return StaffUser(username=user_data['username'])
+        elif user_data['role'] == 'Admin':
+            return AdminUser(username=user_data['username'])
+        elif user_data['role'] == 'Manager':
+            return ManagerUser(username=user_data['username'])
+        else:
+            logging.error("Unknown role in database.")
+            return None
+    else:
+        logging.warning("Invalid username or password.")
+        return None  # Return None if no user found
 
 def staffUser_options_cli(user:StaffUser) -> None:
     while True:
@@ -82,6 +84,7 @@ def staffUser_options_cli(user:StaffUser) -> None:
     exit()
 
 def managerUser_options_cli(user:ManagerUser) -> None:
+    logging.debug("loaded into managerUser_options_cli.")
     while True:
         selection = input("Menu options:\n"
                           "  1. View Listings \n"
@@ -121,6 +124,17 @@ def adminUser_options_cli(user:AdminUser) -> None:
     user.logout()
     exit()
         
+def fetch_movies() -> dict:
+    raise NotImplementedError()
+    select_from_table("tblMovies")
+    
+def get_listings():
+    currentTime = dt.datetime.now()
+    listings = select_from_table_where("tblShowings", f"[{currentTime}] + show_time > sysdatetime()") # returns all data that matches today
+
+def display_listings_cli():
+    strListings = pd.DataFrame(get_listings())
+    return 
 
 def load_cinema(cinemaID) -> Cinema:
     raise NotImplementedError()
@@ -149,36 +163,32 @@ def main_cli() -> None:
     while True:
         username = encrypt(sanitize(input("Username: ")))
         password = encrypt(sanitize(input("Password: ")))
-        #user = loginAttempt(username=username, password=password)
-        user = ManagerUser(impBool=1) # dev remove later
-        if user is None:
+        user = loginAttempt(username=username, password=password)
+        
+        if username=="debug" and password=="debug":
+            logging.warning("Entered as debug user")
+            user = ManagerUser(15, "manager", "password", [1], "Manager")
+            #logging.debug(f"user object loaded as: {user}")
+            managerUser_options_cli(user)
+            break
+        elif user is None:
             print("Login attempt failed please try again.")
         else:
+            logging.debug(f"failed login, returned value: {user}")
             break
-    logging.info("successful login, loading menu...")
+    logging.info(f"successfuly loged in as {user.userName}, loading menu...")
     
     # based on the different user permision levels, load different menus.
-    match user.permissionLevel:
-        case 1:
-            managerUser_options_cli(user)
-        case 2:
-            adminUser_options_cli(user)
-        case _:
-            staffUser_options_cli(user)
+    if user.role=="Manager":
+        managerUser_options_cli(user)
+    elif user.role=="Admin":
+        adminUser_options_cli(user)
+    elif user.role=="Staff":
+        staffUser_options_cli(user)
 
 # following code will only execute if run directly from this file.
 if __name__ == "__main__":
     logging.debug("STARTING main_cli")
     main_cli()
     logging.debug("main_cli finished, program exiting. bye bye!")
-    
-def loginAttempt(username: str, password: str):
-    """Check if the user exists in the database"""
-    conn = get_connection()
-    if conn:
-        cursor = conn.cursor(dictionary=True)
-        cursor.execute("SELECT * FROM Users WHERE username = %s AND password_hash = %s", (username, password))
-        user = cursor.fetchone()
-        conn.close()
-        return user  # Returns user details if found
-    return None
\ No newline at end of file
+   
diff --git a/src/__pycache__/__init__.cpython-312.pyc b/src/__pycache__/__init__.cpython-312.pyc
index aaa784897475dad772c7a61107c760b558fdf570..22aab0c5e549be1de01acbc9f1c13180be82681e 100644
Binary files a/src/__pycache__/__init__.cpython-312.pyc and b/src/__pycache__/__init__.cpython-312.pyc differ
diff --git a/src/__pycache__/adminUser.cpython-312.pyc b/src/__pycache__/adminUser.cpython-312.pyc
index e862f6391397e9c67c1dd92ae1fbf20e7b084608..8cd0a263f4650f94ec2f3445ba63e1247b555380 100644
Binary files a/src/__pycache__/adminUser.cpython-312.pyc and b/src/__pycache__/adminUser.cpython-312.pyc differ
diff --git a/src/__pycache__/bookingObj.cpython-312.pyc b/src/__pycache__/bookingObj.cpython-312.pyc
index 4678c08d458aad37f39f436e7a08d250feb3dad2..a95cc5867d0668f4171d2ea00ba38fac6bad3dc5 100644
Binary files a/src/__pycache__/bookingObj.cpython-312.pyc and b/src/__pycache__/bookingObj.cpython-312.pyc differ
diff --git a/src/__pycache__/cinemaObj.cpython-312.pyc b/src/__pycache__/cinemaObj.cpython-312.pyc
index e889a025d413312cfd167d1a991a2a5909f13fd5..dfc88c86489f19e676778ae90beb1d855c1faffb 100644
Binary files a/src/__pycache__/cinemaObj.cpython-312.pyc and b/src/__pycache__/cinemaObj.cpython-312.pyc differ
diff --git a/src/__pycache__/constants.cpython-312.pyc b/src/__pycache__/constants.cpython-312.pyc
index d3bc49915e4b08b2493f7d0b87854b992d1d9ce7..3bb21f47a4f77a6782ebd8e3d633e0f1b851c44f 100644
Binary files a/src/__pycache__/constants.cpython-312.pyc and b/src/__pycache__/constants.cpython-312.pyc differ
diff --git a/src/__pycache__/dbfunc.cpython-312.pyc b/src/__pycache__/dbfunc.cpython-312.pyc
index 55dfe2f82b5871a26d95ff2418ec5379258e663c..5ba53e9ca58e4129c6cef290ff49a41264c7c450 100644
Binary files a/src/__pycache__/dbfunc.cpython-312.pyc and b/src/__pycache__/dbfunc.cpython-312.pyc differ
diff --git a/src/__pycache__/managerUser.cpython-312.pyc b/src/__pycache__/managerUser.cpython-312.pyc
index 066114c00fe160c03d83e6e6c335ee8c4347c0b7..f0e34ccdc3d8c4845b485f3bf05b7bc54e67f16d 100644
Binary files a/src/__pycache__/managerUser.cpython-312.pyc and b/src/__pycache__/managerUser.cpython-312.pyc differ
diff --git a/src/__pycache__/reportObj.cpython-312.pyc b/src/__pycache__/reportObj.cpython-312.pyc
index 84e9396990ad1e391f3e1c38a0873b3ca6ac71b5..7d4fc47261d2a1e864ba1e853418bb40b86ca611 100644
Binary files a/src/__pycache__/reportObj.cpython-312.pyc and b/src/__pycache__/reportObj.cpython-312.pyc differ
diff --git a/src/__pycache__/screenObj.cpython-312.pyc b/src/__pycache__/screenObj.cpython-312.pyc
index 404eaa518842cffc596ae0349cfae21c58093a3f..9d274a19a39a94de809bad84c3cc3abafab5b5dc 100644
Binary files a/src/__pycache__/screenObj.cpython-312.pyc and b/src/__pycache__/screenObj.cpython-312.pyc differ
diff --git a/src/__pycache__/staffUser.cpython-312.pyc b/src/__pycache__/staffUser.cpython-312.pyc
index 1aee61bed589a71284cd861e87f81a6ed12f6fe9..adcc99e4076d9a6c6abcf958eed4ad89ebdd0127 100644
Binary files a/src/__pycache__/staffUser.cpython-312.pyc and b/src/__pycache__/staffUser.cpython-312.pyc differ
diff --git a/src/adminUser.py b/src/adminUser.py
index 069c0d7d6d36921ab4acd46cd50fb0c42ae2ff8e..7dc9cb77b3dc538d3f0a9147cb47f653f22299ca 100644
--- a/src/adminUser.py
+++ b/src/adminUser.py
@@ -6,9 +6,9 @@ class AdminUser(StaffUser):
     Args:
         staffUser (_type_): _description_
     """
-    def __init__(self):
-        super().__init__()
-        self.permissionLevel = 1
+    def __init__(self, id:int, name:str, passw:str, cinemas:list, role:int):
+        super().__init__(self, id, name, passw, cinemas)
+        self.role = 1
 
 
 
diff --git a/src/dbfunc.py b/src/dbfunc.py
index d388d5a961cbb217b6d6eb9c0a5f9a73f03c8f8d..377eeff5c8f423058925b4984391b90f9299beeb 100644
--- a/src/dbfunc.py
+++ b/src/dbfunc.py
@@ -28,15 +28,13 @@ def get_connection():
         return None
 
 # Function to SELECT data from any table
-def select_from_table(table, *columns):
+def select_from_table(table, *args):
     """Fetches data from a given table."""
     conn = get_connection()
-    if not conn:
-        return []
 
     try:
         cursor = conn.cursor(dictionary=True)
-        query = f"SELECT {', '.join(columns) if columns else '*'} FROM {table}"
+        query = f"SELECT {', '.join(args) if args else '*'} FROM {table}"
         cursor.execute(query)
         results = cursor.fetchall()
         return results
@@ -48,24 +46,32 @@ def select_from_table(table, *columns):
         conn.close()
 
 # Function to SELECT data with a WHERE condition
-def select_from_table_where(table, condition, *columns):
-    """Fetches data from a table with a WHERE condition."""
+def select_from_table_where(table:str, condition:str, *args):
+    """Fetches data from a table with a WHERE condition.
+    
+    Arguments:
+        table (str): database table name, eg; "tblUsers"
+        condition (str): condition string in SQL format, eg; "WHERE username = %s AND password_hash = %s"
+        *columns: excepts all aditinal arguments and converts them into SQL query following SELECT as arguments, if none SQL statemnt uses *.
+    Returns:
+        dict
+    """
     conn = get_connection()
     if not conn:
         return []
 
     try:
         cursor = conn.cursor(dictionary=True)
-        query = f"SELECT {', '.join(columns) if columns else '*'} FROM {table} WHERE {condition}"
+        query = f"SELECT {', '.join(args) if args else '*'} FROM {table} WHERE {condition}"
         cursor.execute(query)
         results = cursor.fetchall()
         return results
     except mysql.connector.Error as err:
         logging.error(f"Error fetching data with condition: {err}")
-        return []
-    finally:
-        cursor.close()
-        conn.close()
+        return None
+    #finally:
+    #    cursor.close()
+    #    conn.close()
 
 # Function to INSERT data into any table
 def insert_into_table(table, data):
diff --git a/src/managerUser.py b/src/managerUser.py
index f74edda220127eaa6dd473011f64f4d446113948..18d72f2e530c017d9cf56f58051d51f53586270e 100644
--- a/src/managerUser.py
+++ b/src/managerUser.py
@@ -6,9 +6,9 @@ class ManagerUser(AdminUser):
     Args:
         userClass (_type_): _description_
     """
-    def __init__(self):
-        super().__init__()
-        self.permissionLevel = 2
+    def __init__(self, id:int, name:str, passw:str, cinemas:list, role:int):
+        super().__init__(self, id, name, passw, cinemas)
+        self.role = 2
     
     def expand_buisness(self):
         # creates new cinemaObj and adds it to db.
diff --git a/src/staffUser.py b/src/staffUser.py
index 27e217a97b3d5a6a74547b50801e1b6c91e0c866..0fcdd27f3df7c2ee415e1666207533891f7b61f1 100644
--- a/src/staffUser.py
+++ b/src/staffUser.py
@@ -5,25 +5,22 @@ from .cinemaObj import Cinema
 
 
 # trying to make this a base implementation for all user classes.
-class StaffUser(object):  
-    def __init__(self, id:int, name:str, passw:str, permLvl:int, cinemas:list, impBool:bool=0):
-        # impbool used to switch case on a newly created user or imported from database.
-        if impBool:
-            # import user from db
-            select_from_tbl_where(table="tblUsers", condition="")
-            pass
-        else:
-            # staff id number assigned by manager during onboarding.
-            self.userID:int = id
-            self.userName:str = name
-            self.userPass:str = passw
-            # staff software level.
-            self.permissionLevel:int = permLvl
-            # list of branches active at.
-            self.cinemas = cinemas
-        
-    def __str__(self):
-        return f"{self.__class__.__name__} user object(userID={self.userID}, userName={self.userName}, userPass={self.userPass}, permissionLevel={self.permissionLevel})"
+class StaffUser:  
+    def __init__(self, id:int, name:str, passw:str, cinemas:list, role:int):
+        # staff id number assigned by manager during onboarding.
+        self.userID:int = id
+        self.userName:str = name
+        self.userPass:str = passw
+        # staff software level.
+        self.role:int = role
+        # list of branches active at.
+        self.cinemas = cinemas
+    
+    
+    # function not working, causes massive recursion?
+    #def __repr__(self):
+    #"""this function returns this object in a string readable format, eg; print(staffUser) returns 'StaffUser user object(userID=1, userName='user', userPass='password'... ' """
+    #    return f"{self.__class__.__name__} user object(userID={self.userID}, userName={self.userName}, userPass={self.userPass}, permissionLevel={self.role})"
 
     def login(self, userName, userPassword) -> None:
         """get values for self from db"""