Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 159 additions & 42 deletions documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,31 @@
The goal of this file is to provide a higher level overview of how this script works to help identify issues, improvements, as well as future maintainability.
## At a Glance
There are two primary methods that this script runs through: The CLI version and the GUI version. The CLI version is more or less function complete in how I intend for it to function and operate, though it still has some rough edges, especially in a user interaction factor. The GUI version is what will continue to receive updates and more improvements over time. These two versions can be toggled between in the `config.ini` file.
---

## Overall Flow
There are four primary functions this whole script sets out to do and maintain as of writing this. These four things are:
1. Creating an Excel sheet from data from a couple of different sources, being the bookstore list for the books, Alma Open Access Analytics, Outlook for emails to help contact professors, and CORE enrollment reports to aid in decision making
2. Creating and formatting emails to compile into an Excel sheet to be fed into PowerAutomate, as well as updating the main Excel sheet with what emails have already been created
3. Updating cached/previously collected information that is stored in CSV files in a modular way to keep time and attention required as low as possible
4. Updating the main Excel sheet with newly scraped data in the case that there is previously missing data that was added to any of the sources

Points 3 and 4 mainly touch on helping facilitate data collection and updating at later points and as such are not the most intensive or directly important parts of the script. On top of all this, this script has two primary modes with some functions being strictly for one or the other, while others simply have a toggle or require no user input / interaction. These two modes are the CLI and GUI mode, but as of now, the GUI option and implementations are the standard. On top of this, `utilties.py` are helper functions used across the whole project.

### Creating an Excel Sheet
To understand the overall process for creating an Excel sheet, it would be best to look inside `sheetmaker.py` as that is the core of that function in how it interacts with everything else. In short, we start with books from the bookstore that was scraped using the `bookstore.py` functions. This gets saved for later to speed up processing time as `bookstore.csv`. These books are processed via `classes.py`, broken down for their components and their ISBN is searched against a couple of different facets in `analytics.py` to pull all the relevant data for them, publication year, access type, internal identification numbers, etc. These bookstore entries also come with names of instructors alongside class codes, this information is passed onto `grabber.py` to pull the instructor email, which is saved to `emails.csv` once pulled. After all this data is processed, everything from `analytics.csv`, `emails.csv`, and `enrollment.csv` is compiled into the output Excel sheet. The `enrollment.csv` data is read via the `enrollment.py` script. Header names are taken from `headers.ini`

### Email Formatting
As far as email formatting, it reads directly from the output Excel sheet from the prior step, or at least a sheet that uses matches formatting. It takes in information such as the instructor name, email, course information with section numbers, as well as the basic book information to format links. All of this is conducted within `emails.py`. It then updates the main Excel sheet with which emails have been formatted and presumably sent. Some of the language is taken from the `emails.ini` file.

### Updating CSV Files
Updating is done via the `modes.py` script to make function calls to the other parts of the project as they need to. These functions all export to their respective csv files as well.

### Updating the Main Excel Sheet
Updates the main excel sheet using the csv file information if new data gets scraped, also managed through `modes.py`.

## main.py
This file serves as the starting point for the whole script. If the GUI mode is activated, it will start the GUI from `gui.py`, otherwise, it will take an input from the user and pass it over to `sheetmaker.py` if you're making a new sheet or to `modes.py` if you're using the other features.

## analytics.py
Anything related to handling data from Alma gets handled through this script. Between setting up the browser, parsing the HTML, and handling inputs for things such as the SQL.
### get_columns
Expand Down Expand Up @@ -54,17 +76,23 @@ Imports data from the bookstore csv file, mainly used by other parts of the prog
## classes.py
Stores the frameworks and methods for interacting with storing and processing book related data.
### Book (Class)
- Contstructor
- **Constructor**

Creating an object requires a dictionary of a couple different values: Related course, section, instructor name and email, enrollment information, the ISBN, book title, author, edition, publisher, requirements state, requisition date, the bookstore comment, and the Alma Analytics data for the given book. The constructor will parse out the information to make it more easily accessible for processing later.
- add_course
- **add_course**

When another entry for a book is found that already exists as an object, the new course information gets added via this function.
- add_section
- **add_section**

Similar to the course entry, but instead adding a section to an existing course within an existing book.
- add_isbn
- **add_isbn**

Adding ISBN values for different variants of the same book.
- add_enroll
- **add_enroll**

Putting in additional enrollment information into the book to track all the campuses and possible enrollment values.
- add_required
- **add_required**

If at any point a bookstore listing has the book as "Required", it sets the book to that status using this function.
### get_max_index
Finds the index of the course with the most sections within it in order to aid in reducing column count, as well as ensuring the largest courses are always first (leftmost).
Expand All @@ -87,12 +115,15 @@ Imports all the data from the master book object list and imports it into the da
Handles compiling and creating Excel sheets for PowerAutomate emails.
### Book (Class)
This class is a very tiny version of the other class that just takes in some basic information for the purposes of emails.
- Constructor
- **Constructor**

Takes the title, author, edition, year published, and access information.
### Instructor (Class)
- Constructor
- **Constructor**

Takes in the instructor name, email, as well as course, section, and book information per section.
- add_book
- **add_book**

Adds books to a given course section for each professor.
### update_excel
Updates the main sheet with marking off what emails have been successfully created.
Expand All @@ -109,71 +140,143 @@ Processes the format of the given CORE report enrollment file, returning campus
## grabber.py
Deals with setting up and handling pulling data from the Outlook browser to get emails for individual professors.
### process_name
Handles iterating through the names that are shown and put into the Outlook window to grab emails.
### process_suggestion
Helps with grabbing the information from the top of the suggestion box.
### get_email
Grabs the first email from the suggestion box.
### setup_grabber
Starts up and initializes the browser to work with to pull data from Outlook.
### grabber_gui
- set_email_store
- run_process_suggestion
- run_check_ui
- run_check_web
- run_suggestion_ui
- run_get_email
GUI variation of the implementation across this file. Functions are created in different versions and variants to utilize smaller GUI windows and threading to ensure no issues occur.
- **set_email_store**

Setter function to aid in providing button functionality to the helper GUI.
- **run_process_suggestion**

Smaller form process_suggestion function to pull the raw HTML from the page to find the suggestion box.
- **run_check_ui**

Creates a smaller GUI window to provide instructions on setting up the web window.
- **run_check_web**

Checks if the user has created the email composition window.
- **run_suggestion_ui**

Provides the user with options to select from that were in the suggestion box.
- **run_get_email**

Processes the suggestion box into names and emails.
### email_importer
Imports prior email information into a dictionary.
### email_exporter
Exports email information into a csv file with name email pairs.

## gui.py
This hosts all of the primary interactive GUI for the user.
### GUI (Class)
- Constructor
- reset_main
- print_main
- build_main
- build_emails
- build_headers
- build_advanced
- build_sheet_outlook
- build_sheet_alma
- build_sheet_final
- build_import_csv
- start_analytics_csv
- start_bookstore_csv
- start_grabber_csv
- start_mode
- write_cfg
- write_headers
- write_emails
- **Constructor**

This constructor takes in a TKinter root GUI window. Sets up the various facets of the window, including names and sizing.
- **reset_main**

Resets the main window to a blank screen. Best used before adding elements.
- **build_main**

Constructs the main screen with all the relevant buttons and functions.
- **build_emails**

Creates the email window to modify the language used in the automated script.
- **build_headers**

Creates the header window to change the names of the headers.
- **build_advanced**

Creates the advanced options window.
- **build_sheet_outlook**

Subscreen for asking the user if they would like to open Outlook prior to creating an Excel sheet.
- **build_sheet_alma**

Subscreen for asking the user if they would like to open Alma prior to creating an Excel sheet.
- **build_sheet_final**

Final function to run to initialize creating an Excel sheet from scratch and resetting the main screen.
- **build_import_csv**

Subscreen to ask if the user wants to import prior csv information for any updating service through the script.
- **start_analytics_csv**

Function to start pulling data from Alma.
- **start_bookstore_csv**

Function to start pulling data from the bookstore.
- **start_grabber_csv**

Function to start pulling data from Outlook for the emails.
- **start_mode**

Handles the main window inputs.
- **write_cfg**

Writes information back to the main configuration file.
- **write_headers**

Writes the information from the header tab back into `headers.ini`.
- **write_emails**

Writes the template information to the `emails.ini` config file.
### start_app
Starts the main GUI application.

## helpergui.py
This is a much slimmer and simpler version of the main GUI class, to be something much more modular and additive.
### AddedGUI (Class)
- Constructor
- reset
- add_label
- add_button
### make_window
- **Constructor**

Takes a title for the window, otherwise just sets the base components.
- **reset**

Resets the window information.
- **add_label**

Adds a text label to the window.
- **add_button**

Adds a button to the window with a passable command.

## modes.py
Aids in handling the various functions of the script, modularizing individual pieces into useful functions.
### start_mode
Takes a flag from the CLI main file on which mode to start.
### csv_mode
Submenu to select which csv file to update.
### email_mode
Starts the email creation portion of the script.
### update_mode
Submenu to select which information to update the Excel sheet with.
### emails_csv
Opens Outlook to update the emails csv file.
### analytics_csv
Updates the analytics csv file.
### enrollment_update
Updates missing or empty enrollment information on the Excel sheet.
### analytics_update
Updates empty portions within the analytics portion of the Excel sheet.
### emails_update
Updates the email columns on the Excel sheet.
### get_import
Asks the user if they would like to import prior csv information.

## output.py
This script has a single function: outputting an Excel sheet! This is where formatting and such gets handled (i.e. color, column sizing, etc.)
### write_to_sheet
Handles all the formatting and information regarding how colors and columns get processed.

## sheetmaker.py
Performs all of the functions related to creating new sheets from scratch.
### make_excel_sheet
Works with other portions of the script to update, finalize, and format an Excel sheet to completion.

## utilties.py
This script hosts helpful functions that might be purposeful in multiple places around the various helper and main scripts. On top of this, it also helps to host hard coded data that is not necessary to keep in a configuration file (such as header values!). The organization is to help cut down on lines of code in other places, as well as keep information consistency so updating one variable does update it in all relevant places when needed.
Expand All @@ -184,22 +287,36 @@ Removes preset phrases and terms from the names of books and authors to reduce t
### get_state
Takes strings of "True" or "False" and converts them to bool values.
### get_directory
Takes a string and the config file to pull it from to get a directory.
### get_filepath
Given a direct file path, it will grab the direct path to the file given.
### get_letter
Utilized to convert number of columns into the letter code.
### get_edition_string
Converts a number to have the "st", "nd", "rd", and "th" at the end.
### get_format_headers
Gets the headers and information for the columns with course, section, and instructor infromation.
### get_replace_header
Takes the format headers and automatically replaces the information out from them given the course number, section number, and the added information at the end.
### get_split_course
Splits course codes into individual components of subject and number.
### get_input
Gets an input between a set number range with a text to display to the user.
### get_enabled
Asks the user "y/n" for True or False.
### get_sheet_headers
Returns the headers for the columns that are stored in the config file.
### get_config_headers
Returns the config file read directly from the configuration parser.
### get_string_cleaners
Gets the list of things to parse out of the titles from the bookstore to clean them and consolidate titles and authors.
### get_row_info
Given a row from the dataframe and a key to access it, it error checks against blank information and reads it.
### get_campus
Gets the full campus name given the letter code for the individual campus.
### set_col_format
A
---
Sets the formatting to a uniform format for the Excel sheet.

## CSV Storage
In order to store all the data in a way that is accessible, quick, and aids in subsequent run times, all pulled data is compiled into `.csv` files, each with their own format. This makes it so we don't have to re-run the bookstore scraper, email grabber, or analytics scraper again every single time we wish to do something.
### analytics.csv
Expand All @@ -219,7 +336,7 @@ Data is formatted as following:
Instructor Name, Email
### enrollment.csv
This is just a CORE report exported as a csv for all courses in the desired term. This must be done outside of the script itself.
---

## Config Files
### config.ini
Primary settings for the script, though some of these are redundant / only used by one half of the script.
Expand Down
3 changes: 2 additions & 1 deletion helpers/grabber.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@


def process_name(base, flag):
""""""
"""Updates the name iteration and flag value to cycle through
different results."""
if flag == 1:
temp_list = base.split(" ")
base = ""
Expand Down
5 changes: 0 additions & 5 deletions helpers/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ def reset_main(self):
for child in self.main_tab.winfo_children():
child.destroy()

# used for updating the main screen message
def print_main(self, message):
self.reset_main()
ttk.Label(self.main_tab, text=message).grid(column=0, row=0, sticky=tk.W)

# building the main tab
def build_main(self):
self.reset_main()
Expand Down
7 changes: 0 additions & 7 deletions helpers/helpergui.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,3 @@ def add_button(self, text, cmd):
column=self.column, row=self.row, sticky=tk.W, padx=5, pady=1
)
self.row += 1


def make_window(title, text):
gui_window = AddedGUI(title=title)
gui_window.reset()
gui_window.add_label(text)
return gui_window
7 changes: 7 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,30 @@
# - try / except blocks around data entry code
# things like analytics.py could use more error checking to prevent
# runtime errors to prevent loss of data and time

# - refactoring / reduction in overhead code times
# there is unoptimized solutions and code purely for the case of
# making this project functional by the necessary date
# example of this is exporting after each round of analytics pulling

# - adding in better modularity + options
# there are not many print debug statements, nor direct debugging
# in general; not that this is necessary, but it is nice
# other options could include allowing ISBN-less bookstore listings
# to be recorded, but lots of the options are kinda left as is

# - resolving leftover TODO statements in the various scripts
# not all of these are serious needs, requirements, or fixes
# as much as they are probably spots i have left notes of
# what COULD be done or what hasn't been fully tested

# - adding testcases for selenium functions using hidden github values
# could still login using headless functionality and secret key values

# - adding in cost comparison that works without querying the site too many times

# - improving documentation, comments, and overall code structure

# - cross referencing our own ISBN values from the bookstore ISBN values
# sometimes we own a different book than what the bookstore has per class
# but it is the same book, in which case this could use an automatic cross
Expand Down
Loading