Skip to content

Commit

Permalink
CDMS-200 refactors analytics chart mechanism to run in parrallel and …
Browse files Browse the repository at this point in the history
…allow charts to be specified
  • Loading branch information
craigedmunds committed Dec 17, 2024
1 parent 1b759f5 commit ce27576
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Btms.Analytics.Tests.Helpers;

public class SingleSeriesDatasetAssertions(SingeSeriesDataset? test)
public class SingleSeriesDatasetAssertions(SingleSeriesDataset? test)
{
[CustomAssertion]
public void HaveResults(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 @@ -6,7 +6,7 @@ public static MultiSeriesDatasetAssertions Should(this List<Series>? instance)
{
return new MultiSeriesDatasetAssertions(instance);
}
public static SingleSeriesDatasetAssertions Should(this SingeSeriesDataset? instance)
public static SingleSeriesDatasetAssertions Should(this SingleSeriesDataset? instance)
{
return new SingleSeriesDatasetAssertions(instance);
}
Expand Down
12 changes: 12 additions & 0 deletions Btms.Analytics/Extensions/AnalyticsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,16 @@ public static Task<IDataset> AsIDataset(this Task<MultiSeriesDatetimeDataset> ms
ms.Wait();
return Task.FromResult((IDataset)ms.Result);
}

public static Task<IDataset> AsIDataset(this Task<MultiSeriesDataset> ms)
{
ms.Wait();
return Task.FromResult((IDataset)ms.Result);
}

public static Task<IDataset> AsIDataset(this Task<SingleSeriesDataset> ms)
{
ms.Wait();
return Task.FromResult((IDataset)ms.Result);
}
}
2 changes: 1 addition & 1 deletion Btms.Analytics/IImportNotificationsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,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<SingeSeriesDataset> ByStatus(DateTime from, DateTime to);
public Task<SingleSeriesDataset> ByStatus(DateTime from, DateTime to);
public Task<MultiSeriesDataset> ByCommodityCount(DateTime from, DateTime to);
}
4 changes: 2 additions & 2 deletions Btms.Analytics/IMovementsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ namespace Btms.Analytics;
public interface IMovementsAggregationService
{
public Task<MultiSeriesDatetimeDataset> ByCreated(DateTime from, DateTime to, AggregationPeriod aggregateBy = AggregationPeriod.Day);
public Task<SingeSeriesDataset> ByStatus(DateTime from, DateTime to);
public Task<SingleSeriesDataset> ByStatus(DateTime from, DateTime to);
public Task<MultiSeriesDataset> ByItemCount(DateTime from, DateTime to);
public Task<MultiSeriesDataset> ByUniqueDocumentReferenceCount(DateTime from, DateTime to);
public Task<SingeSeriesDataset> UniqueDocumentReferenceByMovementCount(DateTime from, DateTime to);
public Task<SingleSeriesDataset> UniqueDocumentReferenceByMovementCount(DateTime from, DateTime to);
public Task<MultiSeriesDataset> ByCheck(DateTime from, DateTime to);
}
4 changes: 2 additions & 2 deletions Btms.Analytics/ImportNotificationsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ string CreateDatasetName(BsonDocument b) =>
return Aggregate(dateRange, CreateDatasetName, matchFilter, "$partOne.arrivesAt", aggregateBy);
}

public Task<SingeSeriesDataset> ByStatus(DateTime from, DateTime to)
public Task<SingleSeriesDataset> ByStatus(DateTime from, DateTime to)
{
var data = context
.Notifications
Expand All @@ -48,7 +48,7 @@ public Task<SingeSeriesDataset> ByStatus(DateTime from, DateTime to)
.ToDictionary(g => AnalyticsHelpers.GetLinkedName(g.Linked, g.ImportNotificationType.AsString()),
g => g.Count);

return Task.FromResult(new SingeSeriesDataset
return Task.FromResult(new SingleSeriesDataset
{
Values = AnalyticsHelpers.GetImportNotificationSegments().ToDictionary(title => title, title => data.GetValueOrDefault(title, 0))
});
Expand Down
8 changes: 4 additions & 4 deletions Btms.Analytics/MovementsAggregationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Task<MultiSeriesDatetimeDataset> ByCreated(DateTime from, DateTime to, Ag
return Aggregate(dateRange, CreateDatasetName, matchFilter, "$createdSource", aggregateBy);
}

public Task<SingeSeriesDataset> ByStatus(DateTime from, DateTime to)
public Task<SingleSeriesDataset> ByStatus(DateTime from, DateTime to)
{
var data = context
.Movements
Expand All @@ -39,7 +39,7 @@ public Task<SingeSeriesDataset> ByStatus(DateTime from, DateTime to)
.Select(g => new { g.Key, Count = g.Count() })
.ToDictionary(g => AnalyticsHelpers.GetLinkedName(g.Key), g => g.Count);

return Task.FromResult(new SingeSeriesDataset
return Task.FromResult(new SingleSeriesDataset
{
Values = AnalyticsHelpers.GetMovementSegments().ToDictionary(title => title, title => data.GetValueOrDefault(title, 0))
});
Expand Down Expand Up @@ -122,7 +122,7 @@ public Task<MultiSeriesDataset> ByUniqueDocumentReferenceCount(DateTime from, Da
});
}

public Task<SingeSeriesDataset> UniqueDocumentReferenceByMovementCount(DateTime from, DateTime to)
public Task<SingleSeriesDataset> UniqueDocumentReferenceByMovementCount(DateTime from, DateTime to)
{
var mongoQuery = context
.Movements
Expand All @@ -142,7 +142,7 @@ public Task<SingeSeriesDataset> UniqueDocumentReferenceByMovementCount(DateTime
r =>r.MovementCount.ToString(),
r=> r.DocumentReferenceCount);

var result = new SingeSeriesDataset { Values = mongoResult };
var result = new SingleSeriesDataset { Values = mongoResult };

return Task.FromResult(result);
}
Expand Down
42 changes: 31 additions & 11 deletions Btms.Analytics/Results.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,46 @@ public class ByNumericDimensionResult
public int Value { get; set; }
}

public class SingeSeriesDataset : IDataset
{
public IDictionary<string, int> Values { get; set; } = new Dictionary<string, int>();
}

public class TypeMappingConverter<TType, TImplementation> : JsonConverter<TType>
where TImplementation : TType
/// <summary>
/// Serialise the derived types of IDataset
/// </summary>
/// <typeparam name="TType"></typeparam>
public class ResultTypeMappingConverter<TType> : JsonConverter<TType> where TType : IDataset
{
[return: MaybeNull]
public override TType Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
JsonSerializer.Deserialize<TImplementation>(ref reader, options);
throw new NotImplementedException();

public override void Write(
Utf8JsonWriter writer, TType value, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, (TImplementation)value!, options);
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)
{
JsonSerializer.Serialize(writer, value as MultiSeriesDataset, options);
}
else if (value is SingleSeriesDataset)
{
JsonSerializer.Serialize(writer, value as SingleSeriesDataset, options);
}
else
{
throw new NotImplementedException();
}
}
}

// A marker interface to identify things we want to be able to return from the analytics API
public interface IDataset;

public class SingleSeriesDataset : IDataset
{
public IDictionary<string, int> Values { get; set; } = new Dictionary<string, int>();
}

public class MultiSeriesDatetimeDataset : IDataset
{
public List<DatetimeSeries> Series { get; set; } = [];
Expand Down
105 changes: 105 additions & 0 deletions Btms.Backend.IntegrationTests/AnalyticsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System.Diagnostics.CodeAnalysis;
using Btms.Common.Extensions;
using Btms.Model;
using Btms.SyncJob;
using Btms.Backend.IntegrationTests.JsonApiClient;
using FluentAssertions;
using System.Net;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Btms.Backend.IntegrationTests.Extensions;
using Btms.Backend.IntegrationTests.Helpers;
using Json.More;
using Xunit;
using Xunit.Abstractions;

namespace Btms.Backend.IntegrationTests;

[Trait("Category", "Integration")]
public class AnalyticsTests(IntegrationTestsApplicationFactory factory, ITestOutputHelper testOutputHelper)
: BaseApiTests(factory, testOutputHelper), IClassFixture<IntegrationTestsApplicationFactory>
{

// private static void ShouldNotBeNull<T>([DoesNotReturnIf(true), NotNull] T? value)
// {
// // throw if null
// value.Should().NotBeNull();
// }

[Fact]
public async Task GetIndividualMultiSeriesDatetimeChart()
{
//Act
var response = await Client.GetAsync(
"/analytics/dashboard?chartsToRender=importNotificationLinkingByCreated");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());

var responseDictionary = await response.ToJsonDictionary();

responseDictionary.Count.Should().Be(1);

responseDictionary.Keys.Should().Equal("importNotificationLinkingByCreated");

}

[Fact]
public async Task GetIndividualMultiSeriesChart()
{
//Act
var response = await Client.GetAsync(
"/analytics/dashboard?chartsToRender=lastMonthMovementsByItemCount");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());

var responseDictionary = await response.ToJsonDictionary();

responseDictionary.Count.Should().Be(1);

responseDictionary.Keys.Should().Equal("lastMonthMovementsByItemCount");

}

[Fact]
public async Task GetIndividualSingleSeriesChart()
{
//Act
var response = await Client.GetAsync(
"/analytics/dashboard?chartsToRender=last7DaysImportNotificationsLinkingStatus");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());

var responseDictionary = await response.ToJsonDictionary();

responseDictionary.Count.Should().Be(1);

responseDictionary.Keys.Should().Equal("last7DaysImportNotificationsLinkingStatus");

}

[Fact]
public async Task GetAllCharts()
{
//Act
var response = await Client.GetAsync("/analytics/dashboard");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());

var responseDictionary = await response.ToJsonDictionary();

responseDictionary.Count.Should().Be(13);

responseDictionary.Keys.Take(2).Should().Equal(
"importNotificationLinkingByCreated",
"importNotificationLinkingByArrival");

responseDictionary["importNotificationLinkingByCreated"].Should().NotBeNull();
}
}
14 changes: 14 additions & 0 deletions Btms.Backend.IntegrationTests/Extensions/HttpExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Text.Json.Nodes;
using Btms.Common.Extensions;

namespace Btms.Backend.IntegrationTests.Extensions;

public static class HttpExtensions
{
public static async Task<IDictionary<string, JsonNode>> ToJsonDictionary(this HttpResponseMessage? response)
{
var responseDictionary = (await response!.Content.ReadAsStringAsync()).ToJsonDictionary();
ArgumentNullException.ThrowIfNull(responseDictionary);
return responseDictionary;
}
}
Loading

0 comments on commit ce27576

Please sign in to comment.