From d97e4842b2fc1da20c3b03ea5360e423a7a52cfa Mon Sep 17 00:00:00 2001 From: Michael Flanakin Date: Wed, 15 Jul 2026 14:15:31 -0700 Subject: [PATCH 1/2] feat(power-bi): update Power BI reports to FOCUS 1.4 (v1_4 schema) Repoint KQL reports from Costs_v1_2/Recommendations_v1_2 to the new v1_4 hub functions and reconcile the Costs model with the FOCUS 1.4 output schema (22 new columns). Retain the deprecated ProviderName and PublisherName model columns by deriving them from HostProviderName and ServiceProviderName so existing visuals and custom reports keep working. Storage reports gain a Has14 normalization branch that backfills new FOCUS 1.3/1.4 columns for older exports and the deprecated provider columns for 1.4 exports, plus FOCUS 1.4/1.2 source-version detection. Update hubs compatibility docs and changelog. Co-Authored-By: Claude Fable 5 --- docs-mslearn/toolkit/changelog.md | 10 + docs-mslearn/toolkit/hubs/compatibility.md | 5 +- .../definition/tables/Costs.tmdl | 214 +++++++++++++++++- .../tables/ReservationRecommendations.tmdl | 2 +- .../definition/expressions.tmdl | 6 +- .../definition/tables/Costs.tmdl | 204 ++++++++++++++++- 6 files changed, 435 insertions(+), 6 deletions(-) diff --git a/docs-mslearn/toolkit/changelog.md b/docs-mslearn/toolkit/changelog.md index e260b4f04..a2b6879a0 100644 --- a/docs-mslearn/toolkit/changelog.md +++ b/docs-mslearn/toolkit/changelog.md @@ -54,6 +54,16 @@ The following section lists features and enhancements that are currently in deve - **Removed** - Removed deprecated `ProviderName` and `PublisherName` columns from the `v1_4` schema in favor of the FOCUS 1.3 replacements, `HostProviderName` and `ServiceProviderName`. The `v1_0` and `v1_2` functions still return both columns by down-converting from the new columns, and raw tables keep them for back compat. +### Power BI reports v15.0.0 + +- **Added** + - Added the new FOCUS 1.3 and 1.4 columns to the Costs table in KQL and storage reports: `AllocatedMethodDetails`, `AllocatedMethodId`, `AllocatedResourceId`, `AllocatedResourceName`, `AllocatedTags`, `CommitmentProgramEligibilityDetails`, `ContractApplied`, the 12 `ContractCommitment*` columns, `HostProviderName`, `InvoiceDetailId`, and `ServiceProviderName` ([#2120](https://github.com/microsoft/finops-toolkit/issues/2120)). +- **Changed** + - Updated KQL reports to use the FinOps hubs `v1_4` schema (`Costs_v1_4()` and `Recommendations_v1_4()`) for FOCUS 1.4 ([#2120](https://github.com/microsoft/finops-toolkit/issues/2120)). + - Updated storage reports to align FOCUS 1.0-1.4 exports to the FOCUS 1.4 schema and to detect FOCUS 1.4 data when identifying the source version. +- **Deprecated** + - Deprecated the `ProviderName` and `PublisherName` columns in the Costs table. Both columns are retained for backward compatibility and are populated from the FOCUS 1.3 replacements, `HostProviderName` and `ServiceProviderName`, when not available in the source data. + ### Bicep Registry module pending updates - Cost Management export modules for subscriptions and resource groups. diff --git a/docs-mslearn/toolkit/hubs/compatibility.md b/docs-mslearn/toolkit/hubs/compatibility.md index dadbf0e04..e563cfc68 100644 --- a/docs-mslearn/toolkit/hubs/compatibility.md +++ b/docs-mslearn/toolkit/hubs/compatibility.md @@ -3,7 +3,7 @@ title: Compatibility guide description: Learn which Power BI report versions are compatible with each FinOps hubs version to ensure seamless upgrades and data integrity. author: flanakin ms.author: micflan -ms.date: 04/01/2026 +ms.date: 07/15/2026 ms.topic: concept-article ms.service: finops ms.subservice: finops-toolkit @@ -33,7 +33,8 @@ The Power BI version refers to the Power BI reports made available within that s | Cost Management exports | FinOps hubs | Storage path | Power BI | Notes | | ----------------------------------------- | ----------- | ---------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| FOCUS costs, prices, reservation datasets | 12+ | {dataset}/{yyyy}/{MM}/{scope} | 12+² | KQL reports use the FinOps hubs v1_2 schema for FOCUS 1.2 | +| FOCUS costs, prices, reservation datasets | 15+ | {dataset}/{yyyy}/{MM}/{scope} | 15+² | KQL reports use the FinOps hubs v1_4 schema for FOCUS 1.4 | +| FOCUS costs, prices, reservation datasets | 12+ | {dataset}/{yyyy}/{MM}/{scope} | 12-14² | KQL reports use the FinOps hubs v1_2 schema for FOCUS 1.2 | | FOCUS costs, prices, reservation datasets | 0.8+ | {dataset}/{yyyy}/{MM}/{scope} | 0.7-0.11² | | | FOCUS costs, prices, reservation datasets | 0.7 | {dataset}/{yyyy}/{MM}/{scope}¹ | 0.7+² | Storage path updated to new dataset names that support joining multiple related datasets together | | FOCUS costs, prices, reservation datasets | 0.6 | {export-type}/{yyyy}/{MM}/{scope} | 0.6+ | Reservation recommendations pulled from hub storage | diff --git a/src/power-bi/kql/Shared.Dataset/definition/tables/Costs.tmdl b/src/power-bi/kql/Shared.Dataset/definition/tables/Costs.tmdl index cb665ee6f..893bea1bf 100644 --- a/src/power-bi/kql/Shared.Dataset/definition/tables/Costs.tmdl +++ b/src/power-bi/kql/Shared.Dataset/definition/tables/Costs.tmdl @@ -1848,6 +1848,210 @@ table Costs annotation SummarizationSetBy = Automatic + column AllocatedMethodDetails + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 55113e62-acbf-4acb-b0e1-41854cefeadc + summarizeBy: none + sourceColumn: AllocatedMethodDetails + + annotation SummarizationSetBy = Automatic + + column AllocatedMethodId + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 8256f9c9-1499-49ff-9d84-e528dc8dd3b5 + summarizeBy: none + sourceColumn: AllocatedMethodId + + annotation SummarizationSetBy = Automatic + + column AllocatedResourceId + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: ce5ffa08-514d-41c4-b3f9-ad22054d5b6e + summarizeBy: none + sourceColumn: AllocatedResourceId + + annotation SummarizationSetBy = Automatic + + column AllocatedResourceName + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 505ecaae-5603-46a4-9c7d-c2a93f84350f + summarizeBy: none + sourceColumn: AllocatedResourceName + + annotation SummarizationSetBy = Automatic + + column AllocatedTags + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 0c09f14d-e1b7-48a3-a51d-dbe9c65c7a4e + summarizeBy: none + sourceColumn: AllocatedTags + + annotation SummarizationSetBy = Automatic + + column CommitmentProgramEligibilityDetails + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: e0a419cd-689a-4667-96e7-848817cf3140 + summarizeBy: none + sourceColumn: CommitmentProgramEligibilityDetails + + annotation SummarizationSetBy = Automatic + + column ContractApplied + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 8e7d2334-99f6-4b4f-8683-2c3c9a535719 + summarizeBy: none + sourceColumn: ContractApplied + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentBenefitCategory + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: c1b085bd-8b41-4947-adf8-3f7b295f7b02 + summarizeBy: none + sourceColumn: ContractCommitmentBenefitCategory + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentCreated + dataType: dateTime + formatString: General Date + sourceProviderType: datetimeoffset + lineageTag: b881035d-76ff-43bc-83ab-72f7c9ff9912 + summarizeBy: none + sourceColumn: ContractCommitmentCreated + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentDiscountPercentage + dataType: double + sourceProviderType: decimal + lineageTag: 3acab673-4552-4996-aa7e-8b04a05f8ea3 + summarizeBy: none + sourceColumn: ContractCommitmentDiscountPercentage + + annotation SummarizationSetBy = Automatic + + annotation PBI_FormatHint = {"isGeneralNumber":true} + + column ContractCommitmentDurationType + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 495b8505-e715-47fc-a27e-4834d2a1e3f6 + summarizeBy: none + sourceColumn: ContractCommitmentDurationType + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentFulfillmentInterval + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 0b54f930-ae2b-4efd-8422-fa6e56971946 + summarizeBy: none + sourceColumn: ContractCommitmentFulfillmentInterval + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentLastUpdated + dataType: dateTime + formatString: General Date + sourceProviderType: datetimeoffset + lineageTag: 58258b25-f8e3-45f8-862d-86e433720454 + summarizeBy: none + sourceColumn: ContractCommitmentLastUpdated + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentLifecycleStatus + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: b09906a8-b301-4cdb-920a-dd91fcb40e1b + summarizeBy: none + sourceColumn: ContractCommitmentLifecycleStatus + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentModel + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: f79edd03-14c9-4a89-a877-fe9bcf3e6c8a + summarizeBy: none + sourceColumn: ContractCommitmentModel + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentOfferCategory + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: d2bc0b21-e86c-4ff2-9085-bb4fdd816e6b + summarizeBy: none + sourceColumn: ContractCommitmentOfferCategory + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentPaymentInterval + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 4e174c85-2d67-4a8a-a8fb-63b1bdd9de4b + summarizeBy: none + sourceColumn: ContractCommitmentPaymentInterval + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentPaymentModel + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 9ec28b52-c4c7-499e-abc8-62254bd7a94d + summarizeBy: none + sourceColumn: ContractCommitmentPaymentModel + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentPaymentUpfrontPercentage + dataType: double + sourceProviderType: decimal + lineageTag: a7a0be0e-0f44-4c34-b313-0ae2a2e692a0 + summarizeBy: none + sourceColumn: ContractCommitmentPaymentUpfrontPercentage + + annotation SummarizationSetBy = Automatic + + annotation PBI_FormatHint = {"isGeneralNumber":true} + + column HostProviderName + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: 5b7f174f-09d5-4c7b-9f51-4486012cf9d3 + summarizeBy: none + sourceColumn: HostProviderName + + annotation SummarizationSetBy = Automatic + + column InvoiceDetailId + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: f338213d-a52c-4fbd-8865-8f9e2ced5907 + summarizeBy: none + sourceColumn: InvoiceDetailId + + annotation SummarizationSetBy = Automatic + + column ServiceProviderName + dataType: string + sourceProviderType: nvarchar(max) + lineageTag: d3d89090-75d9-4695-9df3-1758ab163a73 + summarizeBy: none + sourceColumn: ServiceProviderName + + annotation SummarizationSetBy = Automatic + hierarchy 'Service Hierarchy' lineageTag: 039a7b6d-f19d-4a79-91b3-a05fbc778704 @@ -1886,7 +2090,11 @@ table Costs Source = AzureDataExplorer.Contents(#"Cluster URL", "Hub", " - Costs_v1_2 + Costs_v1_4 + // + // Deprecated columns -- Removed from FOCUS in 1.3; retained for backward compatibility with existing visuals and custom reports + | extend ProviderName = HostProviderName + | extend PublisherName = ServiceProviderName // // Apply summarization settings | where ChargePeriodStart >= monthsago(" & lookback & ") @@ -1952,6 +2160,10 @@ table Costs ) ) else "") & " // + | extend AllocatedMethodDetails = tostring(AllocatedMethodDetails) + | extend AllocatedTags = tostring(AllocatedTags) + | extend CommitmentProgramEligibilityDetails = tostring(CommitmentProgramEligibilityDetails) + | extend ContractApplied = tostring(ContractApplied) | extend SkuPriceDetails = tostring(SkuPriceDetails) | extend Tags = tostring(Tags) | extend x_SkuDetails = tostring(x_SkuDetails) diff --git a/src/power-bi/kql/Shared.Dataset/definition/tables/ReservationRecommendations.tmdl b/src/power-bi/kql/Shared.Dataset/definition/tables/ReservationRecommendations.tmdl index 9cdde158b..ba836269c 100644 --- a/src/power-bi/kql/Shared.Dataset/definition/tables/ReservationRecommendations.tmdl +++ b/src/power-bi/kql/Shared.Dataset/definition/tables/ReservationRecommendations.tmdl @@ -226,7 +226,7 @@ table ReservationRecommendations let Source = AzureDataExplorer.Contents(#"Cluster URL", "Hub", " - Recommendations_v1_2 + Recommendations_v1_4 | where x_SourceProvider == 'Microsoft' and x_SourceType == 'ReservationRecommendations' | extend RegionId = tostring(x_RecommendationDetails.RegionId) | extend RegionName = tostring(x_RecommendationDetails.RegionName) diff --git a/src/power-bi/storage/Shared.Dataset/definition/expressions.tmdl b/src/power-bi/storage/Shared.Dataset/definition/expressions.tmdl index 69c6f549c..d071fabce 100644 --- a/src/power-bi/storage/Shared.Dataset/definition/expressions.tmdl +++ b/src/power-bi/storage/Shared.Dataset/definition/expressions.tmdl @@ -326,7 +326,11 @@ expression ftk_Storage = ``` "x_SourceType", each data), "x_SourceVersion", // TODO: Extract from the manifest - each if data = "focuscost" then (if Table.HasColumns(FilterRowsByDate, {"ChargeSubcategory"}) and [ChargeSubcategory] <> null then "1.0-preview(v1)" else "1.0") + each if data = "focuscost" then ( + if Table.HasColumns(FilterRowsByDate, {"ServiceProviderName"}) and [ServiceProviderName] <> null then "1.4" + else if Table.HasColumns(FilterRowsByDate, {"ChargeSubcategory"}) and [ChargeSubcategory] <> null then "1.0-preview(v1)" + else if Table.HasColumns(FilterRowsByDate, {"InvoiceId"}) and [InvoiceId] <> null then "1.2" + else "1.0") else if data = "pricesheet" then "2023-05-01" else if data = "reservationdetails" then "2023-03-01" else if data = "reservationtransactions" then "2023-05-01" diff --git a/src/power-bi/storage/Shared.Dataset/definition/tables/Costs.tmdl b/src/power-bi/storage/Shared.Dataset/definition/tables/Costs.tmdl index 8136f08c1..5bf52bc2d 100644 --- a/src/power-bi/storage/Shared.Dataset/definition/tables/Costs.tmdl +++ b/src/power-bi/storage/Shared.Dataset/definition/tables/Costs.tmdl @@ -1390,6 +1390,188 @@ table Costs annotation SummarizationSetBy = Automatic + column AllocatedMethodDetails + dataType: string + lineageTag: 9402c4c8-c505-464e-931e-751668d3ba83 + summarizeBy: none + sourceColumn: AllocatedMethodDetails + + annotation SummarizationSetBy = Automatic + + column AllocatedMethodId + dataType: string + lineageTag: 26e34a2c-3d0d-47cf-a116-4c861bc62286 + summarizeBy: none + sourceColumn: AllocatedMethodId + + annotation SummarizationSetBy = Automatic + + column AllocatedResourceId + dataType: string + lineageTag: 55d64b52-5560-47f1-9f2b-eb5a04ae0a2e + summarizeBy: none + sourceColumn: AllocatedResourceId + + annotation SummarizationSetBy = Automatic + + column AllocatedResourceName + dataType: string + lineageTag: c9863af0-538a-44cd-b03f-53a4004b9a4e + summarizeBy: none + sourceColumn: AllocatedResourceName + + annotation SummarizationSetBy = Automatic + + column AllocatedTags + dataType: string + lineageTag: 1e7ec40d-2d57-4c62-ab98-a4c9eb577ada + summarizeBy: none + sourceColumn: AllocatedTags + + annotation SummarizationSetBy = Automatic + + column CommitmentProgramEligibilityDetails + dataType: string + lineageTag: 52986e67-2e71-4413-bca2-1e37333d5908 + summarizeBy: none + sourceColumn: CommitmentProgramEligibilityDetails + + annotation SummarizationSetBy = Automatic + + column ContractApplied + dataType: string + lineageTag: f12cd4d2-2ede-4553-9814-57fa0757112c + summarizeBy: none + sourceColumn: ContractApplied + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentBenefitCategory + dataType: string + lineageTag: ae3d4177-9814-4879-9bb7-9c84f0b127d2 + summarizeBy: none + sourceColumn: ContractCommitmentBenefitCategory + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentCreated + dataType: dateTime + formatString: General Date + lineageTag: 6aaa2b8d-7950-4b5f-8e7d-fdbff15a60e2 + summarizeBy: none + sourceColumn: ContractCommitmentCreated + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentDiscountPercentage + dataType: double + lineageTag: 251a216b-4954-4f84-a972-2c9bd9593573 + summarizeBy: none + sourceColumn: ContractCommitmentDiscountPercentage + + annotation SummarizationSetBy = Automatic + + annotation PBI_FormatHint = {"isGeneralNumber":true} + + column ContractCommitmentDurationType + dataType: string + lineageTag: f246de01-ff20-4373-b3b5-58e8c6705543 + summarizeBy: none + sourceColumn: ContractCommitmentDurationType + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentFulfillmentInterval + dataType: string + lineageTag: 08022da8-18a2-4d1a-884f-a03615f90b29 + summarizeBy: none + sourceColumn: ContractCommitmentFulfillmentInterval + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentLastUpdated + dataType: dateTime + formatString: General Date + lineageTag: ed6b0f99-e25f-4861-885f-b1becb81e17d + summarizeBy: none + sourceColumn: ContractCommitmentLastUpdated + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentLifecycleStatus + dataType: string + lineageTag: 1abe7929-75b4-4ccd-abdc-7980ea71132a + summarizeBy: none + sourceColumn: ContractCommitmentLifecycleStatus + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentModel + dataType: string + lineageTag: abb04100-9b6a-491f-90af-9a4d06b760e0 + summarizeBy: none + sourceColumn: ContractCommitmentModel + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentOfferCategory + dataType: string + lineageTag: 94666530-e96d-47b0-8af0-6472b3f97e2b + summarizeBy: none + sourceColumn: ContractCommitmentOfferCategory + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentPaymentInterval + dataType: string + lineageTag: 5850c014-27a3-4b6f-8499-4263ac860da4 + summarizeBy: none + sourceColumn: ContractCommitmentPaymentInterval + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentPaymentModel + dataType: string + lineageTag: 0f9d97a4-b773-47b8-8190-b25d9c4545c8 + summarizeBy: none + sourceColumn: ContractCommitmentPaymentModel + + annotation SummarizationSetBy = Automatic + + column ContractCommitmentPaymentUpfrontPercentage + dataType: double + lineageTag: 0e58352c-4239-4152-9e5d-4296d4fc3e1c + summarizeBy: none + sourceColumn: ContractCommitmentPaymentUpfrontPercentage + + annotation SummarizationSetBy = Automatic + + annotation PBI_FormatHint = {"isGeneralNumber":true} + + column HostProviderName + dataType: string + lineageTag: 4ed42b42-c9bc-4566-b586-50b914d500d6 + summarizeBy: none + sourceColumn: HostProviderName + + annotation SummarizationSetBy = Automatic + + column InvoiceDetailId + dataType: string + lineageTag: 5d3f426f-21d9-4e8b-bd21-187dc5f16dbb + summarizeBy: none + sourceColumn: InvoiceDetailId + + annotation SummarizationSetBy = Automatic + + column ServiceProviderName + dataType: string + lineageTag: 357cda7a-59a0-4992-aa90-39422f7a6764 + summarizeBy: none + sourceColumn: ServiceProviderName + + annotation SummarizationSetBy = Automatic + hierarchy 'Service Hierarchy' lineageTag: 039a7b6d-f19d-4a79-91b3-a05fbc778704 @@ -1432,6 +1614,7 @@ table Costs HasPreview = Table.HasColumns(RawData, {"ChargeSubcategory"}), Has10 = Table.HasColumns(RawData, {"ChargeClass"}), Has12 = Table.HasColumns(RawData, {"InvoiceId"}), + Has14 = Table.HasColumns(RawData, {"ServiceProviderName"}), HandlePeview = if HasPreview = false then RawData else if PerformDeprecatedOptimizations = false then error "LegacyFocusVersion: Please enable the 'Perform Extra Query Optimizations' parameter" else ( @@ -1477,11 +1660,26 @@ table Costs null, each [PricingCurrency], Replacer.ReplaceValue, {"x_PricingCurrency"}), null, each [SkuMeter], Replacer.ReplaceValue, {"x_SkuMeterName"}), + // Handle columns added in FOCUS 1.3/1.4 gracefully -- Create missing columns so all FOCUS versions expose the same schema + Ensure14Cols = List.Accumulate( + {"AllocatedMethodDetails", "AllocatedMethodId", "AllocatedResourceId", "AllocatedResourceName", "AllocatedTags", "CommitmentProgramEligibilityDetails", "ContractApplied", "ContractCommitmentBenefitCategory", "ContractCommitmentCreated", "ContractCommitmentDiscountPercentage", "ContractCommitmentDurationType", "ContractCommitmentFulfillmentInterval", "ContractCommitmentLastUpdated", "ContractCommitmentLifecycleStatus", "ContractCommitmentModel", "ContractCommitmentOfferCategory", "ContractCommitmentPaymentInterval", "ContractCommitmentPaymentModel", "ContractCommitmentPaymentUpfrontPercentage", "HostProviderName", "InvoiceDetailId", "ServiceProviderName", "ProviderName", "PublisherName"}, + Align12, + (t, col) => if Table.HasColumns(t, col) then t else Table.AddColumn(t, col, each null) + ), + // Backfill the FOCUS 1.3 provider columns from the deprecated ProviderName/PublisherName columns (removed in FOCUS 1.3) for older data + AlignNewProviders = Table.ReplaceValue(Table.ReplaceValue(Ensure14Cols, + null, each [ProviderName], Replacer.ReplaceValue, {"HostProviderName"}), + null, each if [PublisherName] <> null then [PublisherName] else [ProviderName], Replacer.ReplaceValue, {"ServiceProviderName"}), + // Backfill the deprecated ProviderName/PublisherName columns from the FOCUS 1.3 replacements for backward compatibility + Align14 = if Has14 = false then AlignNewProviders else Table.ReplaceValue(Table.ReplaceValue(AlignNewProviders, + null, each [HostProviderName], Replacer.ReplaceValue, {"ProviderName"}), + null, each [ServiceProviderName], Replacer.ReplaceValue, {"PublisherName"}), + // Fix known bugs and set data types Fixes = Table.TransformColumnTypes( Table.ReplaceValue(Table.ReplaceValue( // Create AvailabilityZone column if missing to support non-Microsoft clouds - if Table.HasColumns(Align12, {"AvailabilityZone"}) then Align12 else Table.AddColumn(Align12, "AvailabilityZone", each null), + if Table.HasColumns(Align14, {"AvailabilityZone"}) then Align14 else Table.AddColumn(Align14, "AvailabilityZone", each null), // Fix savings plan purchases -- Cost Management fix pending as of Dec 8, 2024 each [EffectiveCost], each if [ChargeCategory] = "Purchase" and [CommitmentDiscountId] <> "" and [CommitmentDiscountId] <> null then 0.0 else [EffectiveCost], Replacer.ReplaceValue, {"EffectiveCost"}), // Fix PricingCategory values -- Remove after Oct 1, 2025 @@ -1492,6 +1690,8 @@ table Costs {"BillingPeriodStart", type datetimezone}, {"ChargePeriodEnd", type datetimezone}, {"ChargePeriodStart", type datetimezone}, + {"ContractCommitmentCreated", type datetimezone}, + {"ContractCommitmentLastUpdated", type datetimezone}, {"x_BillingExchangeRateDate", type datetimezone}, {"x_ServicePeriodStart", type datetimezone}, {"x_ServicePeriodEnd", type datetimezone}, @@ -1509,6 +1709,8 @@ table Costs {"x_EffectiveUnitPrice", type number}, // Other columns {"ConsumedQuantity", type number}, + {"ContractCommitmentDiscountPercentage", type number}, + {"ContractCommitmentPaymentUpfrontPercentage", type number}, {"PricingQuantity", type number}, {"x_BillingExchangeRate", type number}, {"x_PartnerCreditRate", type number}, From 12085f61b5695fd7973c6a9ad19f56a8d503d95f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 00:23:59 +0000 Subject: [PATCH 2/2] chore: Update ms.date in docs-mslearn files --- docs-mslearn/toolkit/hubs/compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-mslearn/toolkit/hubs/compatibility.md b/docs-mslearn/toolkit/hubs/compatibility.md index e563cfc68..62d47f538 100644 --- a/docs-mslearn/toolkit/hubs/compatibility.md +++ b/docs-mslearn/toolkit/hubs/compatibility.md @@ -3,7 +3,7 @@ title: Compatibility guide description: Learn which Power BI report versions are compatible with each FinOps hubs version to ensure seamless upgrades and data integrity. author: flanakin ms.author: micflan -ms.date: 07/15/2026 +ms.date: 07/16/2026 ms.topic: concept-article ms.service: finops ms.subservice: finops-toolkit