moveBookings.ps1

<#
.SYNOPSIS
Moves Bookings between projects.
 
.DESCRIPTION
If a Workpackage does not exist in the target project, it is created. Empty workpackages in source project are not removed.
All filterparamters are optional. They are treated in logical AND.
Project to move tasks between both need to be open.
 
.PARAMETER tcCredential
    Credential for Timecockpit. If not given they will be requested and stored in CredentialManager.
 
.PARAMETER useCredentialsManager
    If Credentialmanager should be used. Defaults to $True.
 
.PARAMETER customerCode
    Code of Customer to move bookings within.
 
.PARAMETER projectCode
    Code of Project the bookings to move are currently in.
 
.PARAMETER targetProjectCode
    Code of Project to move the bookings to. If not given, bookings are moved within same project.
 
.PARAMETER taskCode
    Code of Task the bookings to move are currently in.
 
.PARAMETER targetTaskCode
    Code of Task to move the bookings to. If not given, $taskCode is used. If Task in target project is not found, it gets created.
    Tasks themself are not moved, but a equivalen Task is created in the targetproject.
 
.PARAMETER from
    Filter to move only bookings having a startdate later than from.
 
.PARAMETER to
    Filter to move only bookings having an enddate earlier than to. For end of day, please add 23:59
     
.EXAMPLE
    Moves all bookings from previous year into a archive project
     
    .\moveBookings -customerCode "Recheis" -projectCode "Support" -targetProjectCode "Support 2019" -to "2019-12-31 23:59"
 
.EXAMPLE
    Testrun moving all bookings from project A into B
     
    .\moveBookings -customerCode "Recheis" -sourceProjectCode "A" -targetProjectCode "B" -Verbose -WhatIf
 
.EXAMPLE
    Move bookings later than 2020-06-04 0:00 from task 1003 into task 1002
     
    .\moveBookings.ps1 -customerCode "Recheis" -projectCode "Support" -taskCode "1003" -targetTaskCode "1002" -from 2020-06-04
 
.EXAMPLE
    Move bookings from task 1003 in project "support" into project "support old"
     
    .\moveBookings.ps1 -customerCode "Recheis" -projectCode "Support" -targetProjectCode "Support Old" -taskCode "1003" -from 2020-06-04
 
#>

[CmdletBinding(SupportsShouldProcess=$true)]
param(
    [PSCredential] $tcCredential,
    [Boolean] $useCredentialsManager = $True,
    [Parameter(Mandatory=$true)][string] $customerCode,
    [Parameter(Mandatory=$true)][string] $projectCode,
    [string] $targetProjectCode = $projectCode,
    [string] $taskCode,
    [string] $targetTaskCode = $taskCode,
    [Nullable[DateTime]] $from,
    [Nullable[DateTime]] $to
)

function FetchProject([string]$customerCode, [string]$projectCode)
{
    $project = Get-TCProject -CustomerCode $customerCode -Code $projectCode
    if (-not $project) 
    {
        throw "Project with Code '${projectCode}' not found for Customer with Code '${customerCode}'.";
    }
    if ($project.GetType() -eq [Object[]]) 
    {
        throw "Project with Code '${projectCode}' found more than once for Customer with Code '${customerCode}'. Check double projects in TC.";
    }
    return $project;
}



# check prerequisites
$tcModule = Get-Module -ListAvailable -Name "TimeCockpit";
if (!$tcModule) { throw "Module 'TimeCockpit' needed. Please install executing 'Install-Module -Name TimeCockpit' as Administrator."; }
Write-Output "Using TimeCockpit Module v$($tcModule.Version)."

Connect-TC -Credential $tcCredential -UseCredentialsManager $useCredentialsManager;

# Fetch the Projects for the given Customer
Write-Output "Fetching Project '${projectCode}' in customer '${customerCode}'..."
$sourceProject = FetchProject $customerCode $projectCode
$targetProject = FetchProject $customerCode $targetProjectCode

# Fetch bookings to move
$params = @{ "ProjectUuid" = $sourceProject.APP_ProjectUuid; }
if($taskCode) 
{ 
    $sourceTask = Get-TCTask -ProjectUuid $sourceProject.APP_ProjectUuid -Code $taskCode
    $params.Add("TaskUuid", $sourceTask.APP_TaskUuid); 
}
if($from) { $params.Add("BeginTime", $from); }
if($to) { $params.Add("EndTime", $to); }
$bookings = Get-TCTimesheets @params

foreach($booking in $bookings) 
{
    # if booking is on task, get task with same code in targetproject
    if($booking.APP_TaskUuid)
    {
        $sourceTask = Get-TCTask -ProjectUuid $booking.APP_ProjectUuid -Uuid $booking.APP_TaskUuid
        if(!$targetTaskCode) { $usedTargetTaskCode = $sourceTask.APP_Code; }
        else { $usedTargetTaskCode = $targetTaskCode; } 
        $targetTask = Get-TCTask -ProjectUuid $targetProject.APP_ProjectUuid -Code $usedTargetTaskCode
        
        # if not exists, create it
        if(!$targetTask) 
        {
            if($pscmdlet.ShouldProcess("Project '${targetProjectCode}', Task '$($sourceTask.APP_Code)'", "Add-TCTask"))
            {
                Write-Output "Adding Task '$($sourceTask.APP_Code)' to Project '${targetProjectCode}'" 
                $targetTask = Add-TCTask -ProjectUuid $targetProject.APP_ProjectUuid -Code $sourceTask.APP_Code -Description $sourceTask.APP_Description
            }
        }
    } 
    else
    {
        $targetTask = $Null
    }
    if($pscmdlet.ShouldProcess("Timesheet '$($booking.APP_BeginTime)' to '${customerCode}.${targetProjectCode}.$($targetTask.APP_Code)'", "Edit-TCTimesheet"))
    {
        Write-Output "Moving Booking '$($booking.APP_BeginTime)' to '${customerCode}.${targetProjectCode}.$($targetTask.APP_Code)'" 
        if($targetTask)
        {
            $moved = Edit-TCTimesheet -Uuid $booking.APP_TimesheetUuid -ProjectUuid $targetProject.APP_ProjectUuid -TaskUuid $targetTask.APP_TaskUuid
        }
        else 
        {
            $moved = Edit-TCTimesheet -Uuid $booking.APP_TimesheetUuid -ProjectUuid $targetProject.APP_ProjectUuid
        }
    }
}