diff --git a/Adaptation/FileHandlers/ADO/ProcessData.cs b/Adaptation/FileHandlers/ADO/ProcessData.cs index 5566cdd..a884a79 100644 --- a/Adaptation/FileHandlers/ADO/ProcessData.cs +++ b/Adaptation/FileHandlers/ADO/ProcessData.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; +using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; @@ -44,12 +45,11 @@ public class ProcessData : IProcessData { List results = new(); Description? description; - JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); - description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); + description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description); if (description is null) continue; results.Add(description); diff --git a/Adaptation/FileHandlers/Kanban/ProcessData.cs b/Adaptation/FileHandlers/Kanban/ProcessData.cs index a42b3ce..9eb7244 100644 --- a/Adaptation/FileHandlers/Kanban/ProcessData.cs +++ b/Adaptation/FileHandlers/Kanban/ProcessData.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.IO; +using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; @@ -221,12 +222,11 @@ public class ProcessData : IProcessData { List results = new(); Description? description; - JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); - description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); + description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description); if (description is null) continue; results.Add(description); diff --git a/Adaptation/FileHandlers/Markdown/ProcessData.cs b/Adaptation/FileHandlers/Markdown/ProcessData.cs index ada4141..fbd22a3 100644 --- a/Adaptation/FileHandlers/Markdown/ProcessData.cs +++ b/Adaptation/FileHandlers/Markdown/ProcessData.cs @@ -399,12 +399,11 @@ public class ProcessData : IProcessData { List results = new(); Description? description; - JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); - description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); + description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description); if (description is null) continue; results.Add(description); diff --git a/Adaptation/FileHandlers/Violation/ProcessData.cs b/Adaptation/FileHandlers/Violation/ProcessData.cs index b065d99..a68a2ee 100644 --- a/Adaptation/FileHandlers/Violation/ProcessData.cs +++ b/Adaptation/FileHandlers/Violation/ProcessData.cs @@ -615,12 +615,11 @@ public class ProcessData : IProcessData { List results = new(); Description? description; - JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); - description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); + description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description); if (description is null) continue; results.Add(description); diff --git a/Adaptation/FileHandlers/json/StaticSite/js/cod-1-123-0.js b/Adaptation/FileHandlers/json/StaticSite/js/cod-1-123-0.js index 6fbddf5..9a32423 100644 --- a/Adaptation/FileHandlers/json/StaticSite/js/cod-1-123-0.js +++ b/Adaptation/FileHandlers/json/StaticSite/js/cod-1-123-0.js @@ -143,7 +143,7 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da let businessValue = workItem.BusinessValue; let timeCriticality = workItem.TimeCriticality; let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement; - let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? null : workItem.WeightedShortestJobFirst.toFixed(2); + let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? ' ' : workItem.WeightedShortestJobFirst.toFixed(2); workItem.CumulativeStoryPoints = ' '; workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)'; workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? ' ' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1); @@ -159,15 +159,19 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? ' ' : getNotifications(t, data.TimeCriticality); workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? ' ' : getNotifications(r, data.RiskReductionOpportunityEnablement); workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder; - let check = effort == workItem.Effort - && businessValue === workItem.BusinessValue - && timeCriticality === workItem.TimeCriticality - && riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement; - if (check && weightedShortestJobFirst == workItem.WeightedShortestJobFirst) { + if (effort == undefined || businessValue == undefined || timeCriticality == undefined || riskReductionMinusOpportunityEnablement || weightedShortestJobFirst == undefined) { workItem.api = ''; - } else { - workItem.api = ` -### Work Item Patch ${check} WSJF ${workItem.Id} ${weightedShortestJobFirst} != ${workItem.WeightedShortestJobFirst} + } + else { + let check = effort === workItem.Effort + && businessValue === workItem.BusinessValue + && timeCriticality === workItem.TimeCriticality + && riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement; + if (check && weightedShortestJobFirst == workItem.WeightedShortestJobFirst) { + workItem.api = ''; + } else { + workItem.api = ` +### Work Item Patch ${check} WSJF ${workItem.Id} ${effort}:${workItem.Effort}; ${businessValue}:${workItem.BusinessValue}; ${timeCriticality}:${workItem.TimeCriticality}; ${riskReductionMinusOpportunityEnablement}:${workItem.RiskReductionMinusOpportunityEnablement}; ${weightedShortestJobFirst}:${workItem.WeightedShortestJobFirst}; patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0 Authorization: Basic {{PAT}} @@ -178,44 +182,45 @@ Content-Type: application/json-patch+json "op": "replace", "path": "/fields/Microsoft.VSTS.Common.BusinessValue", "value": "${workItem.BusinessValue}" - }, - { - "op": "replace", - "path": "/fields/Microsoft.VSTS.Scheduling.Effort", - "value": "${workItem.Effort}" - }, - { - "op": "replace", - "path": "/fields/Custom.RRminusOE", - "value": "${workItem.RiskReductionMinusOpportunityEnablement}" - }, - { - "op": "replace", - "path": "/fields/Microsoft.VSTS.Common.TimeCriticality", + }, + { + "op": "replace", + "path": "/fields/Microsoft.VSTS.Scheduling.Effort", + "value": "${workItem.Effort}" + }, + { + "op": "replace", + "path": "/fields/Custom.RRminusOE", + "value": "${workItem.RiskReductionMinusOpportunityEnablement}" + }, + { + "op": "replace", + "path": "/fields/Microsoft.VSTS.Common.TimeCriticality", "value": "${workItem.TimeCriticality}" - }, - { - "op": "replace", + }, + { + "op": "replace", "path": "/fields/Custom.WSJF", "value": "${workItem.WeightedShortestJobFirst}" - }, - { - "op": "replace", - "path": "/fields/Custom.WSJFFib", - "value": "${workItem.WeightedShortestJobFirst}" - } -] - -HTTP 200 -[Asserts] -header "Content-Type" == "application/json; charset=utf-8; api-version=7.0" -jsonpath "$.id" == ${workItem.Id} -jsonpath "$.fields['Microsoft.VSTS.Common.BusinessValue']" == ${workItem.BusinessValue} -jsonpath "$.fields['Microsoft.VSTS.Scheduling.Effort']" == ${workItem.Effort} -jsonpath "$.fields['Custom.RRminusOE']" == ${workItem.RiskReductionMinusOpportunityEnablement} -jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality} -jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst} -jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`; + }, + { + "op": "replace", + "path": "/fields/Custom.WSJFFib", + "value": "${workItem.WeightedShortestJobFirst}" + } + ] + + HTTP 200 + [Asserts] + header "Content-Type" == "application/json; charset=utf-8; api-version=7.0" + jsonpath "$.id" == ${workItem.Id} + jsonpath "$.fields['Microsoft.VSTS.Common.BusinessValue']" == ${workItem.BusinessValue} + jsonpath "$.fields['Microsoft.VSTS.Scheduling.Effort']" == ${workItem.Effort} + jsonpath "$.fields['Custom.RRminusOE']" == ${workItem.RiskReductionMinusOpportunityEnablement} + jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality} + jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst} + jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`; + } } } } diff --git a/Adaptation/Shared/FileRead.cs b/Adaptation/Shared/FileRead.cs index 48aacab..aaa6958 100644 --- a/Adaptation/Shared/FileRead.cs +++ b/Adaptation/Shared/FileRead.cs @@ -9,7 +9,6 @@ using System.IO; using System.Linq; using System.Text; using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading; namespace Adaptation.Shared; @@ -447,12 +446,13 @@ public class FileRead : Properties.IFileRead { List results = new(); Duplicator.Description description; - JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); - description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); + description = JsonSerializer.Deserialize(jsonElement.ToString(), Duplicator.SharedDescriptionSourceGenerationContext.Default.Description); + if (description is null) + continue; results.Add(description); } return results; diff --git a/Adaptation/Shared/ProcessDataStandardFormat.cs b/Adaptation/Shared/ProcessDataStandardFormat.cs index 1fb9e2a..9d48a31 100644 --- a/Adaptation/Shared/ProcessDataStandardFormat.cs +++ b/Adaptation/Shared/ProcessDataStandardFormat.cs @@ -654,6 +654,17 @@ internal class ProcessDataStandardFormat return results; } + internal static JsonElement[] GetArray(string reportFullPath, string[] lines, ProcessDataStandardFormat processDataStandardFormat) + { + JsonElement[] results; + string? json = GetRecordsJson(reportFullPath, lines); + if (string.IsNullOrEmpty(json)) + results = GetArray(processDataStandardFormat); + else + results = JsonSerializer.Deserialize(json, JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception(); + return results; + } + internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText) { string result; @@ -903,7 +914,7 @@ internal class ProcessDataStandardFormat } foreach (KeyValuePair> keyValuePair in results) { - if (body.Count < 3) + if (body.Count < 2) break; if (keyValuePair.Value.Count != body.Count) continue; @@ -956,6 +967,26 @@ internal class ProcessDataStandardFormat return result; } + private static string? GetRecordsJson(string reportFullPath, string[] lines) + { + string? result; + bool foundRecords = false; + List results = new(); + lines ??= File.ReadAllLines(reportFullPath); + foreach (string line in lines) + { + if (line.StartsWith("\"Records\"")) + foundRecords = true; + if (!foundRecords) + continue; + if (line == "],") + break; + results.Add(line); + } + result = results.Count == 0 ? null : $"{string.Join(Environment.NewLine, results.Skip(1))}{Environment.NewLine}]"; + return result; + } + } [JsonSourceGenerationOptions(WriteIndented = true)]