New Driver Training

Assign training courses to onboard new drivers

Overview

This script automates the process of assigning training courses to new drivers to your organization. It interacts with Samsara APIs to fetch drivers based on tags, check existing assignments, and create new assignments for drivers based on their new hire status.

Note: This guide assumes you are already familiar with the basics of the Samsara Training Product and the overall GET Training Assignments, POST Training Assignments and GET Training Courses APIs. If you are new to Training, see the Driver Training Guide first.

Example Use Cases

  • An HR manager wants to assign the "New Hire Training" course to new drivers in the organization.
  • An HR manager wants to assign an onboarding course to new drivers that are added to Samsara and added to tag "New Driver".

Trigger Conditions

Trigger Conditions

  • A new driver is added
  • Specify driver tags for assignment

Action

  • Assign relevant onboarding training course with defined due dates

Execution Flow

  1. Generates a timestamp for filtering new drivers based on NEW_DRIVER_LOOKBACK_DAYS.
  2. Calls get_drivers to retrieve new drivers.
  3. Extracts driver IDs from the response.
  4. Checks if any of the newly created drivers has already been assigned the course and omits those drivers.
  5. Generates a due date timestamp for training completion.
  6. Calls assign_training to assign the training course to the drivers.

Script

Note: To run certain automations, you will need to set up a development environment. Ensure your environment has access to Samsara API endpoints and is properly configured for integration. These code snippets can be copied but will need to be customized to match your organization's specific use case, including correct API tokens and organizational details.

from datetime import datetime, timedelta
import requests

# API URLs and token
LIST_DRIVERS_API = 'https://api.samsara.com/fleet/drivers'
ASSIGN_TRAINING_API = 'https://api.samsara.com/training-assignments'
STREAM_TRAINING_ASSIGNMENT_API = 'https://api.samsara.com/training-assignments/stream'
API_TOKEN = 'Insert your API token'
HEADERS = {'Accept': 'application/json', 'Authorization': f'Bearer {API_TOKEN}'}

# Constants
COURSE_ID = 'Insert course ID'  # Course ID for 'Values' course
TARGET_DRIVER_TAG_IDS = ['Insert the driver tag ID']  # Tag ID for the target driver tags
NEW_DRIVERS_LOOKBACK_DAYS = -1
COURSE_COMPLETION_DUE_DAYS = 14
TRAINING_LOOKBACK_DAYS = -1

def get_drivers(tag_ids, created_after_timestamp):
    '''Retrieve a list of drivers based on specific tags and a creation timestamp.

    Args:
        tag_ids (list of str): A list of tag IDs used to filter drivers.
        created_after_timestamp (str): The timestamp (in RFC3339 format) to filter
        drivers created after this time.

    Returns:
        list: A list of driver objects that match the given tags and creation timestamp.
    '''
    drivers = []
    after = ''
    has_next_page = True
    params = {'createdAfterTime': created_after_timestamp, 'tagIds': tag_ids}

    while has_next_page:
        params['after'] = after
        response = requests.get(LIST_DRIVERS_API, headers=HEADERS, params=params)
        data = response.json()
        drivers.extend(data.get('data', []))

        if data.get('pagination', {}).get('hasNextPage'):
            has_next_page = True
            after = data['pagination']['endCursor']
        else:
            has_next_page = False

    return drivers

def get_training_assignment_details(assignment_interval_timestamp, course_id):
    '''
    Retrieves a stream of filtered training assignments within a specified time range.

    Args:
        assignment_interval_timestamp (str): Start timestamp in RFC3339 format to
        filter the training assignments.
        course_id (str): The ID of the training course to filter the assignments.

    Returns:
        list: A list of training assignments that match the provided filters.
    '''
    training_assignments = []
    after = ''
    params = {'startTime': assignment_interval_timestamp, 'courseIds': [course_id]}
    has_next_page = True
    while has_next_page:
        params['after'] = after
        response = requests.get(
            STREAM_TRAINING_ASSIGNMENT_API, headers=HEADERS, params=params
        )
        data = response.json()
        training_assignments.extend(data['data'])
        if data.get('pagination', {}).get('hasNextPage'):
            has_next_page = True
            after = data['pagination']['endCursor']
        else:
            has_next_page = False

    return training_assignments

def assign_training(driver_id_list, course_id, due_date):
    '''Assign a training course to a list of drivers.

    Args:
        driver_id_list (list of str): A list of driver IDs to assign the training course to.
        course_id (str): The ID of the course to be assigned.
        due_date (str): The due date for the training in RFC3339 format.

    This function makes an API call to assign the training course to the specified drivers.
    '''
    params = {
        'learnerIds': ','.join([f'driver-{id}' for id in driver_id_list]),
        'courseId': course_id,
        'dueAtTime': due_date,
    }
    requests.post(ASSIGN_TRAINING_API, headers=HEADERS, params=params)

def generate_rfc3339_timestamp(delta_days):
    '''
    Generates an RFC3339 timestamp by adding or subtracting days from the current date.

    Args:
        delta_days (int): Number of days to add (positive) or subtract (negative) from the
        current date.

    Returns:
        str: The RFC3339 formatted timestamp.
    '''
    target_date = (datetime.now() + timedelta(days=delta_days)).replace(
        hour=0, minute=0, second=0, microsecond=0
    )
    return target_date.strftime('%Y-%m-%dT%H:%M:%SZ')

def main():
    # Generate timestamp for lookback period of new drivers
    driver_lookback_days_rfc3339 = generate_rfc3339_timestamp(NEW_DRIVERS_LOOKBACK_DAYS)

    # Get a list of newly created drivers within the lookback period
    newly_created_drivers = get_drivers(
        TARGET_DRIVER_TAG_IDS, driver_lookback_days_rfc3339
    )

    # Extract driver IDs of newly created drivers
    driver_id_list = [driver['id'] for driver in newly_created_drivers]

    drivers_assigned_training = []
    # Generate timestamp for training assignment lookback period
    training_lookback_days_rfc3339 = generate_rfc3339_timestamp(TRAINING_LOOKBACK_DAYS)

    # Get the assignment details for training
    assignment_details = get_training_assignment_details(
        training_lookback_days_rfc3339, COURSE_ID
    )

    # Loop through the assignment details to get drivers who have been assigned training
    for assignment in assignment_details:
        if assignment['learner']['type'] == 'driver':
            drivers_assigned_training.append(assignment['learner']['id'])

    # Find drivers who haven't been assigned the training
    drivers_requiring_training = [
        driver for driver in driver_id_list if driver not in drivers_assigned_training
    ]

    drivers_requiring_training = ','.join(
        [f'driver-{id}' for id in drivers_requiring_training]
    )

    # Generate RFC3339 timestamp for course completion due date
    course_due_date_rfc3339 = generate_rfc3339_timestamp(COURSE_COMPLETION_DUE_DAYS)

    # Assign the course to newly created drivers
    assign_training(driver_id_list, COURSE_ID, course_due_date_rfc3339)

if __name__ == '__main__':
    main()

Appendix

Constant Definitions

ConstantTypeDescription
COURSE_IDStringID of the training course that will be assigned.
TARGET_DRIVER_TAG_IDSList of StringsList of tag IDs used to filter specific drivers.
NEW_DRIVER_LOOKBACK_DAYSIntegerThe timeframe (in days) for fetching new drivers.
COURSE_COMPLETION_DUE_DAYSIntegerNumber of days from today to set as the due date for training assignments.
TRAINING_LOOKBACK_DAYSIntegerNumber of days to look back for training assignments.

Function Definitions

FunctionDescription
get_driversRetrieves a list of drivers created after the specified timestamp and matching the provided tag IDs.
get_training_assignment_detailsThis function retrieves a stream of training assignments filtered by a specified assignment_interval_timestamp and course_id. It handles pagination to fetch all relevant assignment data from the Samsara API. If successful, it returns a list of assignment records.
assign_trainingThis function is responsible for creating training assignments for drivers. It accepts three parameters: course_id, which is the ID of the training course to be assigned, driver_ids, which is a list of driver IDs to receive the training, and due_date, which is the due date for completing the training.
generate_rfc3339_timestampThis function generates a timestamp in milliseconds format by either adding or subtracting a specified number of days (given by delta_days) from the current date. To calculate a date in the past, pass a negative value for delta_days; for a future date, pass a positive value. This allows the function to determine whether the days should be added or subtracted. The timestamp generated in this example is midnight and in the UTC timezone. Please refer to Samsara Timestamp Documentation for more information on this.