#---------------------------------------------------------------------------------------------------------------------
#  Script:   Copy Work Item attachment from Parent to Child Notification Activity 
#  Author:   www.xapity.com
#  Date:     29-11-2016
#  Version:  1.0
#  Comments: Used in a Xapity PowerShell Activity to copy the attachments from a Parent work Item
#            to a Child Notificastion Activity with [AddAttachments] in Title.
#            Use with SR, CR and RR workflows
#---------------------------------------------------------------------------------------------------------------------

Import-Module SMLets -Force

function Add-ActionComment {
    param (
            [parameter(Mandatory=$true,Position=0)][Alias('Id')]$ParentWorkItemID,
            [parameter(Mandatory=$true,Position=1)][Alias('ActionType')][String]$ActionTypeData,
            [parameter(Mandatory=$true,Position=2)][Alias('Title')][String]$AddTitle,
            [parameter(Mandatory=$true,Position=3)][Alias('Comment')][String]$AddComment,
            [parameter(Mandatory=$true,Position=4)][Alias('EnteredBy')][String]$AddEnteredBy
          )

    #Check what type of WorkItem and set variables 
    If ($ParentWorkItemID -like "SR*") {
    $WorkItemClass = Get-SCSMClass System.WorkItem.ServiceRequest$
    $WorkItemTypeProjection = "System.WorkItem.ServiceRequestProjection" }

    ElseIf ($ParentWorkItemID -like "IR*") {
    $WorkItemClass = Get-SCSMClass System.WorkItem.Incident$
    $WorkItemTypeProjection = "Xapity.ActionLog.TypeProjection.Incident"}

    ElseIf ($ParentWorkItemID -like "PR*") {
    $WorkItemClass = Get-SCSMClass System.WorkItem.Problem$
    $WorkItemTypeProjection = "Xapity.ActionLog.TypeProjection.Problem"}

    Switch($ActionTypeData) 
    {
        EmailSent {$ActionType = "System.WorkItem.ActionLogEnum.EmailSent"}
        FileAttached {$ActionType = "System.WorkItem.ActionLogEnum.FileAttached"}
        FileDeleted {$ActionType = "System.WorkItem.ActionLogEnum.FileDeleted"}
        RecordAssigned {$ActionType = "System.WorkItem.ActionLogEnum.RecordAssigned"}
        RecordClosed {$ActionType = "System.WorkItem.ActionLogEnum.RecordClosed"}
        RecordDispatched {$ActionType = "System.WorkItem.ActionLogEnum.RecordDispatched"}
        RecordEscalated {$ActionType = "System.WorkItem.ActionLogEnum.RecordEscalated"}
        RecordOpened {$ActionType = "System.WorkItem.ActionLogEnum.RecordOpened"}
        Reopened {$ActionType = "System.WorkItem.ActionLogEnum.Reopened"}
        Resolved {$ActionType = "System.WorkItem.ActionLogEnum.Resolved"}
        SurveyCompleted {$ActionType = "System.WorkItem.ActionLogEnum.SurveyCompleted"}
        TaskExecuted {$ActionType = "System.WorkItem.ActionLogEnum.TaskExecuted"}
        TemplateApplied {$ActionType = "System.WorkItem.ActionLogEnum.TemplateApplied"}
     }


    $WorkItemObject = Get-SCSMObject -Class $WorkItemClass -Filter "Id -eq $ParentWorkItemID" 
    $NewGUID = ([guid]::NewGuid()).ToString()
    $Projection = @{__CLASS = $ProjectionClass;
                    __SEED = $WorkItemObject;
                    ActionLog = @{__CLASS = "System.WorkItem.TroubleTicket.ActionLog";
                                          __OBJECT = @{Id = $NewGUID;
                                                       DisplayName = $NewGUID;
                                                       ActionType = $ActionType;
                                                       Title = $AddTitle;
                                                       Description = $AddComment;
                                                       EnteredBy  = $AddEnteredBy;
                                                       EnteredDate = (Get-Date).ToUniversalTime();
                                                       IsPrivate = $false;
                                                      }
                                         }
                   }
    New-SCSMObjectProjection -Type $WorkItemTypeProjection -Projection $Projection
}

#Set the variables that depend on the work item type ie SR, CR or RR
If ($ParentID -like "SR*")     {$ParentClass = Get-SCSMClass System.WorkItem.ServiceRequest$; $CommentLog = "ActionLog"}
ElseIf ($ParentID -like "CR*") {$ParentClass = Get-SCSMClass System.WorkItem.ChangeRequest$; $CommentLog = "Notes"}
ElseIf ($ParentID -like "RR*") {$ParentClass = Get-SCSMClass System.WorkItem.ReleaseRecord$; $CommentLog = "Notes"}

#Set the Object and class of  File Attachments and Parent Object
$ParentObject = Get-SCSMObject -Class $ParentClass -Filter "ID -eq $ParentID"
$FileAttachmentClass = Get-SCSMClass -Name "System.FileAttachment"
$ManagementGroup =  new-object Microsoft.EnterpriseManagement.EnterpriseManagementGroup "localhost"
$FileAttachmentRel = Get-SCSMRelationshipClass "System.WorkItemHasFileAttachment"

#Get the Attachments from the Parent Object
$Sourcefiles = Get-SCSMRelatedObject -SMObject $ParentObject -Relationship $FileAttachmentRel 

#Get a list of the Activities on the ParentObject. Recursive to find Activities in PA or SA containers. Filtered to Xapity WorkItem Activity
$Activities = Get-SCSMRelatedObject -SMObject $ParentObject -Depth Recursive  | ?{$_.TypeName -like "Xapity.WorkItem.Activity.*"}

#Loop through each activity looking for keyword AddAttachement
foreach ($Activity in $Activities)
            {  
                If ($Activity.title -like "*addattachment*")
                    { 
                        Write-Host "Copy attachments to Activity: [$($Activity.Id)]: $($Activity.Title)"
 
                        $AddComment ="" #set comment to blank value

                        #Loop through each of the attachments on the ParentObject and add them to the Activity
                        Foreach ( $Attachment in $SourceFiles )
                        {   #Read the attachment into a memory stream          
                            $memoryStream = New-Object IO.MemoryStream
                            $buffer = New-Object byte[] 8192
                            [int]$bytesRead|Out-Null
                            while (($bytesRead = $attachment.Content.Read($buffer, 0, $buffer.Length)) -gt 0)
                                {$memoryStream.Write($buffer, 0, $bytesRead) }        

                            #Create new file object 
                            $NewAttachment = New-Object Microsoft.EnterpriseManagement.Common.CreatableEnterpriseManagementObject($ManagementGroup, $FileAttachmentClass)
                            
                            #Populate properties of new object
                            $NewGUID_Attachment = [Guid]::NewGuid().ToString()
                            $NewAttachment.Item($FileAttachmentClass, "Id").Value = $NewGUID_Attachment
                            $NewAttachment.Item($FileAttachmentClass, "DisplayName").Value = $Attachment.DisplayName
                            $NewAttachment.Item($FileAttachmentClass, "Description").Value = $Attachment.Name
                            $NewAttachment.Item($FileAttachmentClass, "Extension").Value = $Attachment.Extension
                            $NewAttachment.Item($FileAttachmentClass, "Size").Value = $memoryStream.Length
                            $NewAttachment.Item($FileAttachmentClass, "AddedDate").Value = [DateTime]::Now.ToUniversalTime()
                            $NewAttachment.Item($FileAttachmentClass, "Content").Value = $memoryStream

                            #Initialise projection. This is hard coded to the Notification Activity. This would need to change for other activity types
                            $ProjectionType = Get-SCSMTypeProjection -Name Xapity.NotificationActivity.Form.ProjectionType$
                            $Projection = Get-SCSMObjectProjection -ProjectionName $ProjectionType.Name -Filter "ID -eq $($Activity.ID)"

                            #Attach file to the work item
                            $Projection.__base.Add($NewAttachment, $FileAttachmentRel.Target)
                            $Projection.__base.Commit()

                            $AddComment += "  Attached File to [$($Activity.Id)]:  $($Attachment.Displayname) `n"   
                
                            #Close the file stream
                            $memoryStream.Close();

                        } #End foreach Attachment

                        Write-Host $AddComment
                       
                        #Write to Action Log for SR and to Notes Field for CR or RR
                        If ($CommentLog -eq "Notes")  #this applies to CR and RR
                            {
                                If ($ParentObject.Notes -eq $null)
                                   {$ParentObject | Set-SCSMObject -Property Notes -Value $AddComment}
                                Else
                                   {$AppendedDescription = $ParentObject.Notes + "`n" + $AddComment
                                    $ParentObject | Set-SCSMObject -Property Notes -Value $AppendedDescription
                                   }
                            } #End CommentLog If

                        ElseIf ($CommentLog -eq "ActionLog") #this applies to SR 
                             { Add-ActionComment -Id "$ParentID" -ActionType "FileAttached"  -Title "Files Uploaded" -Comment $AddComment -EnteredBy "System, John"  } 

                    } # End of If Activity matched
                    Else
                        {Write-Host "No Match [$($Activity.ID)]: $($Activity.Title)"} 
                
            } #End of ForEach Activity