Skip to content

Commit

Permalink
CDMS-223 Decision Analytics & additional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
craigedmunds committed Jan 13, 2025
1 parent c454571 commit 6a7db9f
Show file tree
Hide file tree
Showing 81 changed files with 898 additions and 379 deletions.
4 changes: 2 additions & 2 deletions Btms.Analytics.Tests/Helpers/MultiSeriesDatasetAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

namespace Btms.Analytics.Tests.Helpers;

public class MultiSeriesDatasetAssertions(List<Series>? test)
: GenericCollectionAssertions<Series>(test)
public class MultiSeriesDatasetAssertions(List<Series<ByNumericDimensionResult>>? test)
: GenericCollectionAssertions<Series<ByNumericDimensionResult>>(test)
{
[CustomAssertion]
public void BeSameLength(string because = "", params object[] becauseArgs)
Expand Down
2 changes: 1 addition & 1 deletion Btms.Analytics.Tests/Helpers/TestAssertionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Btms.Analytics.Tests.Helpers;

public static class TestAssertionExtensions
{
public static MultiSeriesDatasetAssertions Should(this List<Series>? instance)
public static MultiSeriesDatasetAssertions Should(this List<Series<ByNumericDimensionResult>>? instance)
{
return new MultiSeriesDatasetAssertions(instance);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Btms.Analytics.Tests;

public class ImportNotificationsByCommoditiesTests(ITestOutputHelper output)
: ScenarioDatasetBaseTest(output, Datasets.FunctionalAnalyticsDatasetName, reloadData:false)
: ScenarioDatasetBaseTest(output, Datasets.FunctionalAnalyticsDatasetName)
{

[Fact]
Expand All @@ -37,7 +37,6 @@ public async Task WhenCalledLastWeek_ReturnExpectedAggregation()
});

result.Should().HaveResults();

result.Should().BeSameLength();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public async Task WhenCalledLastMonth_ReturnExpectedAggregation()
r.Periods.Count.Should().Be(DateTime.Today.DaysSinceMonthAgo() + 1);
});

// result.shoul
result.Sum(r => r.Periods.Sum(p => p.Value))
.Should().BeGreaterThan(0);
}
Expand Down
17 changes: 7 additions & 10 deletions Btms.Analytics.Tests/MovementsByDecisionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,18 @@
namespace Btms.Analytics.Tests;

public class MovementsByDecisionsTests(ITestOutputHelper output)
: ScenarioDatasetBaseTest(output, Datasets.FunctionalAnalyticsDatasetName)
: ScenarioDatasetBaseTest(output, Datasets.FunctionalAnalyticsDecisionsDatasetName)
{

[Fact(Skip = "Needs revisiting - needs more assertions, perhaps switch to individual scenario test")]
[Fact]
// [Fact(Skip = "Needs revisiting - needs more assertions, perhaps switch to individual scenario test")]
public async Task WhenCalled_ReturnExpectedAggregation()
{
TestOutputHelper.WriteLine("Querying for aggregated data");
var result = (await GetMovementsAggregationService()
.ByDecision(DateTime.Today.MonthAgo(), DateTime.Today.Tomorrow()))
.Result;
var result = await MovementsAggregationService
.ByDecision(DateTime.MinValue, DateTime.MaxValue)!;

TestOutputHelper.WriteLine("{0} aggregated items found", result.Count);
TestOutputHelper.WriteLine("{0} aggregated items found", result!.Result.Count());

result.Count.Should().BeGreaterThan(1);
// result.Select(r => r.Key).Order().Should()
// .Equal("ALVS Linked : H01", "BTMS Linked : C03", "BTMS Linked : X00", "BTMS Not Linked : X00");
result.Result.Count.Should().BeGreaterThan(1);
}
}
39 changes: 21 additions & 18 deletions Btms.Analytics.Tests/MovementsByUniqueDocumentReferenceTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Text.Json.Nodes;
using Btms.Common.Extensions;
using FluentAssertions;
using Xunit;
Expand All @@ -6,37 +7,39 @@
using Btms.Analytics.Tests.Fixtures;
using Btms.Analytics.Tests.Helpers;
using TestDataGenerator.Config;
using TestDataGenerator.Scenarios.SpecificFiles;
using TestGenerator.IntegrationTesting.Backend;
using TestGenerator.IntegrationTesting.Backend.Extensions;

namespace Btms.Analytics.Tests;

public class MovementsByUniqueDocumentReferenceTests(ITestOutputHelper output)
: ScenarioDatasetBaseTest(output, Datasets.FunctionalAnalyticsDatasetName)
: ScenarioGeneratorBaseTest<Mrn24GBDDJER3ZFRMZAR9ScenarioGenerator>(output)
{

[Fact(Skip = "Needs revisiting - needs more assertions, perhaps switch to individual scenario test")]
public async Task WhenCalledLastWeek_ReturnExpectedAggregation()
[Fact]
public async Task ShouldReturnExpectedAggregation()
{
TestOutputHelper.WriteLine("Querying for aggregated data");
var result = (await GetMovementsAggregationService()
.ByUniqueDocumentReferenceCount(DateTime.Today.WeekAgo(), DateTime.Today.Tomorrow()))
.Series
.ToList();

TestOutputHelper.WriteLine("{0} aggregated items found", result.Count);
var result = await Client
.GetAnalyticsDashboard(["movementsByUniqueDocumentReferenceCount"],
dateFrom: DateTime.MinValue, dateTo: DateTime.MaxValue);

TestOutputHelper.WriteLine($"{result.StatusCode} status");
result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString());

result.Count().Should().Be(3);
result.Select(r => r.Name).Order().Should().Equal("Investigate", "Linked", "Not Linked");
var chart = await result
.AnalyticsMultiSeriesChartAs<MultiSeriesDataset<ByNumericDimensionResult>,ByNumericDimensionResult>("movementsByUniqueDocumentReferenceCount")!;

TestOutputHelper.WriteLine("{0} aggregated items found", chart.Series!.Count);

result.Should().AllSatisfy(d =>
chart.Series!.Count.Should().Be(3);
chart.Series.Should().HaveResults();
chart.Series.Should().BeSameLength();

chart.Series!.Should().AllSatisfy(d =>
{
d.Dimension.Should().Be("Document Reference Count");
d.Results.Count().Should().NotBe(0);
d.Results.Sum(r => ((ByNumericDimensionResult)r).Value).Should().BeGreaterThan(0);
});

result.Should().HaveResults();

result.Should().BeSameLength();
}
}
27 changes: 19 additions & 8 deletions Btms.Analytics.Tests/MovementsExceptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,35 @@
using Btms.Analytics.Tests.Fixtures;
using Btms.Analytics.Tests.Helpers;
using TestDataGenerator.Config;
using TestDataGenerator.Scenarios;
using TestGenerator.IntegrationTesting.Backend;
using TestGenerator.IntegrationTesting.Backend.Extensions;

namespace Btms.Analytics.Tests;

public class MovementsExceptionsTests(ITestOutputHelper output)
: ScenarioDatasetBaseTest(output, Datasets.FunctionalAnalyticsDatasetName)
: ScenarioGeneratorBaseTest<CrNoMatchSingleItemWithDecisionScenarioGenerator>(output)
{

[Fact(Skip="Change to an individiual scenario test that generates an exception. Possibly a seperate test for each exception type")]
[Fact] //(Skip="Change to an individiual scenario test that generates an exception. Possibly a seperate test for each exception type")]
public async Task WhenCalled_ReturnExpectedAggregation()
{
TestOutputHelper.WriteLine("Querying for aggregated data");
var result = (await GetMovementsAggregationService()
.ByDecision(DateTime.Today.MonthAgo(), DateTime.Today.Tomorrow()))
.Result;

TestOutputHelper.WriteLine("{0} aggregated items found", result.Count);

result.Count.Should().BeGreaterThan(1);
var result = await Client
.GetAnalyticsDashboard(["movementsExceptions"],
dateFrom: DateTime.MinValue, dateTo: DateTime.MaxValue);

var chart = await result
.AnalyticsChartAs<SingleSeriesDataset>("movementsExceptions")!;

chart.Values.Count
.Should().BeGreaterThan(1);

chart.Values
.Single(v => v.Key == "Alvs has match decisions but no Btms links")
.Value
.Should().Be(1);

}
}
35 changes: 29 additions & 6 deletions Btms.Analytics/Dataset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ public class SummarisedDataset<TSummary, TResult> : IDataset

}

public class MultiSeriesDataset : IDataset
public class MultiSeriesDataset<TDimensionResult> : IDataset
where TDimensionResult : IDimensionResult
{
public List<Series> Series { get; set; } = [];
public List<Series<TDimensionResult>> Series { get; set; } = [];
}

public class SingleSeriesDataset : IDataset, IDimensionResult
Expand Down Expand Up @@ -49,18 +50,40 @@ public class DatasetResultTypeMappingConverter<TType> : JsonConverter<TType> whe
{
[return: MaybeNull]
public override TType Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
throw new NotImplementedException();
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var converters = options
.Converters
.Where(c => c is not DatasetResultTypeMappingConverter<TType>);

var newOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = options.PropertyNamingPolicy
};

foreach (var jsonConverter in converters)
{
newOptions.Converters.Add(jsonConverter);
}
// newOptions.Converters.Append<IEnumerable<JsonConverter>>(converters);

TType result = JsonSerializer.Deserialize<TType>(ref reader, newOptions)!;

// TType result = JsonSerializer.Deserialize<TType>(ref reader, options)!;

// return new ByNumericDimensionResult() { Dimension = 1, Value = 1};
return result;
}

public override void Write(Utf8JsonWriter writer, TType value, JsonSerializerOptions options)
{
if (value is MultiSeriesDatetimeDataset)
{
JsonSerializer.Serialize(writer, value as MultiSeriesDatetimeDataset, options);
}
else if (value is MultiSeriesDataset)
else if (value is MultiSeriesDataset<ByNumericDimensionResult>)
{
JsonSerializer.Serialize(writer, value as MultiSeriesDataset, options);
JsonSerializer.Serialize(writer, value as MultiSeriesDataset<ByNumericDimensionResult>, options);
}
else if (value is SingleSeriesDataset)
{
Expand Down
18 changes: 14 additions & 4 deletions Btms.Analytics/DatasetDimensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ public class DatetimeSeries(string name)
public List<ByDateTimeResult> Periods { get; set; } = [];
}

public class Series
public class Series<TDimensionResult>
{
public required string Name { get; set; }
public required string Dimension { get; set; }
public required List<IDimensionResult> Results { get; set; }
public required List<TDimensionResult> Results { get; set; }
}

/// <summary>
Expand All @@ -82,8 +82,18 @@ public class DimensionResultTypeMappingConverter<TType> : JsonConverter<TType> w
{
[return: MaybeNull]
public override TType Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
throw new NotImplementedException();
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var newOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = options.PropertyNamingPolicy
};
// ByNumericDimensionResult byNumeric = JsonSerializer.Deserialize<ByNumericDimensionResult>(ref reader, newOptions)!;

TType result = JsonSerializer.Deserialize<TType>(ref reader, newOptions)!;
// return new ByNumericDimensionResult() { Dimension = 1, Value = 1};
return result;
}

public override void Write(Utf8JsonWriter writer, TType value, JsonSerializerOptions options)
{
Expand Down
2 changes: 1 addition & 1 deletion Btms.Analytics/Extensions/AnalyticsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public static async Task<IDataset> AsIDataset(this Task<MultiSeriesDatetimeDatas
return (IDataset)ms.Result;
}

public static async Task<IDataset> AsIDataset(this Task<MultiSeriesDataset> ms)
public static async Task<IDataset> AsIDataset(this Task<MultiSeriesDataset<ByNumericDimensionResult>> ms)
{
await ms;
return (IDataset)ms.Result;
Expand Down
7 changes: 5 additions & 2 deletions Btms.Analytics/Extensions/AnalyticsHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Btms.Model;
using Btms.Model.Cds;
using MongoDB.Bson;
namespace Btms.Analytics.Extensions;

Expand Down Expand Up @@ -51,8 +52,10 @@ public static string[] GetImportNotificationSegments()
.ToArray();
}

public static string[] GetMovementStatusSegments()
public static LinkStatusEnum[] GetMovementStatusSegments()
{
return ["Linked", "Not Linked", "Investigate"];
return Enum.GetValues<LinkStatusEnum>();
// .Select(e => e.AsString()).ToArray();
// return ["Linked", "Not Linked", "Investigate"];
}
}
6 changes: 3 additions & 3 deletions Btms.Analytics/Extensions/MovementExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Btms.Model;
using Btms.Model.Cds;
using Btms.Model.Ipaffs;

namespace Btms.Analytics.Extensions;
Expand All @@ -21,7 +22,7 @@ public class MovementWithLinkStatus
{
public required Movement Movement;
public required DateTime CreatedSource;
public required string Description;
public required LinkStatusEnum Status;
}

public static IQueryable<MovementWithLinkStatus> SelectLinkStatus(this IQueryable<Movement> source)
Expand All @@ -30,8 +31,7 @@ public static IQueryable<MovementWithLinkStatus> SelectLinkStatus(this IQueryabl
.Select(m => new MovementWithLinkStatus() {
Movement = m,
CreatedSource = m.CreatedSource!.Value,
Description =
m.BtmsStatus.LinkStatus
Status = m.BtmsStatus.LinkStatus
// m.Relationships.Notifications.Data.Count > 0 ? "Linked" :
// m.AlvsDecisionStatus!.Context!.AlvsCheckStatus!.AnyMatch ? "Investigate" :
// "Not Linked"
Expand Down
2 changes: 1 addition & 1 deletion Btms.Analytics/IImportNotificationsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ public interface IImportNotificationsAggregationService
public Task<MultiSeriesDatetimeDataset> ByCreated(DateTime from, DateTime to, AggregationPeriod aggregateBy = AggregationPeriod.Day);
public Task<MultiSeriesDatetimeDataset> ByArrival(DateTime from, DateTime to, AggregationPeriod aggregateBy = AggregationPeriod.Day);
public Task<SingleSeriesDataset> ByStatus(DateTime? from = null, DateTime? to = null);
public Task<MultiSeriesDataset> ByCommodityCount(DateTime from, DateTime to);
public Task<MultiSeriesDataset<ByNumericDimensionResult>> ByCommodityCount(DateTime from, DateTime to);
public Task<SingleSeriesDataset> ByMaxVersion(DateTime from, DateTime to, ImportNotificationTypeEnum[]? chedTypes = null, string? country = null);
}
4 changes: 2 additions & 2 deletions Btms.Analytics/IMovementsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ public interface IMovementsAggregationService
{
public Task<MultiSeriesDatetimeDataset> ByCreated(DateTime from, DateTime to, AggregationPeriod aggregateBy = AggregationPeriod.Day);
public Task<SingleSeriesDataset> ByStatus(DateTime? from = null, DateTime? to = null);
public Task<MultiSeriesDataset> ByItemCount(DateTime from, DateTime to);
public Task<MultiSeriesDataset<ByNumericDimensionResult>> ByItemCount(DateTime from, DateTime to);
public Task<SummarisedDataset<SingleSeriesDataset, StringBucketDimensionResult>> ByDecision(DateTime from, DateTime to, ImportNotificationTypeEnum[]? chedTypes = null, string? country = null);
// public Task<TabularDataset<ByNameDimensionResult>> ByDecisionAndLinkStatus(DateTime from, DateTime to);
public Task<MultiSeriesDataset> ByUniqueDocumentReferenceCount(DateTime from, DateTime to);
public Task<MultiSeriesDataset<ByNumericDimensionResult>> ByUniqueDocumentReferenceCount(DateTime from, DateTime to);
public Task<SingleSeriesDataset> UniqueDocumentReferenceByMovementCount(DateTime from, DateTime to);
// public Task<MultiSeriesDataset> ByCheck(DateTime from, DateTime to, string[]? chedTypes = null, string? country = null);
public Task<EntityDataset<AuditHistory>?> GetHistory(string movementId);
Expand Down
8 changes: 4 additions & 4 deletions Btms.Analytics/ImportNotificationsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public Task<SingleSeriesDataset> ByStatus(DateTime? from = null, DateTime? to =
});
}

public Task<MultiSeriesDataset> ByCommodityCount(DateTime from, DateTime to)
public Task<MultiSeriesDataset<ByNumericDimensionResult>> ByCommodityCount(DateTime from, DateTime to)
{
var query = context
.Notifications
Expand Down Expand Up @@ -97,10 +97,10 @@ public Task<MultiSeriesDataset> ByCommodityCount(DateTime from, DateTime to)
g => g.NotificationCount);


return Task.FromResult(new MultiSeriesDataset()
return Task.FromResult(new MultiSeriesDataset<ByNumericDimensionResult>()
{
Series = AnalyticsHelpers.GetImportNotificationSegments()
.Select(title => new Series()
.Select(title => new Series<ByNumericDimensionResult>()
{
Name = title,
Dimension = "ItemCount",
Expand All @@ -109,7 +109,7 @@ public Task<MultiSeriesDataset> ByCommodityCount(DateTime from, DateTime to)
{
Dimension = i,
Value = asDictionary.GetValueOrDefault(new { Title=title, CommodityCount = i })
}).ToList<IDimensionResult>()
}).ToList()
})
.ToList()
});
Expand Down
Loading

0 comments on commit 6a7db9f

Please sign in to comment.