Automate your fieldglass using Selenium

Automate your fieldglass using Selenium

At my workplace, I'm required to perform this task on a weekly basis. In order to break away from the monotony of this repetitive task and gain new knowledge, I decided to experiment with using Selenium to automate the process of filling out my Fieldglass. Let's dive into the details. To begin, our first task involves handling the configuration of the logging and browser settings, which are managed using Selenium. Additionally, during this step, we load the necessary environment variables, whi

At my workplace, I'm required to perform this task on a weekly basis. In order to break away from the monotony of this repetitive task and gain new knowledge, I decided to experiment with using Selenium to automate the process of filling out my Fieldglass. Let's dive into the details.


To begin, our first task involves handling the configuration of the logging and browser settings, which are managed using Selenium. Additionally, during this step, we load the necessary environment variables, which include the following:

URL = "https://www.fieldglass.net/?next=%2Fworker_desktop.do"
EMAIL = "your company email"
PASSWORD = "your company password"
HOURS_PER_DAY = 8 # hours to be filled per day
HOURS_PER_WEEK = 40 # hours to be filled per week
COMMENT = "" # if you had any comments for this week
COUNTRY = "CO" # your country code

EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_ADDRESS = "your personal email"
EMAIL_PASSWORD = "your personal email password"
RECIPIENT_EMAIL_ADDRESS = "the recipient email address for the report"

Now we need to open the browser and login into the system using our credentials:

def login(browser, email, password):
    """
    Logs into the website with the given credentials.

    Args:
        browser (webdriver): The webdriver instance.
        email (str): The user's email address.
        password (str): The user's password.

    Returns:
        bool: True if login was successful, False otherwise.
    """
    browser.get(os.getenv("URL"))
    email_input = wait.until(
        EC.presence_of_element_located((By.ID, "usernameId_new")))
    email_input.send_keys(email)
    password_input = wait.until(
        EC.presence_of_element_located((By.ID, "passwordId_new")))
    password_input.send_keys(password)
    login_button = browser.find_element(By.CLASS_NAME, "formLoginButton_new")
    login_button.click()

    try:
        todos_link = browser.find_element(By.CSS_SELECTOR, ".todosItemList a")
        todos_link.click()
    except NoSuchElementException as e:
        logging.warning(f"Could not find todos link: {e}")
        return False

    return True

Subsequently, our next objective is to locate the timesheet table and populate the hours in each corresponding input field. Furthermore, this function takes into account holidays specific to your country, leaving the input fields blank if any holidays fall within the current week.

def fill_time_sheet(browser, hours_per_day, comment, country):
    """
    Fills out the time sheet with the given hours and comment.

    Args:
        browser (webdriver): The webdriver instance.
        hours_per_day (str): The number of hours worked per day.
        comment (str): The comment to add to the time sheet.
    """
    time_sheet_input = wait.until(
        EC.presence_of_element_located((By.ID, "time_sheet_week_1")))

    # Fill out hours worked and comments
    row_inputs = time_sheet_input.find_elements(By.CSS_SELECTOR, ".hoursWorked input")
    comment_input = browser.find_elements(By.CSS_SELECTOR, "textarea[name*='comments']")[0]
    day_of_week = date.today() - timedelta(days=date.today().weekday()) # Monday of current week
    country_holidays = holidays.country_holidays(country, years=date.today().year)
    holidays_count = 0

    for entry in row_inputs:
        if "nonWorkingDay" not in entry.get_attribute("class") and "hour" in entry.get_attribute("class"):
            if day_of_week not in country_holidays:
                entry.send_keys(hours_per_day)
            else:
                holidays_count += 1
                logging.info(f"{day_of_week} is a holiday.")
            day_of_week += timedelta(days=1)
    
    comment_input.send_keys(comment)
    return holidays_count

Lastly, we proceed with submitting the timesheet and verifying its successful upload. Upon completion, an email notification is sent to inform you of the result.

def submit_time_sheet(browser, total_hours):
    """
    Submits the time sheet and confirms submission.
        total_hours is the number of hours to submit per week
    Returns:
        bool: True if submission was successful, False otherwise.
    """
    total_hours_input = int(browser.find_element(By.CSS_SELECTOR, ".rowTotal").get_attribute("innerHTML").split("h")[0])
    if total_hours == total_hours_input:
        submit = wait.until(EC.presence_of_element_located((By.ID, "fgTSSubmit")))
        submit.click()
        confirm_button = wait.until(EC.presence_of_element_located((By.ID, "update")))
        # confirm_button.click() # Uncomment to submit time sheet
    else:
        logging.warning(
            f"The number of hours worked this week is %d", total_hours)

    # Check if submission successful
    try:
        success_message = browser.find_element(By.CLASS_NAME, "successMessage")
        if "submitted successfully" in success_message.text.lower():
            return True
    except NoSuchElementException as e:
        logging.warning(f"Could not find success message: {e}")
    return False

def notify_result(result: bool) -> None:
    """
    Sends an email notification with the result of the operation.
    """
    # Send email notification
    message = f"Subject: {'Successful' if result else 'Failed'} filled Arroyo time sheet"
    with smtplib.SMTP(os.getenv("EMAIL_HOST"), os.getenv("EMAIL_PORT")) as server:
        server.starttls()
        server.login(os.getenv("EMAIL_ADDRESS"), os.getenv("EMAIL_PASSWORD"))
        server.sendmail(os.getenv("EMAIL_ADDRESS"), os.getenv(
            "RECIPIENT_EMAIL_ADDRESS"), message)


Furthermore, for complete automation of this process, it is recommended to utilize a tool such as crontab to schedule the execution of this script every Friday at a specific time.

On Mac:

  1. Open Terminal.
  2. Navigate to the directory where your Python script is located using the cd command.
  3. Use the crontab -e command to edit your cron jobs.
  4. If prompted, choose an editor to open the crontab file.
  5. In the editor, add the following line to execute the script every day at a specific time:30 8 * * 5 python3 script.py Replace script.py with the actual name of your Python script.
  6. Save the changes and exit the editor.
  7. The script will now be scheduled to run every day at the specified time.

On Windows:

  1. Open the Task Scheduler. You can do this by searching for "Task Scheduler" in the Start menu.
  2. Click on "Create Basic Task" or "Create Task" in the Actions pane.
  3. Provide a name and optional description for the task, then click "Next".
  4. Choose the trigger "Weekly" and select "Friday". Set the start time to 8:30 AM. Click "Next".
  5. Select the action "Start a program" and browse to select the Python executable (e.g., python.exe or pythonw.exe).
  6. In the "Add arguments" field, enter the path to your Python script (e.g., C:\path\to\script.py).
  7. Optionally, specify the starting directory of the script in the "Start in" field.
  8. Click "Next" and review the task's settings. Click "Finish" to create the task.
  9. The script will now be scheduled to run every Friday at 8:30 AM

Please note that the exact steps may vary slightly depending on the specific version of macOS or Windows you are using, but these general instructions should help you schedule the execution of your Python script.

Check the repo here: https://github.com/JoseMiguelCh/SeleniumTest/blob/master/automated_fieldglass.py and don't forget to add your own .env file.

Share :
Tag :
Comments

Leave a Comment