lib/Classes/Public/TMTask.ps1


class TMTask {

    #region Non-Static Properties

    [System.Int64]$Id

    [System.Int64]$TaskNumber

    [System.String]$Title

    [System.String]$Comment

    [ValidateSet('Hold', 'Planned', 'Ready', 'Pending', 'Started', 'Completed', 'Terminated')]
    [System.String]$Status

    [Nullable[System.DateTime]]$StatusUpdated

    [System.String]$StatusUpdatedElapsed

    [Nullable[System.DateTime]]$LastUpdated

    [System.String]$LastUpdatedElapsed

    [TMTaskAction]$Action

    [TMTaskAsset]$Asset

    [TMReference]$AssignedTo

    [TMReference]$CreatedBy

    [System.String]$Category

    [Nullable[System.DateTime]]$DateCreated

    [ValidateRange(0, 1)]
    [System.Int64]$HardAssigned

    [System.Int64]$EstDurationMinutes

    [String]$EstStart

    [String]$EstFinish

    [System.Object]$Slack

    [System.Boolean]$IsCriticalPath

    [Nullable[System.DateTime]]$ActStart

    [Nullable[System.DateTime]]$ActFinish

    [System.String]$Team

    [System.Boolean]$IsPublished

    [ValidateRange(0, 100)]
    [System.Int64]$PercentageComplete

    [TMReference]$Project

    [System.Boolean]$IsActionInvocableLocally

    [System.Boolean]$IsActionInvocableRemotely

    [System.Boolean]$IsAutomatic

    [System.Int64]$Duration

    [System.Boolean]$SendNotification

    [ValidateRange(0, 5)]
    [System.Int64]$Priority

    [TMReference]$Event

    [Nullable[System.DateTime]]$DueDate

    [System.String]$InstructionsLink

    [TMTaskDependency[]]$Predecessors

    [TMTaskDependency[]]$Successors

    [System.Int32]$Schema

    [System.String]$Attribute

    [System.Boolean]$AutoGenerated

    [System.String]$DisplayOption

    [System.Object]$Recipe

    [System.Int64]$TaskSpec



    #endregion Non-Static Properties

    #region Static Properties

    static [System.String[]]$ValidStatuses = @(
        'Hold',
        'Planned',
        'Ready',
        'Pending',
        'Started',
        'Completed',
        'Terminated'
    )

    hidden static [System.String[]]$TMQLFetchProperties = @(
        'actFinish'
        'actStart'
        'apiAction.actionType'
        'apiAction.description'
        'apiAction.id'
        'apiAction.isRemote'
        'apiAction.methodParams'
        'apiAction.name'
        'apiActionCompletedAt'
        'apiActionInvokedAt'
        'apiActionSettings'
        'assetEntity.Asset Class'
        'assetEntity.assetType'
        'assetEntity.Bundle'
        'assetEntity.Id'
        'assetEntity.Name'
        'assetEntity.Tags'
        'assignedTo.id'
        'assignedTo.name'
        'attribute'
        'autoGenerated'
        'category'
        'comment'
        'commentType'
        'createdBy.id'
        'createdBy.name'
        'dateCreated'
        'dateResolved'
        'displayOption'
        'dueDate'
        'duration'
        'estFinish'
        'estStart'
        'hardAssigned'
        'id'
        'instructionsLink'
        'isCriticalPath'
        'isPublished'
        'lastUpdated'
        'moveEvent.id'
        'moveEvent.name'
        'percentageComplete'
        'predecessors'
        'priority'
        'project.id'
        'project.name'
        'recipe'
        'role'
        'sendNotification'
        'slack'
        'status'
        'statusUpdated'
        'successors'
        'taskNumber'
        'taskSpec'
    )

    #endregion Static Properties

    #region Constructors

    TMTask() {}

    TMTask([Object]$_object) {
        $this.Schema = $_object.PSObject.Properties.Name -contains 'assetEntity.Tags' ? 2 : 1
        $this.Id = $_object.id
        $this.TaskNumber = $_object.taskNumber
        $this.Comment = $_object.comment ?? $_object.title
        $this.Title = $_object.title ?? $_object.comment
        $this.Status = $_object.status
        $this.StatusUpdated = $_object.statusUpdated
        $this.StatusUpdatedElapsed = $_object.statusUpdatedElapsed ?? ($_object.statusUpdated ? (New-TimeSpan -Start $_object.statusUpdated -End (Get-Date -AsUTC)) : "")
        $this.LastUpdated = $_object.lastUpdated
        $this.LastUpdatedElapsed = $_object.lastUpdatedElapsed ?? ($_object.statusUpdated ? (New-TimeSpan -Start $_object.lastUpdated -End (Get-Date -AsUTC)) : "")
        $this.Action = if ($this.Schema -eq 1) {
            [TMTaskAction]::new(($_object.action ?? $_object.apiAction))
        } else {
            [TMTaskAction]::new(
                $_object.'apiAction.id',
                $_object.'apiAction.name',
                $_object.'apiAction.isRemote',
                $_object.'apiAction.actionType',
                $_object.'apiAction.description',
                $_object.'apiActionInvokedAt',
                $_object.'apiActionCompletedAt',
                $_object.'apiAction.methodParams'
            )
        }
        $this.Asset = if ($this.Schema -eq 1) {
            [TMTaskAsset]::new($_object.asset)
        } else {
            [TMTaskAsset]::new(
                $_object.'assetEntity.Id',
                $_object.'assetEntity.Name',
                $_object.'assetEntity.Asset Class',
                $_object.'assetEntity.assetType',
                @{id = $_object.'assetEntity.Bundle.id'; name = $_object.'assetEntity.Bundle.name' },
                $_object.'assetEntity.tags'
            )
        }
        $this.AssignedTo = $this.Schema -eq 1 ? [TMReference]::new($_object.assignedTo) : [TMReference]::new($_object.'assignedTo.name', $_object.'assignedTo.id')
        $this.CreatedBy = $this.Schema -eq 1 ? [TMReference]::new($_object.createdBy) : [TMReference]::new($_object.'createdBy.name', $_object.'createdBy.id')
        $this.Category = $_object.category
        $this.DateCreated = $_object.dateCreated
        $this.HardAssigned = $_object.hardAssigned
        $this.EstDurationMinutes = $_object.estDurationMinutes
        $this.EstStart = $_object.estStart
        $this.EstFinish = $_object.estFinish
        $this.Slack = $_object.slack
        $this.IsCriticalPath = $_object.isCriticalPath
        $this.ActStart = $_object.actStart
        $this.ActFinish = $_object.actFinish
        $this.Team = $_object.team ?? $_object.role
        $this.IsPublished = $_object.isPublished
        $this.PercentageComplete = $_object.percentageComplete
        $this.Project = $this.Schema -eq 1 ? [TMReference]::new($_object.project) : [TMReference]::new($_object.'project.name', $_object.'project.id')
        $this.IsActionInvocableLocally = $_object.isActionInvocableLocally ?? $this.IsActionInvokable($_object, 'Local')
        $this.IsActionInvocableRemotely = $_object.isActionInvocableRemotely ?? $this.IsActionInvokable($_object, 'Remote')
        $this.IsAutomatic = $_object.isAutomatic ?? ($_object.role -eq 'AUTO') -or ($_object.'assignedTo.id' -eq 0)
        $this.Duration = $_object.duration
        $this.SendNotification = $_object.sendNotification
        $this.Priority = $_object.priority
        $this.Event = $this.Schema -eq 1 ? [TMReference]::new($_object.event) : [TMReference]::new($_object.'moveEvent.name', $_object.'moveEvent.id')
        $this.DueDate = $_object.dueDate
        $this.InstructionsLink = $_object.instructionsLink
        $this.Predecessors = $_object.predecessors | ForEach-Object { [TMTaskDependency]::new($_) }
        $this.Successors = $_object.successors | ForEach-Object { [TMTaskDependency]::new($_) }
        $this.Attribute = $_object.attribute
        $this.AutoGenerated = $_object.autoGenerated
        $this.DisplayOption = $_object.displayOption
        $this.Recipe = $_object.recipe
        $this.TaskSpec = $_object.taskSpec
    }

    #endregion Constructors

    #region Static Methods

    static [String]GetFetchStringForTMQL() {
        return "'" + ([TMTask]::TMQLFetchProperties -join "', '") + "'"
    }

    #endregion Static Methods

    #region Non-Static Methods

    hidden [PSCustomObject]GetWSUpdateObject() {
        $ReturnObject = [PSCustomObject]@{
            id                 = $this.Id
            comment            = $this.comment ? $this.comment : $this.Title
            project            = $this.Project.Id
            status             = $this.Status
            assignedTo         = $this.AssignedTo.id
            apiAction          = $this.Action.Id
            apiActionId        = $this.Action.Id
            category           = $this.Category
            assetEntity        = $this.Asset.Id
            hardAssigned       = $this.HardAssigned
            moveEvent          = $this.Event.id
            priority           = $this.Priority
            role               = $this.Team
            percentageComplete = $this.PercentageComplete
            sendNotification   = $this.SendNotification ? 1 : 0
            instructionsLink   = $this.InstructionsLink
            duration           = $this.Duration
            durationScale      = 'M'
            durationLocked     = 0
            taskDependency     = @()
            taskSuccessor      = @()
        }

        foreach ($Predecessor in $this.Predecessors) {
            if (-not $Predecessor.Id -or $Predecessor.Id -eq 0) {
                $Predecessor.Id = -1
            }
            $ReturnObject.taskDependency += "$($Predecessor.Id)_$($Predecessor.TaskId)"
        }

        foreach ($Successor in $this.Successors) {
            if (-not $Successor.Id -or $Successor.Id -eq 0) {
                $Successor.Id = -1
            }
            $ReturnObject.taskSuccessor += "$($Successor.Id)_$($Successor.TaskId)"
        }

        return $ReturnObject
    }

    hidden [PSCustomObject]GetApiUpdateObject([String]$_note) {
        $ReturnObject = [PSCustomObject]@{
            action             = @{ id = $this.Action.Id }
            asset              = @{ id = $this.Asset.Id }
            event              = @{ id = $this.Event.id }
            assignedTo         = $this.AssignedTo.id
            category           = $this.Category
            comment            = $this.comment ? $this.comment : $this.title
            title              = $this.comment ? $this.comment : $this.title
            hardAssigned       = $this.HardAssigned
            instructionsLink   = $this.InstructionsLink
            percentageComplete = $this.PercentageComplete
            priority           = $this.Priority
            role               = $this.Team
            status             = $this.Status
            currentStatus      = $this.Status
            sendNotification   = $this.SendNotification ? 1 : 0
            project            = $this.Project.Id
            note               = $_note
            predecessors       = @()
            successors         = @()
        }

        foreach ($Predecessor in $this.Predecessors) {
            if (-not $Predecessor.Id -or $Predecessor.Id -eq 0) {
                $Predecessor.Id = -1
            }
            $ReturnObject.predecessors += @{id = $Predecessor.Id; taskId = $Predecessor.TaskId }
        }

        foreach ($Successor in $this.Successors) {
            if (-not $Successor.Id -or $Successor.Id -eq 0) {
                $Successor.Id = -1
            }
            $ReturnObject.successors += @{id = $Successor.Id; taskId = $Successor.TaskId }
        }


        return $ReturnObject
    }

    hidden [System.Boolean]IsActionInvokable([System.Object]$_object, [System.String]$_location) {
        $_invokable = switch ($_location) {
            'Remote' {
                (
                    ($_object.'apiAction.id' -gt 0) -and
                    (-not $_object.apiActionInvokedAt) -and
                    ($_object.'apiAction.isRemote') -and
                    ($_object.status -in 'Ready', 'Started')
                )
            }

            'Local' {
                (
                    ($_object.'apiAction.id' -gt 0) -and
                    (-not $_object.apiActionInvokedAt) -and
                    (-not $_object.'apiAction.isRemote') -and
                    ($_object.status -in 'Ready', 'Started')
                )
            }

            default {$false}
        }

        return $_invokable
    }

    #endregion Non-Static Methods
}


class TMTaskAction {

    #region Non-Static Properties

    [System.Int64]$Id
    [System.String]$Name
    [System.Boolean]$IsRemote
    [TMTaskActionActionType]$ActionType
    [System.String]$Description
    [Nullable[System.DateTime]]$InvokedAt
    [System.Object]$CompletedAt
    [TMTaskActionMethodParam[]]$MethodParams

    #endregion Non-Static Properties

    #region Constructors

    TMTaskAction() {}

    TMTaskAction(
        [System.Int64]$_id,
        [System.String]$_name,
        [System.Boolean]$_isRemote,
        [System.Object]$_actionType,
        [System.String]$_description,
        [Nullable[System.DateTime]]$_invokedAt,
        [System.Object]$_completedAt,
        [System.Object]$_methodParams
    ) {
        $this.Id = $_id
        $this.Name = $_name
        $this.IsRemote = $_isRemote
        $this.ActionType = [TMTaskActionActionType]::new($_actionType)
        $this.Description = $_description
        $this.InvokedAt = $_invokedAt
        $this.CompletedAt = $_completedAt
        if ($_methodParams -is [System.String]) {
            $_methodParams = ($_methodParams | ConvertFrom-Json -Depth 5)
        }
        $this.MethodParams = $_methodParams | ForEach-Object { [TMTaskActionMethodParam]::new($_) }
    }

    TMTaskAction([Object]$_object) {
        $this.Id = $_object.id
        $this.Name = $_object.name
        $this.IsRemote = $_object.isRemote
        $this.ActionType = [TMTaskActionActionType]::new($_object.actionType)
        $this.Description = $_object.description
        $this.InvokedAt = $_object.invokedAt
        $this.CompletedAt = $_object.completedAt
        if ($_object.methodParams -is [System.String]) {
            $_object.methodParams = ($_object.methodParams | ConvertFrom-Json -Depth 5)
        }
        $this.MethodParams = $_object.methodParams | ForEach-Object { [TMTaskActionMethodParam]::new($_) }
    }

    #endregion Constructors

}


class TMTaskActionMethodParam {

    #region Non-Static Properties

    [System.String]$Type
    [System.String]$Value
    [System.String]$Context
    [System.Boolean]$Encoded
    [System.Boolean]$Invalid
    [System.Boolean]$Readonly
    [System.Boolean]$Required
    [System.String]$FieldName
    [System.String]$ParamName
    [System.String]$Description

    #endregion Non-Static Properties

    #region Constructors

    TMTaskActionMethodParam() {}

    TMTaskActionMethodParam([Object]$_object) {
        $this.Type = $_object.type
        $this.Value = $_object.value
        $this.Context = $_object.context
        $this.Encoded = $_object.encoded
        $this.Invalid = $_object.invalid
        $this.Readonly = $_object.readonly
        $this.Required = $_object.required
        $this.FieldName = $_object.fieldName
        $this.ParamName = $_object.paramName
        $this.Description = $_object.description
    }

    #endregion Constructors

}


class TMTaskActionActionType {

    #region Non-Static Properties

    [System.String]$Id
    [System.String]$Name

    #endregion Non-Static Properties

    #region Constructors

    TMTaskActionActionType() {}

    TMTaskActionActionType([System.String]$_id, [System.String]$_name) {
        $this.Id = $_id
        $this.Name = $_name
    }

    TMTaskActionActionType([System.String]$_object) {
        $this.Id = $_object
        $this.Name = $_object
    }

    TMTaskActionActionType([Object]$_object) {
        $this.Id = $_object.id
        $this.Name = $_object.name
    }

    #endregion Constructors

}


class TMTaskAsset {

    #region Non-Static Properties

    [System.Int64]$Id
    [System.String]$Name
    [System.String]$Class
    [System.String]$Type
    [TMReference]$Bundle
    [System.String[]]$Tags

    #endregion Non-Static Properties

    #region Constructors

    TMTaskAsset() {}

    TMTaskAsset(
        [System.Int64]$_id,
        [System.String]$_name,
        [System.String]$_class,
        [System.String]$_type,
        [System.Object]$_bundle,
        [String[]]$_tags
    ) {
        $this.Id = $_id
        $this.Name = $_name
        $this.Class = $_id -eq 0 ? '' : $_class
        $this.Type = $_type
        $this.Bundle = [TMReference]::new($_bundle)
        $this.Tags = $_tags
    }

    TMTaskAsset([Object]$_object) {
        $this.Id = $_object.id
        $this.Name = $_object.name
        $this.Class = $_object.id -eq 0 ? '' : $_object.class
        $this.Type = $_object.type
        $this.Bundle = [TMReference]::new($_object.bundle)
        $this.Tags = $_object.tags
    }

    #endregion Constructors

}


class TMTaskDependency {

    #region Non-Static Properties

    [System.Int64]$Id
    [System.Int64]$TaskId
    [System.Int64]$Number
    [System.String]$Title

    #endregion Non-Static Properties

    #region Constructors

    TMTaskDependency() {}

    TMTaskDependency([System.Int64]$_taskId) {
        $this.TaskId = $_taskId
    }

    TMTaskDependency([System.Int64]$_id, [System.Int64]$_taskId, [System.Int64]$_number, [System.String]$_title) {
        $this.Id = $_id
        $this.TaskId = $_taskId
        $this.Number = $_number
        $this.Title = $_title
    }

    TMTaskDependency([Object]$_object) {
        $this.Id = $_object.id
        $this.TaskId = $_object.taskId
        $this.Number = $_object.number
        $this.Title = $_object.title
    }

    #endregion Constructors

}