diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/advanced-software.iml b/.idea/advanced-software.iml
new file mode 100644
index 0000000000000000000000000000000000000000..94219bfb571a5449637a48cca9fd47ee28ee95b5
--- /dev/null
+++ b/.idea/advanced-software.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+  <component name="PyDocumentationSettings">
+    <option name="format" value="GOOGLE" />
+    <option name="myDocStringFormat" value="Google" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/git_toolbox_blame.xml b/.idea/git_toolbox_blame.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7dc124965d28403ec2545a24d7d1cd1fec1f57d8
--- /dev/null
+++ b/.idea/git_toolbox_blame.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GitToolBoxBlameSettings">
+    <option name="version" value="2" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..db8786c06ed9719181cd25ebe2615cc99c8490eb
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Black">
+    <option name="sdkName" value="Python 3.12" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6e981942be16c2945e2d4b6bb5eb4a577e9b4ace
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/advanced-software.iml" filepath="$PROJECT_DIR$/.idea/advanced-software.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/main.py b/main.py
index a505e980ee214beb53c6f2f989ae1feb8359d845..0a764116a2fe7e4fb9901b975395dbc0fa472d93 100644
--- a/main.py
+++ b/main.py
@@ -1,93 +1,147 @@
+import logging
+logging.basicConfig(level=logging.DEBUG, format="{asctime} - {levelname} - {message}", style="{", datefmt="%Y-%m-%d %H:%M")
 from src import *
 
-
-
-
-
-
-
-
 """_summary_
 
-- logic should be seprate from the GUI
+- logic should be separate from the GUI
 - this file handles interfacing with the database and classes.
-- most functionalisty should also be here
+- most functionality should also be here
 - using main() as a test function during development, and after can be used as a CLI version of the program.
 
-'idealy there should be a sort of intermeditary between the GUI and database, for example last year most groups queried the database directly from tkintet, although thats not ideal.' - lecturer idk there name
+'ideally there should be a sort of intermediary between the GUI and database, for example last year most groups queried the database directly from tkinter, although that's not ideal.' - lecturer idk there name
 'you should be able to make python classes directly from your class diagram' - same lecturer
 
 """
 
 
-def loginAttempt(username, password):
+def loginAttempt(username: str, password: str) -> StaffUser | ManagerUser | AdminUser | None:
     """_summary_
 
-    quereies database for matching args
+    queries database for matching args
     returns user(staff, admin or manager) obj if found
     else returns None type.
         
     Args:
-        username (_type_): _description_
-        password (_type_): _description_
-
-    Returns:
-        staffUser: _description_
-        or
-        None
+        username (str): encrypted username
+        password (str): encrypted password
     """
-    return True # testing passthrough
-
+    del_later = StaffUser()
+    del_later.userName = username
+    del_later.userPass = password
+    return del_later
+
+def staffUser_options_cli(user:StaffUser) -> None:
+    selection = True
+    while selection:
+        selection = input("Menu options:\n"
+                          "  1. View Listings \n"
+                          "  2. Create booking \n"
+                          "  3. Logout \n"
+                          "  please return a number to select: ")
+        # switch case:
+        if selection == "1":
+            logging.debug("selection 1, View listings")
+            user.viewFilmListings()
+            # get from cinema the listings and display film data in dict/jason
+            # user.viewFilmListings()
+            # format and display data
+        elif selection == "2":
+            logging.debug("selection 2, Create booking")
+            # create booking obj and display attributes for selection
+            # save booking to cinema and db
+            # user.createBooking()
+        elif selection == "3":
+            logging.debug("selection 3, logout")
+            user.logout()
+            exit()
+        else:
+            print("Invalid input, please input an integer value corresponding with an option.")
+            selection = True
+
+def managerUser_options_cli(user:ManagerUser) -> None:
+    selection = True
+    while selection:
+        selection = input("Menu options:\n"
+                          "  1. View Listings \n"
+                          "  2. Create booking \n"
+                          "  3. Logout \n"
+                          "  please return a number to select: ")
+        # switch case:
+        if selection == "1":
+            logging.debug("selection 1, View listings")
+        elif selection == "2":
+            logging.debug("selection 2, Create booking")
+        elif selection == "3":
+            logging.debug("selection 3, logout")
+            user.logout()
+            exit()
+        else:
+            print("Invalid input, please input an integer value corresponding with an option.")
+            selection = False
+
+def adminUser_options_cli(user:AdminUser) -> None:
+    selection = True
+    while selection:
+        selection = input("Menu options:\n"
+                          "  1. View Listings \n"
+                          "  2. Create booking \n"
+                          "  3. Logout \n"
+                          "  please return a number to select: ")
+        # switch case:
+        if selection == "1":
+            logging.debug("selection 1, View listings")
+        elif selection == "2":
+            logging.debug("selection 2, Create booking")
+        elif selection == "3":
+            logging.debug("selection 3, logout")
+            user.logout()
+            exit()
+        else:
+            print("Invalid input, please input an integer value corresponding with an option.")
+            selection = False
 
-def logout():
+def load_cinema(cinemaID) -> Cinema:
     pass
 
-def load_cinema():
-    pass
+def san(string:str) -> str:
+    """
+    String sanitization function
+    Args:
+        string (str): string variable to be sanitized.
+    Returns:
+        string but without any escape chars
+    """
+    return string.strip().replace('/', '_').replace('\\', '_')
 
 def save():
     pass
 
-def cli_main() -> None:
-    print("\n\nSTARTING CINEMA MANAGEMENT SYSTEM.\n\n\n\n")
+def main_cli() -> None:
+    print("\n\nSTARTING CINEMA MANAGEMENT SYSTEM.\n\n")
+    # test db is connected....
+#    if not getConnection():
+#        logging.critical("Database cannot connect, or dose not exist. \nClosing application.")
+#        exit()
     user = None
-    while user == None:
+    while user is None:
         username = str(input("To login please enter your\nUsername: "))
         password = str(input("Password: "))
         user = loginAttempt(username=username, password=password)
-        if user == None:
+        if user is None:
             print("Login attempt failed please try again.")
         else:
             break
-    print("successful login, loading menue...")
-    # load user
-    # load cinema/s that user is linked to
-    #cinema = Cinema()
-    # display options
-    selection = input("Menue options:\n\
-        1. Veiw Listings \n\
-        2. Create booking \n\
-        3. Logout \n\
-        please return a number to select: ")
-    # switch case:
-    if selection == "1":
-        print("1")
-        # get from cinema the listings and display film data in dict/jason
-        # user.veiwFilmListings()
-        # format and display data
-        pass
-    elif selection == "2":
-        print("2")
-        # create booking obj and display attributes for selection
-        # save booking to cinema and db
-        # user.createBooking()
-        pass
-    elif selection == "3":
-        print("3")
-        #user.logout()
-        pass
-    
+    print("successful login, loading menu...")
+    user.login()
+
+    if user.permissionLevel == 1:
+        managerUser_options_cli(user)
+    elif user.permissionLevel == 2:
+        adminUser_options_cli(user)
+    else:
+        staffUser_options_cli(user)
 
 # following code will only execute if run directly from this file.
 if __name__ == "__main__":
-    cli_main()
\ No newline at end of file
+    main_cli()
\ No newline at end of file
diff --git a/src/__init__.py b/src/__init__.py
index d3718c6aaa5bd127244cf3a43ced4feb15e3050e..c20c3f1f9fd36cd52071413eed913cdd5660d68e 100644
--- a/src/__init__.py
+++ b/src/__init__.py
@@ -1,13 +1,14 @@
-from .staffUser import *
-from .adminUser import *
-from .cinemaObj import *
-from .managerUser import *
-from .bookingObj import *
-from .reportObj import *
-from .screenObj import *
+from .staffUser import StaffUser
+from .adminUser import AdminUser
+from .cinemaObj import Cinema
+from .managerUser import ManagerUser
+from .bookingObj import Booking
+from .reportObj import Report
+from .screenObj import Screen
 from .constants import *
 from .dbfunc import *
 
+"""
 __all__ = ["adminUser",
            "bookingObj",
            "cinemaObj",
@@ -17,4 +18,5 @@ __all__ = ["adminUser",
            "managerUser",
            "reportObj",
            "screenObj",
-           "staffUser"]
\ No newline at end of file
+           "staffUser"]
+"""
\ No newline at end of file
diff --git a/src/constants.py b/src/constants.py
index ffd8f86a665196230526d9c3a4dac0fc3d1ce7ff..dc652f59d5acca9b5edf1db9c7341362d6f9ef4e 100644
--- a/src/constants.py
+++ b/src/constants.py
@@ -1,10 +1,15 @@
+# all constants are followed by docstrings labeling them, these strings show on hover in most IDEs(vscode and pycharm at least)
 
-# screeen size in meaters 
-MAX_screen_size:float = 100.0
-MIN_screen_size:float = 0.0
-# screen resolution in px
-MAX_screen_resolution:int = 5000
-MIN_screen_resolution:int = 0
-# seating capacity in screen room
-MAX_screen_capacity:int = 500
-MIN_screen_capacity:int = 0
+# screenObj:
+MAX_SIZE:float = 100.0
+"""Maximum screen size in meters"""
+MIN_SIZE:float = 0.0
+"""Minimum screen size in meters"""
+MAX_RES:int = 5000
+"""Maximum screen resolution in px"""
+MIN_RES:int = 0
+"""Minimum screen resolution in px"""
+MAX_CAP:int = 500
+"""Maximum screen room seating capacity"""
+MIN_CAP:int = 0
+"""Minimum screen room seating capacity"""
diff --git a/src/dbfunc.py b/src/dbfunc.py
index 229334ed4ff2053098ff5c12dc87f98b963875ce..bb661660efec2f040b21035863ce7cb0907922ba 100644
--- a/src/dbfunc.py
+++ b/src/dbfunc.py
@@ -1,3 +1,4 @@
+import logging
 import mysql.connector
 from mysql.connector import errorcode
 
@@ -8,7 +9,7 @@ passwd = ""
 
 
 def getConnection(db=""):
-    # if specifyed database
+    # if specified database
     if db != "":
         
         try:
@@ -18,15 +19,15 @@ def getConnection(db=""):
                 database = db)
         except mysql.connector.Error as err:
             if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
-                print("Username or Password is not working")
+                logging.error("Username or Password is not working")
             elif err.errno == errorcode.ER_BAD_DB_ERROR:
-                print("Database dose not exist")
+                logging.error("Database dose not exist")
             else:
-                print(err)
+                logging.error(err)
         else:
-            print("Connected to server.")
+            logging.info("Connected to server.")
             return conn
-    # if database not specifyed try defult from line 5
+    # if database not specified try default from line 5
     else:
         try:
             conn = mysql.connector.connect(host = hostname,
@@ -34,9 +35,9 @@ def getConnection(db=""):
                 password = passwd)
         except mysql.connector.Error as err:
             if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
-                print("Username or Password is not working")
+                logging.error("Username or Password is not working")
             else:
-                print(err)
+                logging.error(err)
         else:
-            print("Connected to server, without database.")
+            logging.error("Connected to server, without database.")
             return conn
\ No newline at end of file
diff --git a/src/screenObj.py b/src/screenObj.py
index 497576c3cfb12a3982f69452dab57fe6d1786155..efcbae7b679ef16e3c1cdf36a689bf2ff41ea241 100644
--- a/src/screenObj.py
+++ b/src/screenObj.py
@@ -1,4 +1,4 @@
-from .constants import MIN_screen_capacity, MAX_screen_capacity, MIN_screen_resolution, MAX_screen_resolution, MIN_screen_size, MAX_screen_size
+from .constants import MIN_CAP, MAX_CAP, MIN_RES, MAX_RES, MIN_SIZE, MAX_SIZE
 
 class Screen(object):
     """_summary_
@@ -6,14 +6,14 @@ class Screen(object):
     Args:
         object (_type_): _description_
     """
-    def __init__(self, id:int, capacity:int=0, sizeH:int=0, sizeW:int=0, resolutionH:float=0.0, resolutionW:float=0.0, isIMAX:bool=False) -> None:
-        self.id = id
-        self.capacity:int = capacity
-        self.screenSizeHeight:int = sizeH
-        self.screenSizeWidth:int = sizeW
-        self.screenResolutionHeight = resolutionH
-        self.screenResolutionWidth = resolutionW
-        self.isIMAX:bool = isIMAX
+    def __init__(self) -> None:
+        self.id = 0
+        self.capacity: int = 0
+        self.screenSizeHeight: int = 0
+        self.screenSizeWidth: int = 0
+        self.screenResolutionHeight: int = 0
+        self.screenResolutionWidth: int = 0
+        self.isIMAX: bool = False
         
     def __str__(self) -> str:
         return f"Screen(id={self.id}, capacity={self.capacity}, screenSize={self.screenSize}, screenResolution={self.screenResolution}, isIMAX={self.isIMAX})"
@@ -28,27 +28,27 @@ class Screen(object):
     # Getters, inherited from Object class
     # Setters
     def set_capacity(self, value:int) -> None:
-        if MIN_screen_capacity >= value >= MAX_screen_capacity:
+        if MIN_CAP >= value >= MAX_CAP:
             self.capacity = value
         else:
             # log
-            print(f"Error; input({value}) out of range {MIN_screen_capacity}-{MAX_screen_capacity}.")
+            print(f"Error; input({value}) out of range {MIN_CAP}-{MAX_CAP}.")
         
     def set_screen_size(self, height:float, width:float) -> None:
-        if MIN_screen_size >= height >= MAX_screen_size or MIN_screen_size >= width >= MAX_screen_size:
+        if MIN_SIZE >= height >= MAX_SIZE or MIN_SIZE >= width >= MAX_SIZE:
             self.screenSizeHeight = float(height)
             self.screenSizeWidth = float(width)
         else:
             # log
-            print(f"Error, input values:{height}m, {width}m out of bounds {MIN_screen_size}-{MAX_screen_size}m")
+            print(f"Error, input values:{height}m, {width}m out of bounds {MIN_SIZE}-{MAX_SIZE}m")
 
     def set_screen_resolution(self, height:int, width:int) -> None:
-        if MIN_screen_resolution >= height >= MAX_screen_resolution or MIN_screen_resolution >= width >= MAX_screen_resolution:
+        if MIN_RES >= height >= MAX_RES or MIN_RES >= width >= MAX_RES:
             self.screenSizeHeight = height
             self.screenSizeWidth = width
         else:
             # log
-            print(f"Error, input values:{width}x{height}p out of bounds {MIN_screen_resolution}-{MAX_screen_resolution}")
+            print(f"Error, input values:{width}x{height}p out of bounds {MIN_RES}-{MAX_RES}")
 
 
 
diff --git a/src/staffUser.py b/src/staffUser.py
index bc2279491450507e9dfdaddd3c9a00fd3b0027f0..eed2bbecd59ec542deaf9779e8e83f860f90eef7 100644
--- a/src/staffUser.py
+++ b/src/staffUser.py
@@ -8,6 +8,7 @@ class StaffUser(object):
         self.userName:str = self.encrypt("")
         self.userPass:str = self.encrypt("")
         self.permissionLevel:int = 0
+        self.cinemas = [0]
         
     def __str__(self):
         if self.permissionLevel == 1:
@@ -18,19 +19,31 @@ class StaffUser(object):
             userType = "BookingStaff"
         return f"{userType} user object(userID={self.userID}, userName={self.userName}, userPass={self.userPass})"
     
+#    @property
+#    def options_list(self) -> dict:
+#        """_summary_
+#        functions in a dict, to be used as labels and callable function pairs
+#        Returns:
+#            dict: _description_
+#        """
+#        options:dict = {"View film Listings":self.viewFilmListing, "Create booking":self.createBooking, "Logout":self.logout}
+#        return options
+    
     def login(self):
-        pass
+        print("this is the login func")
         
     def logout(self):
         pass
     
-    def veiwFilmListing(self, cinemaID):
-        pass
+    def viewFilmListings(self):
+        print("this is the viewFilmListing func")
+        # load cinema.showings
+        listing_format = f""
     
     def createBooking(self):
-        pass
+        print("this is the createBooking func")
     
-    def manageBooking():
+    def manageBooking(self):
         pass
     
     def encrypt(self, inputString):