Functions/Import-BsgPbiReportsTenantLevel.ps1

<#
    .SYNOPSIS
        Import Power BI reports which are based on a dataset in a different workspace.
         
    .DESCRIPTION
        Import Power BI reports which are based on a dataset in a different workspace.
        Please restore all workspaces before running this script.
        Reports which are connected to a dataset in another workspace need to have their connection updated and reestablished after the dataset has been restored.
 
    .PARAMETER Path
        The path to the tenant folder.
        The folder needs to include the workspaces and mapping files.
 
    .PARAMETER PbiConnection
        The connection to the Power BI Tenant.
 
    .EXAMPLE
        # Import tenant level reports
        Import-BsgPbiReportsTenantLevel -Path "C:\temp\BSG PBI Administration"
         
    .INPUTS
 
    .OUTPUTS
 
    .NOTES
        This script uses the Power BI Management module for Windows PowerShell. If this module isn't installed, install it by using the command 'Install-Module -Name MicrosoftPowerBIMgmt -Scope CurrentUser'.
#>


function Import-BsgPbiReportsTenantLevel {

    param(
        [Parameter(Mandatory=$true)][string]$Path
        ,[Parameter(Mandatory=$false)][Microsoft.PowerBI.Common.Abstractions.Interfaces.IPowerBIProfile] $PbiConnection = $null
    )

    try{

        # Info message
        Write-Host
        Write-PSFHostColor -Level Host -DefaultColor white -String "---------------------------------------------------------------------------------------------"
        Write-PSFHostColor -Level Host -DefaultColor white -String " Importing tenant level reports... "
        Write-PSFHostColor -Level Host -DefaultColor white -String "---------------------------------------------------------------------------------------------"

        # PBI connection
        if ($null -eq $PbiConnection){
            Write-Host
            Write-PSFHostColor -Level Host -DefaultColor gray -String "Choose the tenant and user to start the restoration..."
            Write-PSFHostColor -Level Host -DefaultColor gray -String "You need to be a <c='white'>Power BI Administrator</c> to restore the tenant."
            Logout-PowerBI
            $PbiLogin = Login-PowerBI
            $TenantId = $PbiLogin.TenantId
            $UserName = $PbiLogin.UserName
            Write-Host
            Write-PSFHostColor -Level Host -DefaultColor gray -String "You are logged in with user <c='white'>$userName</c> in tenant <c='white'>$TenantId</c>."
            Write-PSFHostColor -Level Host -DefaultColor white -String "Would you like to start the restoration? [y/n]: "
            $confirmTenant = Read-Host
            Write-Host
            if ($confirmTenant -eq 'y'){
                # continue...
            } else{
                Write-PSFHostColor -Level Host -DefaultColor gray -String "Restoration stopped."
                Logout-PowerBI
                return
            }
        }

        # Define paths and filenames
        $Path_Backup = Join-Path -Path $Path -ChildPath "Backup"
        $Path_Workspaces = Join-Path -Path $Path_Backup -ChildPath "Workspaces"
        $FileName_ReportDatasetMapping = "Mapping_ReportDataset.json"
        $FileName_WorkspaceMapping = "Mapping_Workspace.json"

        # Get all ReportDataset mapping files from each workspace
        $AllDatasetReport_Mappings = Get-BsgPbiAllMappingFiles -Path $Path


        # ===
        # For each mapping file
        # =
        
        $Source_Workspaces = Get-ChildItem -Path $Path_Workspaces -Name
        foreach ($Source_WorkspaceName in $Source_Workspaces) {

            # Define paths and filenames
            $Path_Workspace = Join-Path -Path $Path_Workspaces -ChildPath $Source_WorkspaceName
            $Path_ReportDatasetMapping = Join-Path $Path_Workspace -ChildPath $FileName_ReportDatasetMapping
            $Path_WorkspaceMapping = Join-Path $Path_Workspace -ChildPath $FileName_WorkspaceMapping
            

            # ===
            # Get workspace mapping file
            # =

            try{

                # Check mapping file
                if ((Test-Path $Path_WorkspaceMapping) -eq $false){
                    continue
                }
                $Workspace_Mapping = Get-Content -Path $Path_WorkspaceMapping | ConvertFrom-Json -ErrorAction Stop
                $Target_WorkspaceId = $Workspace_Mapping.new_id

            } catch{
                throw "Error while getting report-dataset mapping file `"$FileName_ReportDatasetMapping`". `n$_"   
            }


            # ===
            # Get report dataset mapping file
            # =

            try{

                # Check mapping file
                if ((Test-Path $Path_ReportDatasetMapping) -eq $false){
                    continue
                }
                $DatasetReport_Mapping = Get-Content -Path $Path_ReportDatasetMapping | ConvertFrom-Json -ErrorAction Stop

            } catch{
                throw "Error while getting report-dataset mapping file `"$FileName_ReportDatasetMapping`". `n$_"   
            }

            
            # ===
            # Process reports which have their dataset located in a different workspace
            # =

            try{

                # Get objects
                $MappingObjects = $DatasetReport_Mapping | Where-Object {$_.datasetIsInDifferentWorkspace}

                if ($null -ne $MappingObjects){
                    #$MappingObjects = $MappingObjects | Sort-Object -Property workspaceName
                    Write-Host
                    Write-PSFHostColor -Level Host -DefaultColor gray -String " Workspace: <c='white'>$Source_WorkspaceName</c>"

                    foreach ($MappingObject in $MappingObjects) {

                        $Source_ReportId = $MappingObject.reportId
                        $Source_DatasetId = $MappingObject.datasetId
                        $Target_ReportName = $MappingObject.new_reportName
    
                        # ===
                        # find shared dataset
                        # =
    
                        $SharedDatasetObject = $AllDatasetReport_Mappings | Where-Object {($_.datasetId -eq $Source_DatasetId) -and ($_.isDatasetOwner)}
                        if ($SharedDatasetObject.Count -gt 1){
                            Write-Host
                            Write-Warning "Dataset ID `"$Source_DatasetId`" must have a unique 'isDatasetOwner = true' property defined in mapping file. `nPlease edit mapping file."
                            Write-Host
                            continue
                        }
                        $Target_DatasetId = $SharedDatasetObject.new_datasetId
                        $Target_DatasetName = $SharedDatasetObject.new_datasetName

                        if ($null -eq $Target_DatasetId -or $null -eq $Target_DatasetName){
                            Write-Host
                            Write-Warning "Could not find a new dataset for report `"$Target_ReportName`" in any of report dataset mapping files."
                            Write-Host
                            Write-PSFHostColor -Level Host -DefaultColor gray -String " Ensure that the report with <c='white'>datasetId = $Source_DatasetId</c> and <c='white'>isDatasetOwner = true</c> has already been restored."
                            Write-PSFHostColor -Level Host -DefaultColor gray -String " <c='white'>Report skipped</c>."
                            continue
                        }

                        # ===
                        # Change mapping file
                        # =

                        try{
                            foreach ($report in $DatasetReport_Mapping) {
                                if ($report.reportId -eq $Source_ReportId){
                                    
                                    # Change new dataset name
                                    $report.new_datasetName = $Target_DatasetName

                                    # Add new dataset id
                                    $report | Add-Member -MemberType NoteProperty -Name "new_datasetId" -Value $Target_DatasetId -Force

                                }
                            }

                            # Save changes to JSON
                            $DatasetReport_Mapping | ConvertTo-Json | Out-File -FilePath $Path_ReportDatasetMapping -ErrorAction Stop
                            
                        } catch{
                            throw "Error while changing report-dataset mapping file `"$FileName_ReportDatasetMapping`". `n$_"
                        }

                        # Import report
                        Import-BsgPbiReport -Target_WorkspaceId $Target_WorkspaceId -Source_ReportId $Source_ReportId -Path_Workspace $Path_Workspace -ProcessTenantLevelReport $true                       
                            
                    }

                }

            } catch{
                throw "Error while checking report-dataset mapping file `"$FileName_ReportDatasetMapping`". `n$_"
            }

        }

    } catch{
        Write-Host
        Stop-PSFFunction -Message "Could not import tenant level reports." -EnableException $False -ErrorRecord $_

    }

}