scripts/create_naughty_list.py (122 lines of code) (raw):
import argparse
import sys
import os
import time
import requests
import json
import logging
from datetime import datetime
from collections import defaultdict
# Disable SSL warnings
requests.packages.urllib3.disable_warnings()
MAX_RECORDS_PER_PAGE = 100
def setup_argparser() -> argparse.ArgumentParser:
"""Set up the argument parser for the script"""
argparser = argparse.ArgumentParser(description='Create list of overdue projects')
argparser.add_argument('-b', '--baseurl', help='Base URL of the environment to run the script against')
argparser.add_argument('-t', '--timestamp', help='Date to filter records before (yyyy-mm-dd)')
return argparser
def get_token() -> str:
"""Set token from environment variable"""
token = os.environ.get("PLUTO_TOKEN")
if token == None:
print("No token found. Exiting script...")
sys.exit()
return token
def create_urls(base_url):
commission_list_url = f"{base_url}/pluto-core/api/pluto/commission/list"
project_list_url = f"{base_url}/pluto-core/api/project/list"
return commission_list_url, project_list_url
def get_headers(token: str) -> dict:
return {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}",
}
def api_put_request(url, headers, json_body, max_retries=5):
backoff_factor = 2
for retry in range(max_retries):
try:
with requests.put(url, headers=headers, data=json_body, verify=False) as response:
response.raise_for_status()
return response.json()
except (requests.exceptions.HTTPError, requests.exceptions.RequestException) as e:
if retry == max_retries - 1:
raise
wait_time = backoff_factor ** retry
print(f"An error occurred: {e}. Retrying in {wait_time} seconds...")
time.sleep(wait_time)
def get_filtered_commission_records(timestamp, headers, commission_list_url) -> list:
request_body = {
"match": "W_CONTAINS",
"completionDateBefore": timestamp
}
json_body = json.dumps(request_body)
records = []
try:
json_content = api_put_request(commission_list_url, headers, json_body)
total_records = json_content["count"]
total_pages = (total_records + MAX_RECORDS_PER_PAGE - 1) // MAX_RECORDS_PER_PAGE
start_at = 0
for page in range(1, total_pages + 1):
print(f"Loading commission page: {page}")
response = api_put_request(
f"{commission_list_url}?startAt={start_at}&length={MAX_RECORDS_PER_PAGE}",
headers,
json_body,
)
records.extend(response["result"])
start_at += MAX_RECORDS_PER_PAGE
except requests.exceptions.RequestException as e:
print(e)
raise Exception("An error occurred. Exiting script...")
return records
def get_projects_by_user(records, headers, project_list_url) -> dict:
user_projects = defaultdict(list)
user_project_count = defaultdict(int)
for record in records:
commission_id = record['id']
print(f"Getting projects for commission ID: {commission_id}")
try:
json_content = api_put_request(
project_list_url,
headers,
json.dumps({"match": "W_EXACT", "commissionId": commission_id}),
)
for project in json_content["result"]:
if project['status'] == "In Production":
user = project['user']
user_projects[user].append({
'id': project['id'],
'title': project['title'],
'commission_id': commission_id,
'created': project['created']
})
user_project_count[user] += 1
except requests.exceptions.RequestException as e:
print(f"Error getting projects for commission {commission_id}: {e}")
continue
return user_projects, user_project_count
def write_naughty_list(user_projects: dict, user_project_count: dict, timestamp: str):
output_file = f"naughty_list_{timestamp}.txt"
with open(output_file, "w") as f:
f.write(f"Projects In Production from commissions before {timestamp}\n")
f.write("=" * 80 + "\n\n")
for user, projects in sorted(user_projects.items(), key=lambda x: len(x[1]), reverse=True):
f.write(f"\nUser: {user} (Total overdue projects: {user_project_count[user]})\n")
f.write("-" * 40 + "\n")
for project in projects:
f.write(f"Project ID: {project['id']:<6} Commission: {project['commission_id']:<6} Title: {project['title']}\n")
f.write("\n")
def main():
args = setup_argparser().parse_args()
baseurl = args.baseurl or "https://local.prexit"
commission_list_url, project_list_url = create_urls(baseurl)
token = get_token()
headers = get_headers(token)
timestamp = args.timestamp or "2022-01-01"
timestamp = f"{timestamp}T00:00:00.0Z"
print(f"Getting commissions before {timestamp}")
commissions = get_filtered_commission_records(timestamp, headers, commission_list_url)
print(f"Found {len(commissions)} commissions")
user_projects, user_project_count = get_projects_by_user(commissions, headers, project_list_url)
write_naughty_list(user_projects, user_project_count, timestamp)
print(f"\nNaughty list has been written to naughty_list_{timestamp}.txt")
if __name__ == "__main__":
main()