How to get Planner Task assignee using Microsoft Graph in Powershell?

47 Views Asked by At

I have a script I have been building to copy tasks from one Plan to another. Eventually the purpose of the script will be to copy over old Tasks to a new Plan and delete them in the original Plan but for now I am just working on the copying of tasks.

I have managed to copy task titles, due dates, and percentage complete but have not managed to get other things such as assignee(s), notes, attachments and buckets. I have some output in console when running the task that says for example for task:

"Task Test Task X has assignees:"

"Assignee information not found or incomplete for Test Task X."

"Task Test Task X has no attachments."

"Task Test Task X does not have a bucket."

"Task moved: Test Task X"

# PowerShell script to copy planner tasks from one plan to another
# You will need to connect to Microsoft Graph

# Define your variables
$tenant = "" # Your tenant ID
$clientid = "" # Your registered application client ID
$thumbprint = "" # Thumbprint of your registered application certificate
$sourcePlanId = "" # ID of the source plan from which tasks will be copied
$destinationPlanId = "" # ID of the destination plan where tasks will be copied to

# Connect to Microsoft Graph 
Connect-MgGraph -ClientId $clientid -TenantId $tenant -CertificateThumbprint $thumbprint

# Function to retrieve user details by ID
function Get-MgUserById {
    param (
        [string]$UserId
    )

    if (-not [string]::IsNullOrWhiteSpace($UserId)) {
        return Get-MgUser -UserId $UserId
    }
    else {
        Write-Warning "User ID is empty or null."
        return $null
    }
}

# Get top 3 tasks from the source plan
$sourceTasks = Get-MgPlannerPlanTask -PlannerPlanId $sourcePlanId -Top 3

# Initialize counter for moved tasks
$movedTasksCount = 0

# Iterate through each task in the source plan
foreach ($task in $sourceTasks) {
    # Initialize array to store assignees
    $assignees = @()
    
    # Check if task has assignees
    if ($task.Assignments) {
        Write-Host "Task $($task.Title) has assignees:"
        # Retrieve user details for each assignee and add them to the new task JSON
        foreach ($assignment in $task.Assignments) {
            $userId = $assignment.assignedUser.id
            if (-not [string]::IsNullOrEmpty($userId)) {
                Write-Host "Assignee User ID: $userId"
                Write-Host $assignment | Format-List
                $assignees += @{
                    "assignedDateTime" = $null  # Add assignedDateTime if available
                    "orderHint"        = "string"  # Provide the order hint value
                    "assignedBy"       = @{
                        "user" = @{
                            "id" = $userId
                        }
                    }
                }
            }
            else {
                Write-Host "Assignee information not found or incomplete for $($task.Title)."
            }
        }
    }
    else {
        Write-Host "Task $($task.Title) has no assignees."
    }

    # Get task attachments
    $attachments = @()
    if ($task.Attachments) {
        Write-Host "Task $($task.Title) has attachments:"
        foreach ($attachment in $task.Attachments) {
            Write-Host "Attachment Name: $($attachment.Name)"
            $attachments += @{
                "name" = $attachment.Name
                "type" = $attachment.ContentType
                "url"  = $attachment.Url
            }
        }
    }
    else {
        Write-Host "Task $($task.Title) has no attachments."
    }

    # Get the bucket ID of the task in the destination plan
    $destinationTask = Get-MgPlannerPlanTask -PlannerPlanId $destinationPlanId -Top 1
    $bucketId = $destinationTask.BucketId

    if (-not [string]::IsNullOrWhiteSpace($bucketId)) {
        Write-Host "Task $($task.Title) has a bucket with ID: $bucketId"
    }
    else {
        Write-Host "Task $($task.Title) does not have a bucket."
    }

    # Create a JSON object representing the task to be added to the destination plan
    $newTaskJson = @{
        "planId"          = $destinationPlanId
        "title"           = $task.Title
        "labels"          = $task.Labels  # Retain task labels
        "percentComplete" = $task.PercentComplete
        "priority"        = $task.Priority  # Retain task priority
        "startDateTime"   = $task.StartDateTime
        "dueDateTime"     = $task.DueDateTime
        "notes"           = $task.Details.Description
        "bucketId"        = $bucketId  # Use the fetched bucket ID
        "attachments"     = $attachments  # Retain task attachments
        "assignments"     = $assignees  # Include assignees
        # Add other task details as needed
    }

    # Make a POST request to create the task in the destination plan
    $response = New-MgPlannerTask -Body ($newTaskJson | ConvertTo-Json -Depth 10)

    # Check if task was moved successfully
    if ($response) {
        Write-Host "Task moved: $($task.Title)"
        $movedTasksCount++
        
        # Delete the task from the source plan
        # Commented out for now
        # Remove-MgPlannerTask -PlannerTaskId $task.Id
    }
    else {
        Write-Host "Failed to move task: $($task.Title)"
    }
}

# Display total number of tasks moved
Write-Host "Total tasks moved: $movedTasksCount"

I tried running the script and it copies the task over but no assignees, attachments or related bucket that does exist on the source Task in Planner

I am new to PowerShell and Graph so any insights would be appreciated even if just for solving how to copy over the assignee for a task.

Thank you.

1

There are 1 best solutions below

0
user3408132 On

A coworker helped me figure out that the Assignees are in a double nested dictionary so I definitely had help on this one but posting answer in case it helps anyone else. I don't have it working yet for attachments or notes associated with a Plan Task.

# PowerShell script to copy planner tasks from one plan to another
# You will need to connect to Microsoft Graph

# Define my variables
$tenant = "" # Your tenant ID
$clientid = "" # Your registered application client ID
$thumbprint = "" # Thumbprint of your registered application certificate
$sourcePlanId = "" # ID of the source plan from which tasks will be copied
$destinationPlanId = "" # ID of the destination plan where tasks will be copied to

# Connect to Microsoft Graph 
Connect-MgGraph -ClientId $clientid -TenantId $tenant -CertificateThumbprint $thumbprint

# Get tasks from the source plan
$sourceTasks = Get-MgPlannerPlanTask -PlannerPlanId $sourcePlanId

# Initialize counter for created tasks
$createdTasksCount = 0

# Iterate through each task in the source plan
foreach ($task in $sourceTasks) {
    Write-Host "Processing task: $($task.Title)"

    # Fetch task details including the ETag
    $taskDetails = Get-MgPlannerTask -PlannerTaskId $task.Id
   
    # Extract the ETag value from the task details
    $etag = $taskDetails.'@odata.etag'

    # Get task attachments
    $attachments = @()
    if ($task.Attachments) {
        foreach ($attachment in $task.Attachments) {
            $attachments += @{
                "name" = $attachment.Name
                "type" = $attachment.ContentType
                "url" = $attachment.Url
            }
        }
    }

    # Get the bucket ID of the task in the destination plan
    $destinationTask = Get-MgPlannerPlanTask -PlannerPlanId $destinationPlanId -Top 1
    $bucketId = $destinationTask.BucketId

    # Construct the JSON object representing the task to be added to the destination plan
    $newTaskJson = @{
        "planId"         = $destinationPlanId
        "title"          = $task.Title
        "labels"         = $task.Labels
        "percentComplete"= $task.PercentComplete
        "priority"       = $task.Priority
        "startDateTime"  = $task.StartDateTime
        "dueDateTime"    = $task.DueDateTime
        "notes"          = $task.Details.Description
        "bucketId"       = $bucketId
        "attachments"    = $attachments
    }

    # Check if task has assignees
    if ($taskDetails.Assignments) {
        Write-Host "Assignees found for $($task.Title)"
       
        # Create a list to store assignee IDs for the current task
        $assigneeIds = @()

        # Loop through each assignment in the Assignments property
        foreach ($assignmentKey in $taskDetails.Assignments.PSObject.Properties) {
            foreach ($key in $assignmentKey.Value.Keys) {
                $assigneeIds += $key
            }
        }

        # Add assignments to the JSON object
        $assignments = @{}
        foreach ($assigneeId in $assigneeIds) {
            $assignments["$assigneeId"] = @{
                "@odata.type" = "microsoft.graph.plannerAssignment"
                "orderHint"   = " !"
            }
        }
        $newTaskJson["assignments"] = $assignments
    }

    # Make a POST request to create the task in the destination plan
    $response = New-MgPlannerTask -Body ($newTaskJson | ConvertTo-Json -Depth 10)

    # Check if task was created successfully
    if ($response) {
        Write-Host "Task created: $($task.Title)"
        $createdTasksCount++
    }
    else {
        Write-Host "Failed to create task: $($task.Title)"
    }
}

# Display total number of tasks created
Write-Host "Total tasks created: $createdTasksCount"