TimeCockpit.psm1

$tokenUri = "https://api.timecockpit.com/token";
$baseUrl = "https://api.timecockpit.com/odata";

<#
.SYNOPSIS
Connects to TimeCockpit.
 
.DESCRIPTION
 
.PARAMETER Username
Name of User to connect to Timecockpit to
 
.PARAMETER Password
Password of user to connect to Timecockpit to
#>

function Connect-TC
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][string]$Username,
       [Parameter(Mandatory=$true)][string]$Password
    ) #end param
    
    $webclient = new-object System.Net.WebClient
    $webclient.Credentials = new-object System.Net.NetworkCredential($Username, $Password)
    $script:token = $webclient.DownloadString($tokenUri)
}

<#
.SYNOPSIS
Adds a country to Timecockpit.
 
.DESCRIPTION
 
.PARAMETER IsoCode
2 Digits ISO Code of the country
 
.PARAMETER CountryName
Name of the country
#>

function Add-TCCountry
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][string]$IsoCode,
       [Parameter(Mandatory=$true)][string]$CountryName
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $bodyAsJson = ConvertTo-JSON( @{ APP_CountryName=${CountryName}; APP_IsoCode=${IsoCode}; });

    return $(Invoke-RestMethod -Uri "${baseUrl}/APP_Country" -Method Post -Body $bodyAsJson -ContentType "application/json; charset=utf-8" -Headers @{Authorization=("Bearer {0}" -f $script:token)});
}

<#
.SYNOPSIS
Returns customers from Timecockpit.
 
.DESCRIPTION
All parameters are optional filters. Executing with no parameter returns all customers.
 
.PARAMETER Code
Code of Timecockpit-Customer to filter for
 
.PARAMETER Uuid
Uuid of Timecockpit-Customer to filter for
 
#>

function Get-TCCustomer
{
    [CmdletBinding()]
    Param(
       [string]$Code,
       [Guid]$Uuid
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $uri = "${baseUrl}/APP_Customer()";
    $filterParams = @{};
    if($code) { $filterParams.Add("APP_Code", $Code); }
    if($uuid) { $filterParams.Add("APP_CustomerUuid", $Uuid); }

    if($filterParams.Count -gt 0) { $uri = "${uri}?`$filter=$(CreateFilter($filterParams))"; }
    return $(Invoke-RestMethod -Uri $uri -Method Get -Headers @{Authorization=("Bearer {0}" -f $script:token)}).value;
}

<#
.SYNOPSIS
Returns projects from Timecockpit.
 
.DESCRIPTION
All parameters are optional filters. Executing with no parameter returns all projects.
 
.PARAMETER CustomerCode
Code of Timecockpit-Customer to filter projects for
 
.PARAMETER CustomerUuid
Uuid of Timecockpit-Customer to filter projects for
 
.PARAMETER Code
Code of Timecockpit-Project to filter projects for
 
.PARAMETER Uuid
Uuid of Timecockpit-Customer to filter projects for
 
.PARAMETER Closed
By default only open projects are returned. (Closed=False) Set to null to return closed and open projects.
#>

function Get-TCProject
{
    [CmdletBinding()]
    Param(
       [string]$CustomerCode,
       [Guid]$CustomerUuid,
       [string]$Code,
       [Guid]$Uuid,
       [Nullable[boolean]]$Closed=$False
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $uri = "${baseUrl}/APP_Project()";
    $filterParams = @{};
    if($CustomerCode) { $filterParams.Add("APP_Customer/APP_Code", $CustomerCode); }
    if($CustomerUuid) { $filterParams.Add("APP_Customer/APP_CustomerUuid", $CustomerUuid); }
    if($Code) { $filterParams.Add("APP_Code", $Code); }
    if($Uuid) { $filterParams.Add("APP_ProjectUuid", $Uuid); }
    if($Closed -ne $Null) { $filterParams.Add("APP_Closed", $Closed); }

    if($filterParams.Count -gt 0) { $uri = "${uri}?`$filter=$(CreateFilter($filterParams))"; }
    return $(Invoke-RestMethod -Uri $uri -Method Get -Headers @{Authorization=("Bearer {0}" -f $script:token)}).value;
}

<#
.SYNOPSIS
Modifies a Project
 
.DESCRIPTION
 
.PARAMETER Uuid
Uuid of the project to modify
 
.PARAMETER Code
Code to set in the project
 
.PARAMETER Description
Description to set in the project
 
.PARAMETER HourlyRate
HourlyRate to set in the project
#>

function Edit-TCProject
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][Guid]$Uuid,
       [string]$Code,
       [string]$Description,
       [float]$HourlyRate
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $body = @{};
    if($Code) { $body.Add("APP_Code", $Code); }
    if($Description) { $body.Add("APP_Description", $Description); }
    if($HourlyRate) 
    { 
        $culture = New-Object System.Globalization.CultureInfo("en-US");
        $body.Add("APP_HourlyRate", $HourlyRate.ToString($culture)); 
    }
    $bodyAsJson = ConvertTo-Json($body);
    Write-Host $bodyAsJson;
    
    return $(Invoke-RestMethod -Uri "${baseUrl}/APP_Project(guid'${Uuid}')" -Method Patch -Body $bodyAsJson -ContentType "application/json; charset=utf-8" -Headers @{Authorization=("Bearer {0}" -f $script:token)});
}

<#
.SYNOPSIS
Adds a Task to a project.
 
.DESCRIPTION
Use Get-TCProject for receiving the Uuid of a project.
 
.PARAMETER ProjectUuid
Uuid of the project
 
.PARAMETER Code
The code of the task to add
 
.PARAMETER Description
The Description to set in the task
#>

function Add-TCTask
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][Guid]$ProjectUuid,
       [Parameter(Mandatory=$true)][string]$Code,
       [string]$Description = ""
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $bodyAsJson = ConvertTo-JSON( @{ APP_ProjectUuid=${ProjectUuid}; APP_Code=${Code}; APP_Description=${Description} });

    return $(Invoke-RestMethod -Uri "${baseUrl}/APP_Task" -Method Post -Body $bodyAsJson -ContentType "application/json; charset=utf-8" -Headers @{Authorization=("Bearer {0}" -f $script:token)});
}

<#
.SYNOPSIS
Returns tasks from a project.
 
.DESCRIPTION
All parameters are optional filters. Executing with no parameter returns all tasks.
Use Get-TCProject for receiving the Uuid of a project.
 
.PARAMETER ProjectUuid
Uuid of project to get tasks from
 
.PARAMETER Code
Code of the task
 
.PARAMETER Uuid
Uuid of the task
#>

function Get-TCTask
{
    [CmdletBinding()]
    Param(
       [Guid]$ProjectUuid,
       [string]$Code,
       [Guid]$Uuid
   ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $uri = "${baseUrl}/APP_Task()";
    $filterParams = @{};
    if($ProjectUuid) { $filterParams.Add("APP_Project/APP_ProjectUuid", $ProjectUuid); }
    if($Code) { $filterParams.Add("APP_Code", $Code); }
    if($Uuid) { $filterParams.Add("APP_TaskUuid", $Uuid); }

    if($filterParams.Count -gt 0) { $uri = "${uri}?`$filter=$(CreateFilter($filterParams))"; }
    return $(Invoke-RestMethod -Uri $uri -Method Get -Headers @{Authorization=("Bearer {0}" -f $script:token)}).value;
}

<#
.SYNOPSIS
Modifies a Task
 
.DESCRIPTION
 
.PARAMETER Uuid
Uuid of the task to modify
 
.PARAMETER Code
Code to set in the task
 
.PARAMETER Description
Description to set in the task
#>

function Edit-TCTask
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][Guid]$Uuid,
       [string]$Code,
       [string]$Description,
       [Nullable[boolean]]$Closed
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $body = @{};
    if($Code) { $body.Add("APP_Code", $Code); }
    if($Description) { $body.Add("APP_Description", $Description); }
    if($Closed -ne $Null) { $body.Add("APP_Closed", $Closed); }
    $bodyAsJson = ConvertTo-Json($body);
    
    return $(Invoke-RestMethod -Uri "${baseUrl}/APP_Task(guid'${Uuid}')" -Method Patch -Body $bodyAsJson -ContentType "application/json; charset=utf-8" -Headers @{Authorization=("Bearer {0}" -f $script:token)});
}

<#
.SYNOPSIS
Closes a Task
 
.DESCRIPTION
If the task is already closed, no error is created, its just kept open.
 
.PARAMETER Uuid
Uuid of the task to close
#>

function Close-TCTask
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][Guid]$Uuid
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $body = "{ 'APP_Closed' : 1 }";

    return $(Invoke-RestMethod -Uri "${baseUrl}/APP_Task(guid'${Uuid}')" -Method Patch -Body $body -ContentType "application/json; charset=utf-8" -Headers @{Authorization=("Bearer {0}" -f $script:token)});
}

<#
.SYNOPSIS
Opens a Task
 
.DESCRIPTION
If the task is already open, no error is created, its just kept open.
 
.PARAMETER Uuid
Uuid of the task to open
#>

function Open-TCTask
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][Guid]$Uuid
    ) #end param

    if(!$script:token) { throw "Authenticate using Connect-TC"; }
    
    $body = "{ 'APP_Closed' : 0 }";

    return $(Invoke-RestMethod -Uri "${baseUrl}/APP_Task(guid'${Uuid}')" -Method Patch -Body $body -ContentType "application/json; charset=utf-8" -Headers @{Authorization=("Bearer {0}" -f $script:token)});
}

#Export-ModuleMember -Function 'Connect-TC';
#Export-ModuleMember -Function 'Get-TCCustomer';
#Export-ModuleMember -Function 'Get-TCProject';
#Export-ModuleMember -Function 'Edit-TCProject';
#Export-ModuleMember -Function 'Add-TCCountry';
#Export-ModuleMember -Function 'Add-TCTask';
#Export-ModuleMember -Function 'Get-TCTask';
#Export-ModuleMember -Function 'Edit-TCTask';
#Export-ModuleMember -Function 'Close-TCTask';

function CreateFilter($parameters)
{
    $first = $True;
    foreach($parameter in $parameters.Keys)
    {
        $value = $parameters[$parameter];
        
        if(!$First) { $filter = "${filter} and "; } 
        if($value.GetType() -eq [string]) { $filter = "${filter}${parameter} eq '${value}'"; }
        elseif($value.GetType() -eq [Guid]) { $filter = "${filter}${parameter} eq guid'${value}'"; }
        elseif($value.GetType() -eq [Boolean]) { $filter = "${filter}${parameter} eq $(([string]$value).ToLower())"; }
        else { $filter = "${filter}${parameter} eq ${value}"; }

        $First = $False;
    }
    return $filter;
}