データ モデルのカスタマイズを分析するためのアプリケーション ライフサイクル管理
適用対象: Dynamics 365 Customer Service
この記事では、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 で実行するタスクを表します。
レポートの構成を移行する
Dynamics 365 に追加されたレポートは Dataverse エンティティに保存されます。
次のエンティティ/テーブルは、カスタマイズされたレポート情報を保存するために使用さます。
msdyn_dataanalyticsworkspaces
には、初期セットアップ中に履歴/リアルタイム分析用に構成されたワークスペース情報があります。msdyn_dataanalyticsreport
はサイトマップに追加されたカスタマイズされたレポートを保存します。msdyn_reportid
Power 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><filter type = 'and'>
<condition attribute = 'msdyn_datainsightsandanalyticsfeatureid' operator = 'eq' value = '<<Feature ID of the model customization>> '/>
<condition attribute = 'msdyn_displayname' operator = 'eq' value = '<<custom report name>>'/>
</filter></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 の組み込み分析機能の詳細を学習する際に役立ちます。
- リアルタイム分析ダッシュボードの概要
- Customer Service 用オムニチャネルでの統合ルーティングの履歴分析
- 顧客サービスにおける履歴およびリアルタイム分析レポートのモデル カスタマイズ
- Microsoft Power Platform Build Tools for Azure DevOps
- 構成データを組織間で移動する
- Microsoft Power Platform CLI データ コマンド グループ
- Power BI 展開パイプラインの概要
- Power BI 組み込み分析と自動化のための REST APII