Skip to content

Instantly share code, notes, and snippets.

@solareon
Created March 8, 2023 08:10
Show Gist options
  • Select an option

  • Save solareon/a5247e107601fd58f049d32759dcad45 to your computer and use it in GitHub Desktop.

Select an option

Save solareon/a5247e107601fd58f049d32759dcad45 to your computer and use it in GitHub Desktop.
Unanet automatic timecard entry and creation
from datetime import datetime
from playwright.sync_api import Playwright, sync_playwright
def run(playwright: Playwright) -> None:
# Define the URL of the login page and the target URL
login_url = "https://<yourcompany>.unanet.biz/<yourcompany>/action/login/validate"
target_url = "https://<yourcompany>.unanet.biz/<yourcompany>/action/home"
logout_url = "https://<yourcompany>.unanet.biz/<yourcompany>/action/logout"
# Set the login credentials
username = 'username'
password = 'password'
daily_hours = 8
# Launch the browser and open a new context
browser = playwright.chromium.launch(headless=True)
context = browser.new_context()
# Navigate to the login page and fill in the login form
page = context.new_page()
page.goto(login_url)
page.fill('input[name="username"]', username)
page.fill('input[name="password"]', password)
# Click the login button and wait for the target page to load
page.click('button[type="submit"]')
page.wait_for_url(target_url)
# Find the edit link based on the current date and navigate to the edit page
today = datetime.today()
edit_url = None
links = page.query_selector_all('a[title^="Edit timesheet"]')
for link in links:
title = link.get_attribute('title')
if title:
title_parts = title.split(' ')
start_date = datetime.strptime(title_parts[3], '%m/%d/%Y').date()
end_date = datetime.strptime(title_parts[5], '%m/%d/%Y').date()
if start_date <= today.date() <= end_date:
href = link.get_attribute('href')
edit_url = f"https://<yourcompany>.unanet.biz{href}"
print(f"Edit URL: {edit_url}")
if edit_url:
page.goto(edit_url)
# Wait for the timesheet to load
page.wait_for_selector('tr[id^="r"]')
# Find the first project row and update its name
project_row = page.query_selector('tr[id^="r"]')
# Find the cell for the current day and check if it's empty
day_of_month = today.day
cell_id = f'd_2_{day_of_month}'
day_cell = project_row.query_selector(f'td[id="{cell_id}"]')
day_hours_input = day_cell.query_selector('input[class*=hours]')
day_hours = day_hours_input.get_attribute('value')
if not day_hours:
day_hours_input.fill(daily_hours)
# Save the timesheet
print("Hours for today: " + day_hours_input.get_attribute('value'))
save_button = page.query_selector('button[id="button_save"]')
save_button.click()
print("Timesheet saved successfully")
if day_hours:
print("Hours for today: " + day_hours)
# Wait for the timesheet to save and log out
# page.wait_for_selector('button[name="button_logout"]')
page.goto(logout_url)
browser.close()
print("Logged out successfully")
else:
print("Edit link not found for today's date. Creating a new timesheet...")
# Create a new timesheet
add_timesheet_link = page.query_selector('a[title="Create Timesheet"]')
add_timesheet_link.click()
# Wait for the new timesheet to load
page.wait_for_selector('input[name="date"]')
# Check if the date on the new timesheet matches today's date
date_input = page.query_selector('input[name="date"]')
date_value = date_input.get_attribute('value')
date_value_parts = date_value.split('/')
date_month = int(date_value_parts[0])
date_day = int(date_value_parts[1])
date_year = int(date_value_parts[2])
if date_month != today.month or date_day != today.day or date_year != today.year:
new_date_value = today.strftime('%m/%d/%Y')
date_input.fill(new_date_value)
# Save the new timesheet
save_button = page.query_selector('button[id="button_save"]')
save_button.click()
# Wait for the new timesheet to save
page.wait_for_selector('tr[id^="r"]')
# Find the project row and update its name
project_row = page.query_selector('tr[id^="r"]')
# Find the cell for the current day and fill in the hours
day_of_month = today.day
cell_id = f'd_2_{day_of_month}'
day_cell = project_row.query_selector(f'td[id="{cell_id}"]')
day_hours_input = day_cell.query_selector('input[class*=hours]')
day_hours = day_hours_input.get_attribute('value')
if not day_hours:
day_hours_input.fill(daily_hours)
# Save the timesheet
save_button = page.query_selector('button[id="button_save"]')
save_button.click()
# Wait for the timesheet to save and log out
page.wait_for_selector('button[name="button_logout"]')
page.goto(logout_url)
browser.close()
print("New timesheet created and logged out successfully")
with sync_playwright() as playwright:
run(playwright)
@solareon

solareon commented Mar 8, 2023

Copy link
Copy Markdown
Author

Automatically create and fill in a timecard for companies that use Unanet timekeeping. Leverages playwright due to javascript loading inline elements of the page. Targets the first timecard row and fills in the target hours. Unanet doesn't really see to care if we logout but we do anyway.

Will 100% break if you get a forced password change or change the charge code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment