2024-08-29 20:56:48 -04:00
|
|
|
"""
|
|
|
|
|
This file serves as the basecamp for all the calls for the projects.
|
|
|
|
|
The Creation and Deletion functions will likely be put into different files after some time.
|
|
|
|
|
For now, each function needs to be selected below.
|
|
|
|
|
|
|
|
|
|
*********
|
|
|
|
|
Questions:
|
|
|
|
|
- Does creating an attempt also create an enrollment?
|
|
|
|
|
- Does an attempt/enrollment create a course?
|
|
|
|
|
- No to either of these.
|
|
|
|
|
- What is the point of multiple item_ids? They seem as variable as projects.
|
|
|
|
|
- What is a display name in enrollment or attempt resources?
|
|
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
|
- If client delivers just course progress, do we call completed activities in the array 1, 2, and 3.
|
|
|
|
|
- 427 within completed activities shows id, 281 within completed activities shows UUID.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import json
|
2024-09-01 08:16:39 -04:00
|
|
|
from utils import calls, apikeys
|
2024-09-01 16:49:30 -04:00
|
|
|
from datetime import datetime, timedelta
|
2024-08-29 20:56:48 -04:00
|
|
|
|
|
|
|
|
JSONDOC = "./api_docs.json"
|
|
|
|
|
BASEURL = "https://api.northpass.com/v2/migration"
|
|
|
|
|
|
|
|
|
|
# All possible URLs and their functions:
|
|
|
|
|
tupee = [
|
|
|
|
|
# *************************
|
|
|
|
|
# The most fundamental of calls.
|
|
|
|
|
# *************************
|
|
|
|
|
("/v2/migration/projects", "get", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}", "get", "delete", "patch"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/items", "get", "post"),
|
2024-09-03 18:34:32 -04:00
|
|
|
# IMPORTANT: Each item is of a type that must be one of the following along with their follow up endpoints:
|
|
|
|
|
# 'courses' --> course_resources
|
|
|
|
|
# 'sections', --> section_resources
|
|
|
|
|
# 'activities', --> activity_recourds
|
|
|
|
|
# 'people', --> person_resources
|
|
|
|
|
# 'enrollments', --> enrollment_resources
|
|
|
|
|
# 'course_attempts', --> course_attempt_resources
|
|
|
|
|
# 'quiz_attempts', --> quiz_attempt_resources
|
|
|
|
|
# 'certificates',
|
|
|
|
|
# 'learning_path_attempts --> learning_path_attempt_resources
|
2024-08-29 20:56:48 -04:00
|
|
|
("/v2/migration/projects/{project_id}/items/{item_id}", "get", "delete"),
|
|
|
|
|
# *************************
|
|
|
|
|
# Get Resources (Done after you've added them from below)
|
|
|
|
|
# *************************
|
|
|
|
|
("/v2/migration/projects/{project_id}/items/{item_id}/resources", "get"),
|
|
|
|
|
# *************************
|
|
|
|
|
# Post calls for creating new resources.
|
|
|
|
|
# *************************
|
|
|
|
|
("/v2/migration/projects/{project_id}/items/{item_id}/section_resources", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/items/{item_id}/person_resources", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/items/{item_id}/process_resources", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/items/{item_id}/course_resources", "post"),
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/items/{item_id}/quiz_attempt_resources",
|
|
|
|
|
"post",
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/items/{item_id}/activity_resources",
|
|
|
|
|
"post",
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/items/{item_id}/course_attempt_resources",
|
|
|
|
|
"post",
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/items/{item_id}/enrollment_resources",
|
|
|
|
|
"post",
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/items/{item_id}/learning_path_attempt_resources",
|
|
|
|
|
"post",
|
|
|
|
|
),
|
|
|
|
|
# *************************
|
|
|
|
|
# This is just for setting up the Skilljar Config. Not needed yeet.
|
|
|
|
|
# *************************
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/skilljar_configuration",
|
|
|
|
|
"get",
|
|
|
|
|
"post",
|
|
|
|
|
"delete",
|
|
|
|
|
"patch",
|
|
|
|
|
),
|
|
|
|
|
# *************************
|
|
|
|
|
# Extract is just for getting things out of Skilljar
|
|
|
|
|
# *************************
|
|
|
|
|
("/v2/migration/projects/{project_id}/extraction_processes", "get"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/extract_course_attempts", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/extract_courses", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/extract_enrollments", "post"),
|
|
|
|
|
("/v2/migration/projects/{project_id}/extract_people", "post"),
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/extraction_processes/{extraction_process_id}/processing_logs",
|
|
|
|
|
"get",
|
|
|
|
|
),
|
|
|
|
|
# *************************
|
|
|
|
|
# Migrate is putting things into CE.
|
|
|
|
|
# *************************
|
|
|
|
|
("/v2/migration/projects/{project_id}/start_migration", "post"),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def read_json_docs():
|
|
|
|
|
file = open(JSONDOC)
|
|
|
|
|
data = json.load(file)
|
|
|
|
|
for items, vals in data["paths"].items():
|
|
|
|
|
print(items)
|
|
|
|
|
for cmds in vals:
|
|
|
|
|
print(cmds)
|
|
|
|
|
file.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_project():
|
|
|
|
|
"""
|
|
|
|
|
Function to create a project with just a name. While ID is in the example payload, it isn't needed.
|
|
|
|
|
Will generate a project ID for you in the return that you can use to transfer everything.
|
|
|
|
|
Note that it will not give you an error if a project already exists with that name!
|
|
|
|
|
"""
|
|
|
|
|
project_name = ""
|
|
|
|
|
payload = {
|
2024-09-05 15:04:49 -04:00
|
|
|
"data": [
|
2024-09-02 20:42:31 -04:00
|
|
|
{
|
2024-09-05 15:04:49 -04:00
|
|
|
"type": "migration_projects",
|
|
|
|
|
"attributes": {"name": project_name},
|
2024-09-02 20:42:31 -04:00
|
|
|
}
|
|
|
|
|
]
|
2024-08-29 20:56:48 -04:00
|
|
|
}
|
|
|
|
|
url = f"{BASEURL}/projects"
|
2024-09-02 20:42:31 -04:00
|
|
|
calls.post(url, payload)
|
2024-08-29 20:56:48 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_all_projects():
|
|
|
|
|
"""
|
|
|
|
|
Returns all projects.
|
|
|
|
|
"""
|
2024-09-05 15:04:49 -04:00
|
|
|
count = 0
|
2024-08-31 08:26:18 -04:00
|
|
|
project_ids = []
|
2024-09-05 15:04:49 -04:00
|
|
|
while True:
|
|
|
|
|
count += 1
|
|
|
|
|
url = f"{BASEURL}/projects?page={count}"
|
|
|
|
|
ret = calls.get(url)
|
|
|
|
|
nextlink = ret["links"]
|
2024-08-29 20:56:48 -04:00
|
|
|
|
2024-09-05 15:04:49 -04:00
|
|
|
if ret["data"] != []:
|
|
|
|
|
for items in ret["data"]:
|
|
|
|
|
project_ids.append(items["id"])
|
|
|
|
|
print(f"{ items['attributes']['name'] } -- { items['id'] }")
|
|
|
|
|
|
|
|
|
|
if "next" not in nextlink:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
print("Looks like there are no projects created!")
|
2024-08-29 20:56:48 -04:00
|
|
|
|
2024-08-31 08:26:18 -04:00
|
|
|
return project_ids
|
|
|
|
|
|
2024-09-01 16:49:30 -04:00
|
|
|
|
2024-08-31 08:26:18 -04:00
|
|
|
def delete_all_projects():
|
|
|
|
|
"""
|
|
|
|
|
Deletes all projects after returning the uuids of the projects currently available.
|
|
|
|
|
"""
|
|
|
|
|
project_ids = get_all_projects()
|
2024-09-02 20:42:31 -04:00
|
|
|
print("Within delete function")
|
2024-08-31 08:26:18 -04:00
|
|
|
for proj in project_ids:
|
2024-09-02 20:42:31 -04:00
|
|
|
print(proj)
|
2024-08-31 08:26:18 -04:00
|
|
|
url = f"{BASEURL}/projects/{proj}"
|
2024-09-02 20:42:31 -04:00
|
|
|
resp = calls.delete(url)
|
|
|
|
|
print(resp)
|
2024-08-29 20:56:48 -04:00
|
|
|
|
2024-09-01 16:49:30 -04:00
|
|
|
|
2024-08-29 20:56:48 -04:00
|
|
|
def get_specific_project():
|
|
|
|
|
"""
|
|
|
|
|
Returns results from a specific project.
|
|
|
|
|
"""
|
2024-09-04 19:03:18 -04:00
|
|
|
proj_id = "c8341414-58da-4291-8507-216da3fbf045"
|
2024-08-29 20:56:48 -04:00
|
|
|
url = f"{BASEURL}/projects/{proj_id}"
|
2024-09-04 19:03:18 -04:00
|
|
|
ret = calls.get(url)
|
|
|
|
|
print(ret)
|
2024-08-29 20:56:48 -04:00
|
|
|
|
2024-09-05 15:04:49 -04:00
|
|
|
|
2024-09-03 18:34:32 -04:00
|
|
|
def create_course():
|
|
|
|
|
project_id = "6c7a21c2-de35-4b9d-9b80-a235401783af"
|
|
|
|
|
item_id = "80b95e38-78d1-44b9-8d9f-be96d9c7bf6e"
|
|
|
|
|
learner_uuid = "101d891d-f145-4cb2-8f7f-f0d8a90a743e"
|
|
|
|
|
course_uuid = "0d41bb57-bc65-4e05-adfd-58436ed0bd50"
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
|
course_url = f"{BASEURL}/projects/{project_id}/items/{item_id}/course_resources"
|
|
|
|
|
course_payload = {
|
|
|
|
|
"data": [
|
|
|
|
|
{
|
|
|
|
|
"attributes": {
|
|
|
|
|
"type": "course",
|
|
|
|
|
"uuid": "",
|
|
|
|
|
"display_name": "",
|
|
|
|
|
"name": "",
|
|
|
|
|
"short_description": "",
|
|
|
|
|
"full_description": "",
|
|
|
|
|
"navigation_mode": "",
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-29 20:56:48 -04:00
|
|
|
|
2024-09-01 16:49:30 -04:00
|
|
|
def create_enrollment():
|
2024-09-02 20:42:31 -04:00
|
|
|
# important!! Received this error:
|
|
|
|
|
# {"errors":[{"data":{"0":["size cannot be less than 1"]}},{"resource_type":["resource type and item type must be same"]}]}
|
|
|
|
|
|
2024-09-01 16:49:30 -04:00
|
|
|
project_id = "6c7a21c2-de35-4b9d-9b80-a235401783af"
|
|
|
|
|
item_id = "80b95e38-78d1-44b9-8d9f-be96d9c7bf6e"
|
|
|
|
|
learner_uuid = "101d891d-f145-4cb2-8f7f-f0d8a90a743e"
|
|
|
|
|
course_uuid = "0d41bb57-bc65-4e05-adfd-58436ed0bd50"
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
|
print("Creating Enrollment")
|
|
|
|
|
enroll_payload = {
|
2024-09-02 20:42:31 -04:00
|
|
|
"data": [
|
|
|
|
|
{
|
2024-09-05 15:04:49 -04:00
|
|
|
"attributes": {
|
|
|
|
|
"uuid": "1234567890",
|
|
|
|
|
"display_name": "Enrollment Resource Test",
|
|
|
|
|
"type": "course",
|
|
|
|
|
"data": {
|
|
|
|
|
"enrolled_at": formatted_now,
|
|
|
|
|
"course_id": course_uuid,
|
|
|
|
|
"person_id": learner_uuid,
|
|
|
|
|
},
|
2024-09-02 20:42:31 -04:00
|
|
|
}
|
2024-09-01 16:49:30 -04:00
|
|
|
}
|
2024-09-02 20:42:31 -04:00
|
|
|
]
|
2024-09-01 16:49:30 -04:00
|
|
|
}
|
|
|
|
|
enroll_url = calls.post(
|
|
|
|
|
f"{BASEURL}/projects/{project_id}/items/{item_id}/enrollment_resources",
|
|
|
|
|
enroll_payload,
|
|
|
|
|
)
|
2024-09-02 20:42:31 -04:00
|
|
|
print(f"{enroll_url.status_code} response is")
|
|
|
|
|
if enroll_url.status_code == 404 or enroll_url.status_code == 400:
|
|
|
|
|
print(f"A {enroll_url.status_code} error occurred.")
|
|
|
|
|
else:
|
2024-09-01 16:49:30 -04:00
|
|
|
print("Cool, enrollment resource has been created. Let's create an attempt.")
|
|
|
|
|
create_attempt(project_id, item_id, learner_uuid, course_uuid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_attempt():
|
|
|
|
|
course_uuid = "f1b92092-60bd-4d52-922a-e462f132b69c"
|
|
|
|
|
project_id = "6c7a21c2-de35-4b9d-9b80-a235401783af"
|
|
|
|
|
item_id = "80b95e38-78d1-44b9-8d9f-be96d9c7bf6e"
|
|
|
|
|
learner_uuid = "101d891d-f145-4cb2-8f7f-f0d8a90a743e"
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
|
start_time = datetime.now() - timedelta(hours=2)
|
|
|
|
|
print(f"{formatted_now} ---- {start_time}")
|
|
|
|
|
new_attempt_payload = {
|
|
|
|
|
"data": {
|
|
|
|
|
"attributes": {
|
|
|
|
|
"uuid": course_uuid,
|
|
|
|
|
"display_name": f"norm@rsmsn.co's Attempt for course {course_uuid}",
|
|
|
|
|
"learner_id": learner_uuid,
|
|
|
|
|
"course_id": course_uuid,
|
|
|
|
|
"progress": "100",
|
|
|
|
|
"started_at": "2024-09-01 14:35:55",
|
|
|
|
|
"completed_at": formatted_now,
|
|
|
|
|
"completed_activities": [
|
|
|
|
|
{"uuid": "1111", "completed_at": formatted_now}
|
2024-09-05 15:04:49 -04:00
|
|
|
],
|
2024-09-01 16:49:30 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
print(new_attempt_payload)
|
|
|
|
|
attempt_call = calls.post(
|
|
|
|
|
f"{BASEURL}/projects/{project_id}/items/{item_id}/course_attempt_resources",
|
|
|
|
|
new_attempt_payload,
|
|
|
|
|
)
|
|
|
|
|
print(attempt_call)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
If the learner is enrolled, we can go straight to creating an attempt.
|
|
|
|
|
(
|
|
|
|
|
"/v2/migration/projects/{project_id}/items/{item_id}/course_attempt_resources",
|
|
|
|
|
"post",
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
|
2024-09-05 15:04:49 -04:00
|
|
|
|
2024-09-02 20:42:31 -04:00
|
|
|
def get_item():
|
2024-09-04 19:03:18 -04:00
|
|
|
project_id = "c8341414-58da-4291-8507-216da3fbf045"
|
|
|
|
|
item_id = "4ce43bf5-0c73-427b-ad96-17b5aa8f16b2"
|
2024-09-02 20:42:31 -04:00
|
|
|
print("Checking item")
|
|
|
|
|
get_item_url = f"{BASEURL}/projects/{project_id}/items/{item_id}"
|
|
|
|
|
get_item = calls.get(get_item_url)
|
|
|
|
|
print(get_item)
|
|
|
|
|
|
|
|
|
|
|
2024-09-01 16:49:30 -04:00
|
|
|
def check_resources():
|
2024-09-02 20:42:31 -04:00
|
|
|
PROJ_ID = "6c7a21c2-de35-4b9d-9b80-a235401783af"
|
|
|
|
|
ITEM_ID = "80b95e38-78d1-44b9-8d9f-be96d9c7bf6e"
|
2024-09-01 16:49:30 -04:00
|
|
|
print("Checking resources")
|
2024-09-05 15:04:49 -04:00
|
|
|
get_resources_url = f"{BASEURL}/projects/{PROJ_ID}/items/{ITEM_ID}/resources"
|
2024-09-02 20:42:31 -04:00
|
|
|
get_resources = calls.get(get_resources_url)
|
|
|
|
|
print(get_resources)
|
|
|
|
|
# if get_resources["data"] == []:
|
|
|
|
|
# print("Something went wrong. No resources were created.")
|
|
|
|
|
# else:
|
|
|
|
|
# print("We're in! Here's the data:")
|
|
|
|
|
# print(get_resources)
|
2024-09-01 16:49:30 -04:00
|
|
|
|
|
|
|
|
|
2024-08-29 20:56:48 -04:00
|
|
|
if __name__ == "__main__":
|
2024-12-17 17:02:46 -05:00
|
|
|
# delete_all_projects()
|
2024-08-29 20:56:48 -04:00
|
|
|
# read_json_docs()
|
|
|
|
|
# create_project()
|
2024-12-17 17:02:46 -05:00
|
|
|
get_all_projects()
|
2024-09-05 15:04:49 -04:00
|
|
|
# get_specific_project()
|
2024-09-02 20:42:31 -04:00
|
|
|
# create_enrollment()
|
|
|
|
|
# check_resources()
|
2024-09-05 15:04:49 -04:00
|
|
|
# get_item()
|
2024-09-01 16:49:30 -04:00
|
|
|
# create_attempt()
|