public static string MakePage(string targetRegion, RegionInfo regionInfo, ServiceParityResult parityResult, CostEstimationResult costEstimationResult) { StringBuilder sb = new StringBuilder(); using (HtmlTextWriter w = new HtmlTextWriter(new StringWriter(sb, CultureInfo.CurrentCulture))) { #region Html w.AddAttribute("lang", "en"); w.RenderBeginTag(HtmlTextWriterTag.Html); MakeHead(w); MakeBody(w, targetRegion, regionInfo, parityResult, costEstimationResult); w.RenderEndTag(); #endregion Html } string html = sb.ToString(); return(html); }
public async Task <string> CreateReportAsync( ServiceParityResult parityResult, CostEstimationResult costEstimationResult) { var targetRegion = costEstimationResult.TargetRegion; var regionInfo = await GetRegionInfoAsync(targetRegion); // Create a MigraDoc document and initialize the page setting var documentInfo = new DocumentInfo(); // Introduction Section var introSection = documentInfo.CreateIntroSection(); // Migration Summary Section CreateMigrationSummarySection( ref documentInfo, regionInfo, costEstimationResult, parityResult); // Service Parity Result CreateAppendixServiceParityResultSection( ref documentInfo, parityResult, costEstimationResult); // TODO: extract common parameters for creating section var needCostEstimation = !costEstimationResult.Details.All(d => d.EstimatedCost == null) || costEstimationResult.HasError; if (needCostEstimation) { // Cost Estimation Section CreateCostEstimationSection( ref documentInfo, regionInfo, costEstimationResult); } // Appendix Full Resource List CreateAppendixResouceListSection( ref documentInfo, regionInfo, costEstimationResult); // Conclusion Section documentInfo.CreateConclusionSection(); // Making TOC AppendTOCToIntroductionSection( ref introSection, costEstimationResult.SubscriptionName, needCostEstimation); return(documentInfo.MakePDF()); }
private static void MakeAssessmentSummary(HtmlTextWriter w, RegionInfo regionInfo, CostEstimationResult costEstimationResult, ServiceParityResult serviceParityResult) { MakeHeader(w, "AssessmentSummary for " + costEstimationResult.SubscriptionName, "AssessmentSummary"); MakeParagraph(w, "Based on user selection and configuration, here is summary about subscription CHN;TST;SHARED;0002:"); MakeAssessmentSummaryTable(w, regionInfo, costEstimationResult, serviceParityResult); }
private static void MakeAssessmentSummaryTable(HtmlTextWriter w, RegionInfo regionInfo, CostEstimationResult costEstimationResult, ServiceParityResult serviceParityResult) { var subscriptionName = costEstimationResult.SubscriptionName; var resourceGroupsCount = costEstimationResult.ResourceGroupsCount; var resourcesCount = costEstimationResult.ResourcesCount; #region Table w.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered"); w.RenderBeginTag(HtmlTextWriterTag.Table); #region Tbody w.RenderBeginTag(HtmlTextWriterTag.Tbody); #region Reference Environment MakeKeyValueRow(w, "Reference Environment", "Microsoft Azure"); #endregion Reference Environment #region Reference Subscription MakeKeyValueRow(w, "Reference Subscription", subscriptionName); #endregion Reference Subscription #region Target Environment MakeKeyValueRow(w, "Target Environment", regionInfo.TargetRegionName); #endregion Target Environment #region Number of Resource Group MakeKeyValueRow(w, "Number of Resource Group", resourceGroupsCount.ToString(CultureInfo.InvariantCulture)); #endregion Number of Resource Group #region Number of Resources MakeKeyValueRow(w, "Number of Resources", resourcesCount.ToString(CultureInfo.InvariantCulture)); #endregion Number of Resources #region Number of Resources Failed in Parity Rule Check/Number of All Resources var detailPassFailed = serviceParityResult.Details.Where(d => !d.Value.Pass); var resourceNotPassedCount = costEstimationResult.Details.Where(c => detailPassFailed.Any(d => d.Key == c.ResourceId)).GroupBy(g => g.ResourceId).Count(); MakeKeyValueRow(w, "Number of Resources Failed in Parity Rule Check/Number of All Resources", FormattableString.Invariant($"{resourceNotPassedCount}/{resourcesCount}")); #endregion Number of Resources Failed in Parity Rule Check/Number of All Resources #region Target Region MakeKeyValueRow(w, "Target Region", costEstimationResult.TargetRegion); #endregion Target Region w.RenderEndTag(); #endregion Tbody w.RenderEndTag(); #endregion Table }
public async Task <AssessmentReport> ProcessAsync( ServiceParityResult serviceParityResult, CostEstimationResult costEstimationResult) { //IReportGenerator reportGenerator = new PdfReportGenerator(); IReportGenerator reportGenerator = new HtmlReportGenerator(); AssessmentReport report = await reportGenerator.ProcessAsync( this.context, serviceParityResult, costEstimationResult); return(report); }
// TODO: split code file public async Task <AssessmentReport> ProcessAsync( IAssessmentContext context, ServiceParityResult serviceParityResult, CostEstimationResult costEstimationResult) { var reportFilePath = await this.CreateReportAsync( serviceParityResult, costEstimationResult); return(new AssessmentReport { ReportFilePath = reportFilePath }); }
private static void MakeServiceParity(HtmlTextWriter w, ServiceParityResult serviceParityResult, CostEstimationResult costEstimationResult) { MakeHeader(w, "Service Parity", "ServiceParity"); if (serviceParityResult.Pass) { MakeParagraph(w, "There is no service failed in the parity rule check regarding this migration & expansion"); } else { MakeParagraph(w, "Below are the summary of all services failed in the parity rule check regarding this migration & expansion:"); } MakeSeviceParityTable(w, serviceParityResult, costEstimationResult); }
private static void MakeCostEstimation(HtmlTextWriter w, RegionInfo regionInfo, CostEstimationResult costEstimationResult) { MakeHeader(w, "Cost Estimation", "CostEstimation"); if (costEstimationResult.HasError) { MakeParagraph(w, "Failed to retrieve Azure resource usage to build the cost estimation due to insufficient permission. Please check your Azure RBAC role and ensure you have any of the role below for the whole subscription: Reader, Contributor and Owner."); return; } MakeParagraph(w, @"To best help customer plan and estimate the cost in destination environment, China Cloud Migration & Expansion tool set takes customer’s source service usage of one billing cycle as a reference to perform a cost estimation for the same service usage in the destination. Below is the cost estimation summary report. Please note that the cost only reflects the services that is available in destination environment. For services that is not available in destination, N/A are marked."); MakeCostEstimationSummaryTable(w, regionInfo, costEstimationResult); MakeCostEstimationResourceGroupTable(w, regionInfo, costEstimationResult); }
public async Task <string> CreateReportAsync( ServiceParityResult parityResult, CostEstimationResult costEstimationResult) { var targetRegion = costEstimationResult.TargetRegion; var regionInfo = await GetRegionInfoAsync(targetRegion); var htmlReport = MakePage(targetRegion, regionInfo, parityResult, costEstimationResult); var filename = "CCMEAssessmentReport" + DateTime.Now.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture) + ".html"; var path = Path.Combine(Path.GetTempPath(), filename); Debug.WriteLine(FormattableString.Invariant($"Save PDF document to: {path}")); File.WriteAllText(path, htmlReport); return(path); }
private static void MakeBody(HtmlTextWriter w, string targetRegion, RegionInfo regionInfo, ServiceParityResult parityResult, CostEstimationResult costEstimationResult) { var needCostEstimation = !costEstimationResult.Details.All(d => d.EstimatedCost == null) || costEstimationResult.HasError; #region Body w.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "medium"); w.RenderBeginTag(HtmlTextWriterTag.Body); w.AddAttribute(HtmlTextWriterAttribute.Class, "container"); w.RenderBeginTag(HtmlTextWriterTag.Div); MakeIntroduction(w); MakeTableOfContent(w, costEstimationResult.SubscriptionName, needCostEstimation); MakeAssessmentSummary(w, regionInfo, costEstimationResult, parityResult); MakeServiceParity(w, parityResult, costEstimationResult); if (needCostEstimation) { MakeCostEstimation(w, regionInfo, costEstimationResult); } MakeFullResourceList(w, regionInfo, costEstimationResult); MakeConclusion(w); w.RenderEndTag(); w.RenderEndTag(); #endregion Body }
private static void MakeFullResourceList(HtmlTextWriter w, RegionInfo regionInfo, CostEstimationResult costEstimationResult) { MakeHeader(w, "Full Resource List for " + costEstimationResult.SubscriptionName, "FullResourceList"); MakeParagraph(w, @"Here is the full resource list in reference subscription related to this migration:"); var locationMap = costEstimationResult.LocationMap[costEstimationResult.SubscriptionId]; foreach (var kvp in costEstimationResult.DetailsByResourceGroup) { #region Table w.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered"); w.RenderBeginTag(HtmlTextWriterTag.Table); #region Tbody w.RenderBeginTag(HtmlTextWriterTag.Tbody); #region Resource Group Name w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Scope, "row"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Resource Group Name"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(kvp.Key); w.RenderEndTag(); w.RenderEndTag(); #endregion Resource Group Name #region Head for Name Type Location w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:30%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Name"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:55%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Type"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:15%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Location"); w.RenderEndTag(); w.RenderEndTag(); #endregion Head for Name Type Location #region Data for Name Type Location foreach (var detail in kvp.Value) { #region Row w.RenderBeginTag(HtmlTextWriterTag.Tr); #region Name w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(detail.ResourceName); w.RenderEndTag(); #endregion Name #region Type w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(detail.ResourceType); w.RenderEndTag(); #endregion Type #region Location w.RenderBeginTag(HtmlTextWriterTag.Td); if (locationMap.TryGetValue(detail.Location, out var locationDisplayName)) { w.Write(locationDisplayName); } else { w.Write(detail.Location); } w.RenderEndTag(); #endregion Location w.RenderEndTag(); #endregion Row } #endregion Data for Name Type Location w.RenderEndTag(); #endregion Tbody w.RenderEndTag(); #endregion Table } }
private static void MakeSeviceParityTable(HtmlTextWriter w, ServiceParityResult serviceParityResult, CostEstimationResult costEstimationResult) { var detailsAll = serviceParityResult.Details.Where(d => d.Value.Pass == false).ToDictionary(i => i.Key, i => i.Value); // Group up parities by resource group foreach (var resourceGroup in costEstimationResult.DetailsByResourceGroup) { // ResourceGroup.Key is the name of the group if (resourceGroup.Value.Where(r => detailsAll.Keys.Contains(r.ResourceId)).Count() != 0) { var resourceGroupName = resourceGroup.Key; MakeParagraph(w, "Resource Group: " + resourceGroupName); } // Check each resource in the group foreach (var resource in resourceGroup.Value) { if (detailsAll.Keys.Contains(resource.ResourceId) && detailsAll[resource.ResourceId].Pass == false) { #region Table w.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered"); w.RenderBeginTag(HtmlTextWriterTag.Table); #region Tbody w.RenderBeginTag(HtmlTextWriterTag.Tbody); #region Resource Name w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Scope, "row"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Resource Name"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(resource.ResourceName); w.RenderEndTag(); w.RenderEndTag(); #endregion Resource Name #region Resource Id var cutMark = "providers"; var cut = resource.ResourceId.IndexOf(cutMark, StringComparison.OrdinalIgnoreCase) + cutMark.Length; var resourceID = cut == -1 ? resource.ResourceId : resource.ResourceId.Substring(cut, resource.ResourceId.Length - cut); w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Scope, "row"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Resource Id"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(resourceID); w.RenderEndTag(); w.RenderEndTag(); #endregion Resource Id #region Head for RuleName Pass Message w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:30%"); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("RuleName"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:15%"); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Pass"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:55%"); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Message"); w.RenderEndTag(); w.RenderEndTag(); #endregion Head for RuleName Pass Message #region Data for RuleName Pass Message foreach (var ruleCheck in detailsAll[resource.ResourceId].Details.Where(d => d.Pass == false)) { w.RenderBeginTag(HtmlTextWriterTag.Tr); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(ruleCheck.Brief); w.RenderEndTag(); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write("N"); w.RenderEndTag(); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(ruleCheck.Message); w.RenderEndTag(); w.RenderEndTag(); } #endregion Data for RuleName Pass Message w.RenderEndTag(); #endregion Tbody w.RenderEndTag(); #endregion Table } } } }
private static Section CreateAppendixServiceParityResultSection( ref DocumentInfo documentInfo, ServiceParityResult serviceParityResult, CostEstimationResult costEstimationResult) { // TODO: extract to extension method // TODO: move hard code string to resource file var appendixServiceParityResultSection = documentInfo.CreateSection(); var appendixServiceParityResultTitle = appendixServiceParityResultSection.AddParagraph("Service Parity", DocumentInfo.TitleStyleName); appendixServiceParityResultTitle.AddBookmark("ServiceParity"); // All parities if (serviceParityResult.Pass) { appendixServiceParityResultSection.AddParagraph( "There is no service failed in the parity rule check regarding this migration & expansion", DocumentInfo.TableDesStyleName); } else { appendixServiceParityResultSection.AddParagraph( "Below are the summary of all services failed in the parity rule check regarding this migration & expansion: ", DocumentInfo.TableDesStyleName); var detailsAll = serviceParityResult.Details.Where(d => d.Value.Pass == false).ToDictionary(i => i.Key, i => i.Value); // Group up parities by resource group foreach (var resourceGroup in costEstimationResult.DetailsByResourceGroup) { // ResourceGroup.Key is the name of the group if (resourceGroup.Value.Where(r => detailsAll.Keys.Contains(r.ResourceId)).Count() != 0) { var resourceGroupName = resourceGroup.Key; var groupNameTxt = appendixServiceParityResultSection.AddParagraph( "Resource Group: " + resourceGroupName, DocumentInfo.TableDesStyleName); } var parityTable = DocumentInfo.CreateTable(ref appendixServiceParityResultSection); parityTable.AddColumn("4cm"); // Rule name parityTable.AddColumn("2cm"); // Pass parityTable.AddColumn("12cm"); // Message // Check each resource in the group foreach (var resource in resourceGroup.Value) { if (detailsAll.Keys.Contains(resource.ResourceId) && detailsAll[resource.ResourceId].Pass == false) { // Resource name var parityResourceName = parityTable.AddRow(); parityResourceName.Cells[0].AddParagraph("Resource Name"); parityResourceName.Cells[0].Format.Font.Bold = true; parityResourceName.Cells[1].MergeRight = 1; parityResourceName.Cells[1].Column.Width = "14.5cm"; documentInfo.AddParagraphWordWrap(parityResourceName.Cells[1], resource.ResourceName); // Resource Id var parityResourceID = parityTable.AddRow(); parityResourceID.Cells[0].AddParagraph("Resource ID"); parityResourceID.Cells[0].Format.Font.Bold = true; parityResourceID.Cells[1].MergeRight = 1; parityResourceID.Cells[1].Column.Width = "14.5cm"; var cutMark = "providers"; var cut = resource.ResourceId.IndexOf(cutMark, StringComparison.OrdinalIgnoreCase) + cutMark.Length; var resourceID = cut == -1 ? resource.ResourceId : resource.ResourceId.Substring(cut, resource.ResourceId.Length - cut); documentInfo.AddParagraphWordWrap(parityResourceID.Cells[1], resourceID); var parityProperties = parityTable.AddRow(); parityResourceID.Cells[1].Column.Width = "2cm"; parityProperties.Format.Font.Bold = true; parityProperties.Cells[0].AddParagraph("RuleName"); parityProperties.Cells[1].AddParagraph("Pass"); parityProperties.Cells[2].AddParagraph("Message"); // Check each parity result for the resource foreach (var ruleCheck in detailsAll[resource.ResourceId].Details.Where(d => d.Pass == false)) { var ruleCheckRow = parityTable.AddRow(); documentInfo.AddParagraphWordWrap(ruleCheckRow.Cells[0], ruleCheck.Brief); documentInfo.AddParagraphWordWrap(ruleCheckRow.Cells[1], "N"); documentInfo.AddParagraphWordWrap(ruleCheckRow.Cells[2], ruleCheck.Message); } } } } } return(appendixServiceParityResultSection); }
private static Section CreateMigrationSummarySection( ref DocumentInfo documentInfo, RegionInfo regionInfo, CostEstimationResult costEstimationResult, ServiceParityResult serviceParityResult) { // TODO: extract to extension method // TODO: move hard code string to resource file var subscriptionName = costEstimationResult.SubscriptionName; var resourceGroupsCount = costEstimationResult.ResourceGroupsCount; var resourcesCount = costEstimationResult.ResourcesCount; var migrationSummarySection = documentInfo.CreateSection(); var summaryTitle = migrationSummarySection.AddParagraph( "Assessment Summary for " + subscriptionName, DocumentInfo.TitleStyleName); summaryTitle.AddBookmark("MigrationSummary" + subscriptionName); migrationSummarySection.AddParagraph( "Based on user selection and configuration, here is summary about subscription " + subscriptionName + ":", DocumentInfo.TableDesStyleName); var shortSummary = DocumentInfo.CreateTable(ref migrationSummarySection); var summaryTitleColumn = shortSummary.AddColumn("8cm"); summaryTitleColumn.Format.Font = DocumentInfo.ContentFontBold.Clone(); shortSummary.AddColumn("8cm"); var shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Reference Environment"); shortSummaryRow.Cells[1].AddParagraph("Microsoft Azure"); shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Reference Subscription"); documentInfo.AddParagraphWordWrap(shortSummaryRow.Cells[1], subscriptionName); shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Target Environment"); shortSummaryRow.Cells[1].AddParagraph(regionInfo.TargetRegionName); shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Number of Resource Group"); shortSummaryRow.Cells[1].AddParagraph(resourceGroupsCount.ToString(CultureInfo.InvariantCulture)); shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Number of Resources"); shortSummaryRow.Cells[1].AddParagraph(resourcesCount.ToString(CultureInfo.InvariantCulture)); shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Number of Resources Failed in Parity Rule Check/Number of All Resources"); var detailPassFailed = serviceParityResult.Details.Where(d => !d.Value.Pass); var resourceNotPassedCount = costEstimationResult.Details.Where(c => detailPassFailed.Any(d => d.Key == c.ResourceId)).GroupBy(g => g.ResourceId).Count(); shortSummaryRow.Cells[1].AddParagraph(FormattableString.Invariant($"{resourceNotPassedCount}/{resourcesCount}")); shortSummaryRow = shortSummary.AddRow(); shortSummaryRow.Cells[0].AddParagraph("Target Region"); shortSummaryRow.Cells[1].AddParagraph(costEstimationResult.TargetRegion); return(migrationSummarySection); }
private static void MakeCostEstimationSummaryTable(HtmlTextWriter w, RegionInfo regionInfo, CostEstimationResult costEstimationResult) { #region Table w.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered"); w.RenderBeginTag(HtmlTextWriterTag.Table); #region Tbody w.RenderBeginTag(HtmlTextWriterTag.Tbody); #region Reference Environment MakeKeyValueRow(w, "Reference Environment", "Microsoft Azure"); #endregion Reference Environment #region Reference Subscription MakeKeyValueRow(w, "Reference Subscription", costEstimationResult.SubscriptionName); #endregion Reference Subscription #region Target Environment MakeKeyValueRow(w, "Target Environment", regionInfo.TargetRegionName); #endregion Target Environment #region Usage Collection Period MakeKeyValueRow(w, "Usage Collection Period", FormattableString.Invariant($"{costEstimationResult.StartTime:r} - {costEstimationResult.EndTime:r}")); #endregion Usage Collection Period #region Target Price Base MakeKeyValueRow(w, "Target Price Base", "List Price"); #endregion Target Price Base #region Currency MakeKeyValueRow(w, "Currency", regionInfo.CurrencyUnit); #endregion Currency #region Currency Format MakeKeyValueRow(w, "Currency Format", regionInfo.CurrencyCulture.EnglishName); #endregion Currency Format #region Total Cost in Period for Available Resources if (!costEstimationResult.Details.Any()) { MakeKeyValueRow(w, "Total Cost in Period for Available Resources", "N/A"); } else { decimal totalCost = 0; foreach (var kvp in costEstimationResult.DetailsByResourceGroup) { if (!kvp.Value.Any(d => d.EstimatedCost.HasValue)) { continue; } foreach (var detail in kvp.Value.Where(d => d.EstimatedCost.HasValue)) { totalCost += detail.EstimatedCost.Value; } } MakeKeyValueRow(w, "Total Cost in Period for Available Resources", ToCurrencyString(totalCost, regionInfo.CurrencySymbol)); } #endregion Total Cost in Period for Available Resources w.RenderEndTag(); #endregion Tbody w.RenderEndTag(); #endregion Table }
private static Section CreateCostEstimationSection( ref DocumentInfo documentInfo, RegionInfo regionInfo, CostEstimationResult costEstimationResult) { // TODO: extract to extension method // TODO: move hard code string to resource file. var subscriptionName = costEstimationResult.SubscriptionName; var costEstimationSection = documentInfo.CreateSection(); var costTitle = costEstimationSection.AddParagraph("Cost Estimation", DocumentInfo.TitleStyleName); costTitle.AddBookmark("CostEstimation" + subscriptionName); if (costEstimationResult.HasError) { costEstimationSection.AddParagraph( "Failed to retrieve Azure resource usage to build the cost estimation due to insufficient permission. Please check your Azure RBAC role and ensure you have any of the role below for the whole subscription: Reader, Contributor and Owner.", DocumentInfo.TableDesStyleName); return(costEstimationSection); } costEstimationSection.AddParagraph( "To best help customer plan and estimate the cost in destination environment, China Cloud Migration & Expansion tool set takes customer’s source service usage of one billing cycle as a reference to perform a cost estimation for the same service usage in the destination. Below is the cost estimation summary report. Please note that the cost only reflects the services that is available in destination environment. For services that is not available in destination, N/A are marked.", DocumentInfo.TableDesStyleName); // Make Cost Summary Table var costSummaryTalbe = DocumentInfo.CreateTable(ref costEstimationSection); var headCostSummaryColumn = costSummaryTalbe.AddColumn("8cm"); headCostSummaryColumn.Format.Font.Bold = true; costSummaryTalbe.AddColumn("8cm"); var costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Reference Environment"); costSummaryRow.Cells[1].AddParagraph("Microsoft Azure"); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Reference Subscription"); costSummaryRow.Cells[1].AddParagraph(subscriptionName); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Target Environment"); costSummaryRow.Cells[1].AddParagraph(regionInfo.TargetRegionName); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Usage Collection Period"); costSummaryRow.Cells[1].AddParagraph(FormattableString.Invariant($"{costEstimationResult.StartTime:r} - {costEstimationResult.EndTime:r}")); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Target Price Base"); costSummaryRow.Cells[1].AddParagraph("List Price"); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Currency"); costSummaryRow.Cells[1].AddParagraph(regionInfo.CurrencyUnit); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Currency Format"); costSummaryRow.Cells[1].AddParagraph(regionInfo.CurrencyCulture.EnglishName); costSummaryRow = costSummaryTalbe.AddRow(); costSummaryRow.Cells[0].AddParagraph("Total Cost in Period for Available Resources"); if (!costEstimationResult.Details.Any()) { costSummaryRow.Cells[1].AddParagraph("N/A"); } else { costEstimationSection.AddParagraph( "Please check the below cost list with price by Resource Group:", DocumentInfo.TableDesStyleName); // Resource Details decimal totalCost = 0; decimal totalOriginalCost = 0; foreach (var kvp in costEstimationResult.DetailsByResourceGroup) { if (!kvp.Value.Any(d => d.EstimatedCost.HasValue)) { continue; } var resourceGroup = kvp.Key; var costTable = DocumentInfo.CreateTable(ref costEstimationSection); costEstimationSection.AddParagraph(string.Empty); AddCostTableHeaders(ref costTable, documentInfo, resourceGroup); foreach (var detail in kvp.Value.Where(d => d.EstimatedCost.HasValue)) { AddCostTableRow(ref costTable, documentInfo, regionInfo, detail); totalCost += detail.EstimatedCost.Value; } foreach (var detail in kvp.Value.Where(d => !d.EstimatedCost.HasValue)) { AddCostTableRow(ref costTable, documentInfo, regionInfo, detail).Cells[0].Format.Font.Color = Colors.Red; // ToDo: Is it necessary to put on total original costs? if (!string.IsNullOrWhiteSpace(detail.SourceMeterId) && string.IsNullOrWhiteSpace(detail.TargetMeterId)) { totalOriginalCost += detail.OriginalCost.Value; } } } // Add total cost to summary table costSummaryRow.Cells[1].AddParagraph(ToCurrencyString(totalCost, regionInfo.CurrencySymbol)); } return(costEstimationSection); }
private static Section CreateAppendixResouceListSection( ref DocumentInfo documentInfo, RegionInfo regionInfo, CostEstimationResult costEstimationResult) { // TODO: extract to extension method // TODO: move hard code string to resource file. var subscriptionName = costEstimationResult.SubscriptionName; var appendixResouceListSection = documentInfo.CreateSection(); var appendixResourceListTitle = appendixResouceListSection.AddParagraph( "Full Resource List For " + subscriptionName, DocumentInfo.TitleStyleName); appendixResourceListTitle.AddBookmark("AppendixResourceList" + subscriptionName); // Resource List by Resource Group appendixResouceListSection.AddParagraph( "Here is the full resource list in reference subscription related to this migration: ", DocumentInfo.TableDesStyleName); var locationMap = costEstimationResult.LocationMap[costEstimationResult.SubscriptionId]; foreach (var kvp in costEstimationResult.DetailsByResourceGroup) { var resourceTable = DocumentInfo.CreateTable(ref appendixResouceListSection); resourceTable.AddColumn("5cm"); resourceTable.AddColumn("7cm"); resourceTable.AddColumn("4.5cm"); var resourceGroupName = resourceTable.AddRow(); resourceGroupName.Cells[0].AddParagraph("Resource Group Name"); resourceGroupName.Cells[0].Format.Font.Bold = true; resourceGroupName.Cells[1].MergeRight = 1; documentInfo.AddParagraphWordWrap(resourceGroupName.Cells[1], kvp.Key); var resourceProperties = resourceTable.AddRow(); resourceProperties.Format.Font.Bold = true; resourceProperties.Cells[0].AddParagraph("Name"); resourceProperties.Cells[1].AddParagraph("Type"); resourceProperties.Cells[2].AddParagraph("Location"); foreach (var detail in kvp.Value) { var resourceRow = resourceTable.AddRow(); documentInfo.AddParagraphWordWrap(resourceRow.Cells[0], detail.ResourceName); documentInfo.AddParagraphWordWrap(resourceRow.Cells[1], detail.ResourceType); if (locationMap.TryGetValue(detail.Location, out var locationDisplayName)) { documentInfo.AddParagraphWordWrap(resourceRow.Cells[2], locationDisplayName); } else { documentInfo.AddParagraphWordWrap(resourceRow.Cells[2], detail.Location); } } appendixResouceListSection.AddParagraph(string.Empty); } return(appendixResouceListSection); }
private static void MakeCostEstimationResourceGroupTable(HtmlTextWriter w, RegionInfo regionInfo, CostEstimationResult costEstimationResult) { foreach (var kvp in costEstimationResult.DetailsByResourceGroup) { if (!kvp.Value.Any(d => d.EstimatedCost.HasValue)) { continue; } #region Table w.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered"); w.RenderBeginTag(HtmlTextWriterTag.Table); #region Tbody w.RenderBeginTag(HtmlTextWriterTag.Tbody); #region Resource Group Name w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Scope, "row"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Resource Group Name"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Colspan, "4"); w.RenderBeginTag(HtmlTextWriterTag.Td); w.Write(kvp.Key); w.RenderEndTag(); w.RenderEndTag(); #endregion Resource Group Name #region Head for Name Category MeterName Quantity DailyCost w.RenderBeginTag(HtmlTextWriterTag.Tr); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:20%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Name"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:20%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Category"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:20%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Meter Name"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:20%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Quantity"); w.RenderEndTag(); w.AddAttribute(HtmlTextWriterAttribute.Scope, "col"); w.AddAttribute(HtmlTextWriterAttribute.Style, "width:20%"); w.RenderBeginTag(HtmlTextWriterTag.Th); w.Write("Daily Cost"); w.RenderEndTag(); w.RenderEndTag(); #endregion Head for Name Category MeterName Quantity DailyCost #region Data for Name Category MeterName Quantity DailyCost foreach (var detail in kvp.Value.Where(d => d.EstimatedCost.HasValue)) { w.RenderBeginTag(HtmlTextWriterTag.Tr); MakeCostEstimationResouceGroupTableRow(w, detail, regionInfo); w.RenderEndTag(); } foreach (var detail in kvp.Value.Where(d => !d.EstimatedCost.HasValue)) { w.RenderBeginTag(HtmlTextWriterTag.Tr); MakeCostEstimationResouceGroupTableRow(w, detail, regionInfo, true); w.RenderEndTag(); } #endregion Data for Name Category MeterName Quantity DailyCost w.RenderEndTag(); #endregion Tbody w.RenderEndTag(); #endregion Table } }