Skip to content

Commit

Permalink
Add scripts to fetch and save current employee data from TriNet API
Browse files Browse the repository at this point in the history
  • Loading branch information
austinsonger committed Dec 19, 2024
1 parent 8c777ee commit d32b67b
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 0 deletions.
Empty file.
Empty file.
Empty file.
Empty file.
1 change: 1 addition & 0 deletions evidence-artifacts/federal/tenable/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

57 changes: 57 additions & 0 deletions evidence-artifacts/personnel/2024/10/employee_list.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
employeeId,firstName,lastName,businessTitle,employeeType,supervisorId,citizenshipStatus,birthdate,gender,departmentId,departmentName
00001266632,<FirstName>,<LastName>,Principal Engineer,Full Time,,,,,Unknown,Unknown
00001274360,<FirstName>,<LastName>,Senior DevOps Engineer,Full Time,,,,,Unknown,Unknown
00001290372,<FirstName>,<LastName>,VP of Payer Relations,Full Time,,,,,Unknown,Unknown
00001406637,<FirstName>,<LastName>,Staff Software Engineer,Full Time,,,,,Unknown,Unknown
00001409697,<FirstName>,<LastName>,Director of Engineering,Full Time,,,,,Unknown,Unknown
00001756986,<FirstName>,<LastName>,Sr. DevOps Engineer,Full Time,,,,,Unknown,Unknown
00001786385,<FirstName>,<LastName>,COO,Full Time,,,,,Unknown,Unknown
00001855502,<FirstName>,<LastName>,SVP of Finance,Full Time,,,,,Unknown,Unknown
00001868319,<FirstName>,<LastName>,Senior Engineering Manager,Full Time,,,,,Unknown,Unknown
00001922444,<FirstName>,<LastName>,Lead Analytics Engineer,Full Time,,,,,Unknown,Unknown
00001967259,<FirstName>,<LastName>,Medical Director,Part Time,,,,,Unknown,Unknown
00002021386,<FirstName>,<LastName>,VP Clinical Ops & Primary Ca,Full Time,,,,,Unknown,Unknown
00002113606,<FirstName>,<LastName>,Mobile Engineer,Full Time,,,,,Unknown,Unknown
00002274042,<FirstName>,<LastName>,"Vice President, Sales",Full Time,,,,,Unknown,Unknown
00002368310,<FirstName>,<LastName>,Trusted Advisor,Part Time,,,,,Unknown,Unknown
00002410105,<FirstName>,<LastName>,Client Solution Design Dir,Full Time,,,,,Unknown,Unknown
00002423855,<FirstName>,<LastName>,"SVP, Client Success & Ops",Full Time,,,,,Unknown,Unknown
00002428345,<FirstName>,<LastName>,Digital Marketing Director,Full Time,,,,,Unknown,Unknown
00002437531,<FirstName>,<LastName>,Administrative Office Manager,Full Time,,,,,Unknown,Unknown
00002451067,<FirstName>,<LastName>,"Sr. Manager, Data & Analytics",Full Time,,,,,Unknown,Unknown
00002463387,<FirstName>,<LastName>,Director of Member Engagement,Full Time,,,,,Unknown,Unknown
00002484983,<FirstName>,<LastName>,Senior Software Engineer,Full Time,,,,,Unknown,Unknown
00002485256,<FirstName>,<LastName>,VP of Client Success,Full Time,,,,,Unknown,Unknown
00002517570,<FirstName>,<LastName>,Sr Director Finance & Ops,Full Time,,,,,Unknown,Unknown
00002544891,<FirstName>,<LastName>,Sr. Client Success Manager,Full Time,,,,,Unknown,Unknown
00002597973,<FirstName>,<LastName>,Engineering Manager,Full Time,,,,,Unknown,Unknown
00002609142,<FirstName>,<LastName>,Staff Software Engineer,Full Time,,,,,Unknown,Unknown
00010005756,<FirstName>,<LastName>,"Vice President, Sales",Full Time,,,,,Unknown,Unknown
00010102629,<FirstName>,<LastName>,Sr. Client Success Manager,Full Time,,,,,Unknown,Unknown
00010102754,<FirstName>,<LastName>,iOS Engineer,Full Time,,,,,Unknown,Unknown
00010144311,<FirstName>,<LastName>,Senior Software Engineer,Full Time,,,,,Unknown,Unknown
00010166878,<FirstName>,<LastName>,Member Support Supervisor,Full Time,,,,,Unknown,Unknown
00010199835,<FirstName>,<LastName>,Manager of Clinical Licensing,Full Time,,,,,Unknown,Unknown
00010203400,<FirstName>,<LastName>,Data Analyst,Full Time,,,,,Unknown,Unknown
00010219580,<FirstName>,<LastName>,VP of Client Success,Full Time,,,,,Unknown,Unknown
00010285926,<FirstName>,<LastName>,Sr. Client Success Manager,Full Time,,,,,Unknown,Unknown
00010293521,<FirstName>,<LastName>,IT and Security Administrator,Full Time,,,,,Unknown,Unknown
00010426613,<FirstName>,<LastName>,Trusted Advisor,Part Time,,,,,Unknown,Unknown
00010441496,<FirstName>,<LastName>,Trusted Advisor,Part Time,,,,,Unknown,Unknown
00010449856,<FirstName>,<LastName>,"Sr. Dir, Product Mgmt & Innova",Full Time,,,,,Unknown,Unknown
00010485384,<FirstName>,<LastName>,President & CEO,Full Time,,,,,Unknown,Unknown
00010497098,<FirstName>,<LastName>,Sr iOS Engineer,Full Time,,,,,Unknown,Unknown
00010561795,<FirstName>,<LastName>,Health Coach,Full Time,,,,,Unknown,Unknown
00010575688,<FirstName>,<LastName>,"SVP, Mktg and Brand Strategy",Full Time,,,,,Unknown,Unknown
00010575998,<FirstName>,<LastName>,SVP Product Mgmt & Innovation,Full Time,,,,,Unknown,Unknown
00010584088,<FirstName>,<LastName>,Art Director,Full Time,,,,,Unknown,Unknown
00010608788,<FirstName>,<LastName>,Health Coach,Full Time,,,,,Unknown,Unknown
00010610689,<FirstName>,<LastName>,Product Designer,Full Time,,,,,Unknown,Unknown
00010616738,<FirstName>,<LastName>,Cybersecurity Program Manager,Full Time,,,,,Unknown,Unknown
00010640489,<FirstName>,<LastName>,Product Manager,Full Time,,,,,Unknown,Unknown
00010649725,<FirstName>,<LastName>,Product Manager,Full Time,,,,,Unknown,Unknown
00010654997,<FirstName>,<LastName>,Licensing and Credentialing Sp,Full Time,,,,,Unknown,Unknown
00010655099,<FirstName>,<LastName>,Lead Data Engineer,Full Time,,,,,Unknown,Unknown
00010659705,<FirstName>,<LastName>,QA Engineer,Full Time,,,,,Unknown,Unknown
00010670145,<FirstName>,<LastName>,Senior Software Engineer ,Full Time,,,,,Unknown,Unknown
00010770029,<FirstName>,<LastName>,Platform ML Engineer,Full Time,,,,,Unknown,Unknown
59 changes: 59 additions & 0 deletions evidence-artifacts/personnel/2024/10/organization_chart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
digraph EmployeeChart {
// Node definitions with hidden employee IDs and supervisor IDs
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nPrincipal Engineer", employeeId="00001266632", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSenior DevOps Engineer", employeeId="00001274360", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nVP of Payer Relations", employeeId="00001290372", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nStaff Software Engineer", employeeId="00001406637", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nDirector of Engineering", employeeId="00001409697", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr. DevOps Engineer", employeeId="00001756986", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nCOO", employeeId="00001786385", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSVP of Finance", employeeId="00001855502", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSenior Engineering Manager", employeeId="00001868319", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nLead Analytics Engineer", employeeId="00001922444", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nMedical Director", employeeId="00001967259", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nVP Clinical Ops & Primary Ca", employeeId="00002021386", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nMobile Engineer", employeeId="00002113606", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nVice President, Sales", employeeId="00002274042", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nTrusted Advisor", employeeId="00002368310", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nClient Solution Design Dir", employeeId="00002410105", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSVP, Client Success & Ops", employeeId="00002423855", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nDigital Marketing Director", employeeId="00002428345", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nAdministrative Office Manager", employeeId="00002437531", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr. Manager, Data & Analytics", employeeId="00002451067", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nDirector of Member Engagement", employeeId="00002463387", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSenior Software Engineer", employeeId="00002484983", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nVP of Client Success", employeeId="00002485256", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr Director Finance & Ops", employeeId="00002517570", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr. Client Success Manager", employeeId="00002544891", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nEngineering Manager", employeeId="00002597973", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nStaff Software Engineer", employeeId="00002609142", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nVice President, Sales", employeeId="00010005756", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr. Client Success Manager", employeeId="00010102629", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\niOS Engineer", employeeId="00010102754", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSenior Software Engineer", employeeId="00010144311", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nMember Support Supervisor", employeeId="00010166878", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nManager of Clinical Licensing", employeeId="00010199835", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nData Analyst", employeeId="00010203400", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nVP of Client Success", employeeId="00010219580", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr. Client Success Manager", employeeId="00010285926", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nIT and Security Administrator", employeeId="00010293521", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nTrusted Advisor", employeeId="00010426613", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nTrusted Advisor", employeeId="00010441496", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr. Dir, Product Mgmt & Innova", employeeId="00010449856", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nPresident & CEO", employeeId="00010485384", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSr iOS Engineer", employeeId="00010497098", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nHealth Coach", employeeId="00010561795", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSVP, Mktg and Brand Strategy", employeeId="00010575688", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSVP Product Mgmt & Innovation", employeeId="00010575998", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nArt Director", employeeId="00010584088", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nHealth Coach", employeeId="00010608788", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nProduct Designer", employeeId="00010610689", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nCybersecurity Program Manager", employeeId="00010616738", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nProduct Manager", employeeId="00010640489", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nProduct Manager", employeeId="00010649725", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nLicensing and Credentialing Sp", employeeId="00010654997", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nLead Data Engineer", employeeId="00010655099", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nQA Engineer", employeeId="00010659705", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nSenior Software Engineer", employeeId="00010670145", supervisorId=""];
"<First Name> <Last Name>" [label="<First Name> <Last Name>\nPlatform ML Engineer", employeeId="00010770029", supervisorId=""];
}
Empty file.
155 changes: 155 additions & 0 deletions src/populations/personnel/current-employees.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import requests
import os
import csv
import base64
from datetime import datetime


API_KEY = os.getenv('TRINET_API_KEY')
API_SECRET = os.getenv('TRINET_API_SECRET')
COMPANY_ID = "CJ6"
TOKEN_URL = "https://api.trinet.com/oauth/accesstoken?grant_type=client_credentials"
EMPLOYEE_LIST_URL_TEMPLATE = "https://api.trinet.com/v1/company/{companyId}/employees"
BASE_DIR = "evidence-artifacts/personnel" # Base directory for storing the employee list


# Helper function to get access token
def get_access_token(api_key, api_secret):
client_credentials = f"{api_key}:{api_secret}"
encoded_credentials = base64.b64encode(client_credentials.encode('utf-8')).decode('utf-8')
headers = {
'Authorization': f'Basic {encoded_credentials}'
}
response = requests.get(TOKEN_URL, headers=headers)
if response.status_code == 200:
token_data = response.json()
return token_data['access_token']
else:
raise Exception(f"Error getting access token: {response.text}")

# Helper function to fetch employee list
def get_employee_list(access_token, company_id=COMPANY_ID, limit=100, offset=None):
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json',
'grant_type': 'client_credentials'
}
url = EMPLOYEE_LIST_URL_TEMPLATE.format(companyId=company_id)
params = {"limit": limit}
if offset is not None:
params["offset"] = offset
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Error fetching employee list: {response.status_code} - {response.text}")

# Helper function to extract relevant fields from employee data
def extract_employee_data(employee):
# Exclude terminated employees
employment_status = employee.get('employmentInfo', {}).get('employmentStatus', '')
if employment_status == 'T': # Assuming 'T' represents terminated employees
return None

# Extract primary name from the names array
names = employee.get('names', [])
first_name, last_name = "", ""
if names:
primary_name = names[0] # Assuming the first entry is the primary name
first_name = primary_name.get('firstName', '')
last_name = primary_name.get('lastName', '')

# Extract job title and department info
business_title = employee.get('employmentInfo', {}).get('businessTitle', 'Unknown')
employee_type = employee.get('employmentInfo', {}).get('employeeType', 'Unknown')

# Extract department details
department_info = employee.get('departmentSplit', [])
department_id = department_name = "Unknown"
if department_info:
department_id = department_info[0].get('deptId', 'Unknown')
department_name = department_info[0].get('departmentName', 'Unknown')

# Extract other relevant fields
employee_id = employee.get('employeeId', '')
supervisor_id = employee.get('supervisorId', '')
citizenship_status = employee.get('workEligibility', {}).get('citizenshipStatus', '')
birthdate = employee.get('bioInfo', {}).get('birthdate', '')
gender = employee.get('bioInfo', {}).get('gender', '')

return {
'employeeId': employee_id,
'firstName': first_name,
'lastName': last_name,
'businessTitle': business_title, # Adding job title
'employeeType': employee_type, # Adding employee type
'supervisorId': supervisor_id,
'citizenshipStatus': citizenship_status,
'birthdate': birthdate,
'gender': gender,
'departmentId': department_id, # Adding department ID
'departmentName': department_name # Adding department name
}

# Function to save employee data to a CSV file
def save_employee_list_to_csv(employee_data):
# Get current year and month
current_year = datetime.now().year
current_month = datetime.now().month

# Create directory if it doesn't exist
output_dir = os.path.join(BASE_DIR, str(current_year), str(current_month))
os.makedirs(output_dir, exist_ok=True)

# Path for the CSV file
output_csv_path = os.path.join(output_dir, 'employee_list.csv')

# Extract and flatten relevant employee data, excluding terminated employees
flattened_data = [extract_employee_data(employee) for employee in employee_data if extract_employee_data(employee)]

# Define the CSV columns
fieldnames = ['employeeId', 'firstName', 'lastName', 'businessTitle', 'employeeType', 'supervisorId',
'citizenshipStatus', 'birthdate', 'gender', 'departmentId', 'departmentName']

# Write to the CSV file
with open(output_csv_path, 'w', newline='') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(flattened_data)

print(f"Employee list saved to {output_csv_path}")

# Main function to fetch data and generate CSV
def main():
try:
# Use environment variables or input API key and secret directly
api_key = API_KEY or input("Enter your API Key: ")
api_secret = API_SECRET or input("Enter your API Secret: ")

token = get_access_token(api_key, api_secret)

# Paginate through the employee list
offset = None # Start with no offset
has_more = True
all_employees = []

while has_more:
response_data = get_employee_list(token, company_id=COMPANY_ID, offset=offset)
employee_data = response_data.get('data', {}).get('employeeData', [])
all_employees.extend(employee_data)

# Check if there are more employees to fetch
has_more = response_data.get('data', {}).get('hasMore', False)

# Set offset for the next request only if there are more employees
if has_more:
offset = offset + 100 if offset is not None else 101 # Start at 101 for second request

# Once we have all the employees, generate the CSV
save_employee_list_to_csv(all_employees)

except Exception as e:
print(e)

if __name__ == "__main__":
main()

0 comments on commit d32b67b

Please sign in to comment.