次の方法で共有


データ モデルのカスタマイズを分析するためのアプリケーション ライフサイクル管理

適用対象: Dynamics 365 Customer Service

重要

Microsoft Copilot を搭載したクラウド コンタクト センター、Dynamics 365 Contact Center を発表します。 詳細

この記事では、Dynamics 365 Customer Service 用オムニチャネルのデータ モデルのカスタマイズに基づくカスタム レポートのアプリケーション ライフサイクル管理 (ALM) の詳細な情報を提供します。

ALM の概要

ALM は、環境全体のカスタム レポートに必要な変更を移行するが、最小限の手作業で終わらせたい場合の重要なステップです。 ALM を適切に構成すると、手動エラーを減らし、時間を節約できます。

レポートのカスタマイズについては、Power BI レポートの展開用の ALM を検討してください。 この展開は、さまざまな方法で実行できます。

  • Power BI 展開パイプラインを使用して、Power BI レポートを環境間で移動できます。 あるいは、正しいデータ ソースを指定することで Power BI レポートを手動で展開することもできます。
  • Customer Service 管理センターはモデル駆動型アプリであるため、カスタマイズしたレポートを埋め込むことができます。

Dynamics 365 の ALM には、Customer Service 管理センターでのレポートの構成が含まれます。

次の図に、ステップを示します。 白色のテキストを含む青色のボックスは、Dynamics 365 で実行するタスクを表します。 黒のテキストを含む黄色のボックスは、Power BI で実行するタスクを表します。

ALM の手順を示す図。

レポートの構成を移行する

Dynamics 365 に追加されたレポートは Dataverse エンティティに保存されます。

次のエンティティ/テーブルは、カスタマイズされたレポート情報を保存するために使用さます。

  • msdyn_dataanalyticsworkspaces には、初期セットアップ中に履歴/リアルタイム分析用に構成されたワークスペース情報があります。

  • msdyn_dataanalyticsreport はサイトマップに追加されたカスタマイズされたレポートを保存します。

    • msdyn_reportidPower BI ワークスペースのレポート ID。
    • msdyn_dataanalyticsreportid: Dynamics 365 の主キー
    • msdyn_displayname: Customer Service workspace モデル駆動型アプリのカスタマイズされたレポートに表示される表示名。
    • msdyn_name: Power BI ワークスペースのレポートの名前。
    • msdyn_workspaceid: 前の手順で構成された Power BI ワークスペースのワークスペース ID。
    • msdyn_datainsightsandanalyticsfeatureid: f2266eb4-226f-4cf1-b422-89c5f48b40cb は履歴のデータモデル カスタマイズ、および 09c168be-efe2-4f08-a986-3aab7095c863 は、リアルタイムでデータモデルをカスタマイズする機能 ID です。

サイトマップに追加されたレポートを移行するには、エンティティ/テーブルからデータを移動する必要があります。 この目的で設定移行ツールを使用できます。 この記事では サンプル スキーマ ファイルを提供します。 詳細については、構成移行ツールで環境と組織間を移動する構成データを移動 そ参照してください。

移行後、レポート参照を更新する必要があります。 つまり、レポートがホストされている Power BI ワークスペースと、ワークスペースからのレポート ID を更新する必要があります。 この記事は、参考用にサンプル PowerShell スクリプトを提供していますが、任意の言語を使用して同じ結果を実現できます。

サンプル スクリプト

このセクションには、次のサンプル スクリプトが含まれています:

サンプル スキーマ ファイル

次の XML スキーマ ファイルは、作成後に Power BI ワークスペースに配備されるカスタム レポートで構成されます。 構成移行ツールからデータをエクスポートするために使用できます。 詳細については、構成移行ツールで環境と組織間を移動する構成データを移動スキーマを作成して構成データをエクスポートする を参照してください。

<entities>
  <entity name="msdyn_dataanalyticsreport" displayname="Data Analytics Report" etc="10427" primaryidfield="msdyn_dataanalyticsreportid" primarynamefield="msdyn_name" disableplugins="false">
    <fields>
      <field displayname="Report Id" name="msdyn_reportid" type="string" customfield="true" />
      <field displayname="Data Analytics Report" name="msdyn_dataanalyticsreportid" type="guid" primaryKey="true" />
      <field displayname="Display name" name="msdyn_displayname" type="string" customfield="true" />
      <field displayname="Name" name="msdyn_name" type="string" customfield="true" />
      <field displayname="Report Display Order" name="msdyn_displayorder" type="number" customfield="true" />
      <field displayname="Report Provision Status" name="msdyn_provisionstatus" type="bool" customfield="true" />
      <field displayname="Report Page" name="msdyn_reportpage" type="string" customfield="true" />
      <field displayname="Report Group" name="msdyn_reportgroup" type="string" customfield="true" />
      <field displayname="Report Entity Name" name="msdyn_reportentityname" type="string" customfield="true" />
      <field displayname="Report Template Id" name="msdyn_reporttemplateid" type="string" customfield="true" />
      <field displayname="Dataset Id" name="msdyn_datasetid" type="string" customfield="true" />
      <field displayname="Is Enabled" name="msdyn_isenabled" type="bool" customfield="true" />
      <field displayname="Workspace Id" name="msdyn_workspaceid" type="string" customfield="true" />
      <field displayname="datainsightsandanalyticsfeatureId" name="msdyn_datainsightsandanalyticsfeatureid" type="entityreference" lookupType="msdyn_datainsightsandanalyticsfeature" customfield="true" />
      <field displayname="Analytics Checksum" name="msdyn_analyticschecksum" type="number" customfield="true" />
    </fields>
    <filter>&lt;filter type = 'and'&gt;
          &lt;condition attribute = 'msdyn_datainsightsandanalyticsfeatureid' operator = 'eq' value = '<<Feature ID of the model customization>> '/&gt;
          &lt;condition attribute = 'msdyn_displayname' operator = 'eq' value = '<<custom report name>>'/&gt; 
        &lt;/filter&gt;</filter>
  </entity>
</entities>

f2266eb4-226f-4cf1-b422-89c5f48b40cb を履歴データの機能 ID として、xxxx をリアルタイムの機能 ID として使用します。

サンプル PowerShell スクリプト

次のスクリプトは、クライアント ID シークレット認証メカニズムを使用します。 ただし、スクリプトを変更することで、任意のタイプの認証を使用できます。

このスクリプトは、Power BI Rest API を介して Power BI に接続します。 Dataverse Web API を介して Dataverse に接続します。

#Get Power BI access token
function Get-PBIAccessToken {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $TenantId,
        [Parameter(Mandatory=$true)]
        $PBIAppId,
        [Parameter(Mandatory=$true)]
        $PBIClientSecret
    )

    $authority = "https://login.microsoftonline.com/$TenantId/oauth2/token"
    $resource = "https://analysis.windows.net/powerbi/api"
    $body = @{
        "grant_type" = "client_credentials"
        "client_id" = $PBIAppId
        "client_secret" = $PBIClientSecret
        "resource" = $resource
    }
    Write-Host "Retreiving PBI Access Token"
    $tokenResponse = Invoke-RestMethod -Method Post -Uri $authority -Body $body
    
    return $tokenResponse.access_token
}
#Get Dataverse access token
function Get-DVAccessToken{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $tenantId,
        [Parameter(Mandatory=$true)]
        $clientId,
        [Parameter(Mandatory=$true)]
        $clientSecret,
        [Parameter(Mandatory=$true)]
        $dataVerseURL
    )
    $oAuthTokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"

    # OAuth Body Access Token Request
    $authBody = @{
        client_id = $clientId;
        client_secret = $ClientSecret;    
        scope = "$($dataVerseURL)/.default"    
        grant_type = 'client_credentials'
    }

    # Parameters for OAuth Access Token Request
    $authParams = @{
        URI = $oAuthTokenEndpoint
        Method = 'POST'
        ContentType = 'application/x-www-form-urlencoded'
        Body = $authBody
    }
    Write-Host "Retreiving CRM Access Token"
    # Get Access Token
    $authResponseObject = Invoke-RestMethod @authParams -ErrorAction Stop
    return $authResponseObject
}
function Get-DVWorkspaceId {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $dvAuthResponseObject,
        [Parameter(Mandatory=$true)]
        $dataVerseURL
    )

    $getDataRequestUri = 'msdyn_dataanalyticsworkspaces?$top=5&$select=msdyn_workspaceid,msdyn_name&$filter=(msdyn_name ne ''Customer Service Managed Workspace'' and _msdyn_datainsightsandanalyticsfeatureid_value eq ''f2266eb4-226f-4cf1-b422-89c5f48b40cb'')'
    # Set up web API call parameters, including a header for the access token
    $getApiCallParams = @{
        URI = "$($dataVerseURL)/api/data/v9.1/$($getDataRequestUri)"
        Headers = @{
            "Authorization" = "$($dvAuthResponseObject.token_type) $($dvAuthResponseObject.access_token)"
            "Accept" = "application/json"
            "OData-MaxVersion" = "4.0"
            "OData-Version" = "4.0"
        }
        Method = 'GET'
    }
    Write-Host "Retreiving Dataverse DCCP Workspace Id"
    # Call API to Get Response
    $getApiResponseObject = Invoke-RestMethod @getApiCallParams -ErrorAction Stop

    return $getApiResponseObject.value[0].msdyn_workspaceid
}
function Get-DVDCCPReports {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $dvAuthResponseObject,
        [Parameter(Mandatory=$true)]
        $workspaceId,
        [Parameter(Mandatory=$true)]
        $dataVerseURL
    )
    Write-Host "Retreiving DV DCCP Reports"
    $getDataRequestUri = 'msdyn_dataanalyticsreports?$select=msdyn_dataanalyticsreportid,msdyn_name,msdyn_workspaceid&$filter=(msdyn_workspaceid ne '''+$workspaceId+''' and _msdyn_datainsightsandanalyticsfeatureid_value eq ''f2266eb4-226f-4cf1-b422-89c5f48b40cb'')'
      # Set up web API call parameters, including a header for the access token
      $getApiCallParams = @{
          URI = "$($dataVerseURL)/api/data/v9.1/$($getDataRequestUri)"
          Headers = @{
              "Authorization" = "$($dvAuthResponseObject.token_type) $($dvAuthResponseObject.access_token)"
              "Accept" = "application/json"
              "OData-MaxVersion" = "4.0"
              "OData-Version" = "4.0"
          }
          Method = 'GET'
      }
      $getApiResponseObject = Invoke-RestMethod @getApiCallParams -ErrorAction Stop
      # Output
      $dvReports = $getApiResponseObject.value
    return $dvReports    
}

function Get-PBIReports {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $accessToken,
        [Parameter(Mandatory=$true)]
        $workspaceId
    )
    Write-Host "Retreiving PBI Workspace Reports"
    $headers = @{
        "Authorization" = "Bearer $accessToken"
          'Content-Type' = 'application/json'
      }
    $uri = "https://api.powerbi.com/v1.0/myorg/groups/$workspaceId/reports"
    $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
    $pbiReports = $response.value
    return $pbiReports
    
}

function Update-DVReportReferences
{
      [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $pbiAccessToken,
        [Parameter(Mandatory=$true)]
        $dvAuthResponseObject,
        [Parameter(Mandatory=$true)]
        $workspaceId,
        [Parameter(Mandatory=$true)]
        $dataVerseURL
    )
    
    $pbiReports = Get-PBIReports -accessToken $pbiAccessToken -workspaceId $workspaceId
    Write-Host $pbiReports.Count
    $dvReports = Get-DVDCCPReports -dvAuthResponseObject $dvAuthResponseObject -workspaceId $workspaceId -dataVerseURL $dataVerseURL
    Write-Host $dvReports.Count
    Write-Host "Updating DCCP report references"
    $pbiReports
    foreach ($item in $dvReports)
      {
          $item.msdyn_name          
          $report = $pbiReports.value | Where-Object {$_.name -eq $item.msdyn_name}
          if($report -ne $null)
          {
              
              Write-Host "Updating report reference for $($item.msdyn_name) with PBI $($report.id)"
              $dvReportId = $item.msdyn_dataanalyticsreportid
              $patchRequestUri = "msdyn_dataanalyticsreports($($dvReportId))"+'?$select=msdyn_workspaceid,msdyn_dataanalyticsreportid'
              $updateBody  = @{
                  'msdyn_workspaceid' = ''+$workspaceId+''
                  'msdyn_reportid' = ''+$report.id+''
              } | ConvertTo-Json
              # Set up web API call parameters, including a header for the access token
              $patchApiCallParams = @{
                  URI = "$($dataVerseURL)/api/data/v9.1/$($patchRequestUri)"
                  Headers = @{
                      "Authorization" = "$($dvAuthResponseObject.token_type) $($dvAuthResponseObject.access_token)"
                      "Accept" = "application/json"
                      "OData-MaxVersion" = "4.0"
                      "OData-Version" = "4.0"
                      "Content-Type" = "application/json; charset=utf-8"
                      "Prefer" = "return=representation"  # in order to return data
                      "If-Match" = "*" 
                  }
                  Method = 'PATCH'
                  Body = $updateBody
              }
              
              $patchApiResponseObject = Invoke-RestMethod @patchApiCallParams -ErrorAction Stop   
          }
          else
          {
              Write-Host "Corresponding PBI report not found in PBI workspace with name $($item.msdyn_name)"
          }
      }
      return $pbiReports
}

###Sample usage########
#$PBIAppId = '<<Client ID which has access to Power BI workspace>>' 
#$TenantId = '<<Tenant Id of the DV/PBI organization>>'    
#$PBIClientSecret = "<<Secret of application user PBI>>" 
#$AppId = '<<Dataverse App id>>' 
#$ClientSecret = '<<DV client Secret>>' 
#$PowerPlatformEnvironmentUrl = "<<DV URL>>" 
#$PBIAccessToken = Get-PBIAccessToken -TenantId $TenantId -PBIAppId $PBIAppId -PBIClientSecret $PBIClientSecret
#$CRMAccessToken = Get-DVAccessToken -tenantId $TenantId -dataVerseURL $PowerPlatformEnvironmentUrl -clientId $AppId -clientSecret $ClientSecret
#$workspaceId = Get-DVWorkspaceId -dvAuthResponseObject $CRMAccessToken -dataVerseURL $PowerPlatformEnvironmentUrl
#Update-DVReportReferences -pbiAccessToken $PBIAccessToken -dvAuthResponseObject $CRMAccessToken -workspaceId $workspaceId -dataVerseURL $PowerPlatformEnvironmentUrl 

サンプル Azure DevOps YAML パイプライン

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
trigger:
- main
pool:
  vmImage: windows-latest
steps:
- task: CopyFiles@2
  inputs:
    Contents: '**'
    TargetFolder: '$(Build.ArtifactStagingDirectory)'
    CleanTargetFolder: true
    ignoreMakeDirErrors: true
  displayName: 'Copy files from Repo'
- task: PowerPlatformToolInstaller@2
  inputs:
    DefaultVersion: true
- task: PowerPlatformExportData@2
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: 'Optimize25CRM'
    Environment: '$(BuildTools.EnvironmentUrl)'
    SchemaFile: '$(Build.ArtifactStagingDirectory)\source\Optimize25Schema\schema_sample.xml'
    DataFile: 'data.zip'
  displayName: 'Export reports sitemap data from Source'
- task: PowerPlatformImportData@2
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: 'Optimize25POC'
    Environment: '$(BuildTools.EnvironmentUrl)'
    DataFile: 'data.zip'
  displayName: 'Import reports sitemap data to Target' 
- task: PowerShell@2  
  inputs:
    targetType: 'inline'
    script: |
      $ScriptContent = Get-Content "$(Build.ArtifactStagingDirectory)\source\automation\PipelineScript.ps1" -Raw
      Invoke-Expression $ScriptContent      
      # Write your PowerShell commands here.
      Write-Host "Assigning connection variables"   
      $PBIAppId = '$(PBIClientId)' 
      $PBIClientSecret = '$(PBIClientSecret)'
      $TenantId = '$(TenantId)'    
      $AppId = '$(CRMClientId)' 
      $ClientSecret = '$(CRMClientSecret)'  
      $PowerPlatformEnvironmentUrl = '$(GetConnectionVar.PowerPlatformEnvironmentUrl)' 
      $PBIAccessToken = Get-PBIAccessToken -TenantId $TenantId -PBIAppId $PBIAppId -PBIClientSecret $PBIClientSecret
      $CRMAccessToken = Get-DVAccessToken -tenantId $TenantId -dataVerseURL $PowerPlatformEnvironmentUrl -clientId $AppId -clientSecret $ClientSecret
      $featureId = 'f2266eb4-226f-4cf1-b422-89c5f48b40cb'      
      $workspaceId = Get-DVWorkspaceId -dvAuthResponseObject $CRMAccessToken -dataVerseURL $PowerPlatformEnvironmentUrl -featureId $featureId
      Write-Host $workspaceId
      Update-DVReportReferences -pbiAccessToken $PBIAccessToken -dvAuthResponseObject $CRMAccessToken -workspaceId $workspaceId -dataVerseURL $PowerPlatformEnvironmentUrl  -featureId $featureId

次のリソースは、オムニチャネル用 Dynamics 365 Customer Service の組み込み分析機能の詳細を学習する際に役立ちます。

次のステップ