diff --git a/docs-mslearn/toolkit/changelog.md b/docs-mslearn/toolkit/changelog.md index 026e891ee..c0d1bde11 100644 --- a/docs-mslearn/toolkit/changelog.md +++ b/docs-mslearn/toolkit/changelog.md @@ -49,6 +49,8 @@ _Released January 2026_ - **Added** - Created comprehensive [Data Lake Storage connectivity options](data-lake-storage-connectivity.md) documentation covering tools and services beyond Power BI including Azure Data Explorer, Microsoft Fabric, Azure Synapse Analytics, Azure Databricks, and custom applications. - Enhanced troubleshooting guidance for [Data Explorer ingestion errors](help/errors.md#dataexploreringestionfailed) with detailed steps for diagnosing and resolving the common SEM0080 "Ingestion Failed" semantic error, including schema mismatch detection, ingestion mapping verification, and diagnostic query examples. +- **Fixed** + - Fixed tag expansion in Power BI reports when tag names contain special characters like colons. ### [FinOps hubs](hubs/finops-hubs-overview.md) v13 @@ -88,6 +90,7 @@ _Released January 2026_ - **Added** - Added export requirements sections to all Power BI report documentation pages to clarify which Cost Management exports are needed for each report. - Added Azure Resource Graph as an explicit requirement for governance and workload optimization reports. + - Added `CapacityReservationId` and `CapacityReservationStatus` columns in storage-based Power BI reports ([#1839](https://github.com/microsoft/finops-toolkit/issues/1839)). - **Fixed** - Fixed tag expansion in Power BI reports when tag names contain special characters like colons. - Fixed unattached disks count in the workload optimization report to show only truly unattached disks instead of all disks. The card visual now filters disks where (managedBy is empty and diskState is not ActiveSAS) or (diskState is Unattached and not ActiveSAS) ([#1896](https://github.com/microsoft/finops-toolkit/issues/1896)). diff --git a/src/power-bi/queries/ftk_NormalizeSchema.pq b/src/power-bi/queries/ftk_NormalizeSchema.pq index 991ab8cba..6ef238830 100644 --- a/src/power-bi/queries/ftk_NormalizeSchema.pq +++ b/src/power-bi/queries/ftk_NormalizeSchema.pq @@ -287,7 +287,9 @@ let BillingAccountType = Table.AddColumn(BillingAccountName, "BillingAccountType", each if [x_AccountType] = "MCA" then "Billing Profile" else if [x_AccountType] = "EA" then "Billing Account" else "Subscription"), BillingPeriodEnd = _swapCol(BillingAccountType, "tmp_BillingPeriodEnd", "BillingPeriodEnd", each if _isMissing("tmp_BillingPeriodEnd") then Date.StartOfMonth(Date.AddDays([ChargePeriodStart], 31)) else Date.AddDays([tmp_BillingPeriodEnd], 1), type date), BillingPeriodStart = _swapCol(BillingPeriodEnd, "tmp_BillingPeriodStart", "BillingPeriodStart", each if _isBlank([tmp_BillingPeriodStart]) then Date.StartOfMonth([ChargePeriodStart]) else [tmp_BillingPeriodStart], type date), - ChargeCategory = Table.AddColumn(BillingPeriodStart, "ChargeCategory", each if _isBlank([tmp_ChargeType]) then "Usage" else if [tmp_ChargeType] = "Usage" or [tmp_ChargeType] = "Purchase" or [tmp_ChargeType] = "Tax" then [tmp_ChargeType] else if Text.StartsWith([tmp_ChargeType], "Unused") then "Usage" else if [tmp_ChargeType] = "Refund" then "Purchase" else "Adjustment"), + CapacityReservationId = Table.AddColumn(BillingPeriodStart, "CapacityReservationId", each if _isNotBlank([x_CapacityCommitmentId]) then [x_CapacityCommitmentId] else null), + CapacityReservationStatus = Table.AddColumn(CapacityReservationId, "CapacityReservationStatus", each if _isBlank([CapacityReservationId]) then null else if _isNotBlank([x_ResourceType]) and Text.Lower([x_ResourceType]) = "microsoft.compute/capacityreservationgroups/capacityreservations" then "Unused" else "Used"), + ChargeCategory = Table.AddColumn(CapacityReservationStatus, "ChargeCategory", each if _isBlank([tmp_ChargeType]) then "Usage" else if [tmp_ChargeType] = "Usage" or [tmp_ChargeType] = "Purchase" or [tmp_ChargeType] = "Tax" then [tmp_ChargeType] else if Text.StartsWith([tmp_ChargeType], "Unused") then "Usage" else if [tmp_ChargeType] = "Refund" then "Purchase" else "Adjustment"), ChargeClass = Table.AddColumn(ChargeCategory, "ChargeClass", each if [tmp_ChargeType] = "Refund" then "Correction" else null), ChargeDescription = Table.AddColumn(ChargeClass, "ChargeDescription", each [x_SkuDescription]), // TODO: PricingQuantity,SkuId,SkuPriceId 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 904fd4447..747a28b53 100644 --- a/src/power-bi/storage/Shared.Dataset/definition/tables/Costs.tmdl +++ b/src/power-bi/storage/Shared.Dataset/definition/tables/Costs.tmdl @@ -796,6 +796,22 @@ table Costs annotation PBI_FormatHint = {"isCustom":true} + column CapacityReservationId + dataType: string + lineageTag: 7a3e4b1c-6f8e-4d9a-b5c1-3e2f4a7b8c9d + summarizeBy: none + sourceColumn: CapacityReservationId + + annotation SummarizationSetBy = Automatic + + column CapacityReservationStatus + dataType: string + lineageTag: 8b4f5c2d-7g9f-5e0b-c6d2-4f3e5b8a9c0e + summarizeBy: none + sourceColumn: CapacityReservationStatus + + annotation SummarizationSetBy = Automatic + column ChargeCategory dataType: string lineageTag: 669cea79-1e27-46c1-a88f-0ad859cee094