Skip to content

Commit

Permalink
Fix up tests to use DecisionStatusFinder
Browse files Browse the repository at this point in the history
  • Loading branch information
craigedmunds committed Feb 5, 2025
1 parent 5cf18ab commit 58de882
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 63 deletions.
18 changes: 18 additions & 0 deletions Btms.Business.Tests/DecisionStatusEnumFinderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Btms.Business.Builders;
using Btms.Business.Commands;
using Btms.Model;
using FluentAssertions;
using Xunit;

namespace Btms.Business.Tests;

public class DecisionStatusFinderTests
{
[Fact]
public void EnsureWeHaveAllStatusFinders()
{
//An exception would be thrown if it doesn't
var decisionFinder = new DecisionStatusFinder();
decisionFinder.Should().NotBeNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public async Task WhenNotificationNotExists_ThenShouldBeCreated()
// ARRANGE
var clearanceRequest = CreateAlvsClearanceRequest();
var dbContext = new MemoryMongoDbContext();
var preProcessor = new MovementPreProcessor(dbContext, NullLogger<MovementPreProcessor>.Instance, new MovementBuilderFactory(NullLogger<MovementBuilder>.Instance));
var preProcessor = new MovementPreProcessor(dbContext, NullLogger<MovementPreProcessor>.Instance, new MovementBuilderFactory(new DecisionStatusFinder(), NullLogger<MovementBuilder>.Instance));

// ACT
var preProcessingResult = await preProcessor.Process(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private static List<Movement> GenerateMovements(bool hasChecks)

var config = ScenarioFactory.CreateScenarioConfig(generator, 1, 1);

var movementBuilderFactory = new MovementBuilderFactory(NullLogger<MovementBuilder>.Instance);
var movementBuilderFactory = new MovementBuilderFactory(new DecisionStatusFinder(), NullLogger<MovementBuilder>.Instance);
var generatorResult = generator
.Generate(1, 1, DateTime.UtcNow, config)
.First(x => x is AlvsClearanceRequest);
Expand Down
4 changes: 2 additions & 2 deletions Btms.Business.Tests/Services/Matching/MatchingServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ private static List<Movement> GenerateMovements()
{
CrNoMatchScenarioGenerator generator =
new CrNoMatchScenarioGenerator(NullLogger<CrNoMatchScenarioGenerator>.Instance);
var movementBuilderFactory = new MovementBuilderFactory(NullLogger<MovementBuilder>.Instance);
var movementBuilderFactory = new MovementBuilderFactory(new DecisionStatusFinder(), NullLogger<MovementBuilder>.Instance);
var config = ScenarioFactory.CreateScenarioConfig(generator, 1, 1);

var generatorResult = generator
Expand All @@ -73,7 +73,7 @@ private static (List<ImportNotification> Notifications, List<Movement> Movements
ChedASimpleMatchScenarioGenerator generator =
new ChedASimpleMatchScenarioGenerator(NullLogger<ChedASimpleMatchScenarioGenerator>.Instance);
var config = ScenarioFactory.CreateScenarioConfig(generator, 1, 1);
var movementBuilderFactory = new MovementBuilderFactory(NullLogger<MovementBuilder>.Instance);
var movementBuilderFactory = new MovementBuilderFactory(new DecisionStatusFinder(), NullLogger<MovementBuilder>.Instance);

var generatorResult = generator.Generate(1, 1, DateTime.UtcNow, config);

Expand Down
137 changes: 137 additions & 0 deletions Btms.Business/Builders/DecisionStatusEnumFinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using Btms.Model;
using Btms.Model.Cds;
using Btms.Model.Ipaffs;

namespace Btms.Business.Builders;

public class DecisionStatusFinder
{
private readonly List<(DecisionStatusEnum status, Func<Movement, AlvsDecision, bool> finder)> _finders = [];

public DecisionStatusFinder()
{
_finders.Add((DecisionStatusEnum.BtmsMadeSameDecisionAsAlvs, BtmsMadeSameDecisionAsAlvs));
_finders.Add((DecisionStatusEnum.BtmMadeSameDecisionTypeAsAlvs, BtmMadeSameDecisionTypeAsAlvs));
_finders.Add((DecisionStatusEnum.NoImportNotificationsLinked, NoImportNotificationsLinked));
_finders.Add((DecisionStatusEnum.NoAlvsDecisions, NoAlvsDecisions));
_finders.Add((DecisionStatusEnum.HasChedppChecks, HasChedppChecks));

_finders.Add((DecisionStatusEnum.AlvsX00CaseSensitivity, AlvsX00CaseSensitivity));
_finders.Add((DecisionStatusEnum.AlvsX00WrongDocumentReferenceFormat, AlvsX00WrongDocumentReferenceFormat));
_finders.Add((DecisionStatusEnum.AlvsX00NotBtms, AlvsX00NotBtms));
_finders.Add((DecisionStatusEnum.ReliesOnCDMS205, ReliesOnCDMS205));
_finders.Add((DecisionStatusEnum.ReliesOnCDMS249, ReliesOnCDMS249));
_finders.Add((DecisionStatusEnum.HasOtherDataErrors, HasOtherDataErrors));
_finders.Add((DecisionStatusEnum.HasGenericDataErrors, HasGenericDataErrors));
_finders.Add((DecisionStatusEnum.HasMultipleChedTypes, HasMultipleChedTypes));
_finders.Add((DecisionStatusEnum.HasMultipleCheds, HasMultipleCheds));

_finders.Add((DecisionStatusEnum.InvestigationNeeded, InvestigationNeeded));

// Default if none of the above match - none needs to be the last one in the Enum
_finders.Add((DecisionStatusEnum.None, (m, d) => true));

//Validate that each status in the enum has a finder
var hasFinders = _finders.Select(f => f.status).ToArray();
var needsFinders = Enum.GetValues<DecisionStatusEnum>();

// var missing = needsFinders
// .Where(d => hasFinders.Any(h => h == d));

var missing = needsFinders
.Except(hasFinders);

// var missing = hasFinders
// .Union(needsFinders)
// .Where(x => !hasFinders.Contains(x) || !needsFinders.Contains(x));

if (missing.Count() > 0)
{
throw new Exception("Decision Status Finders missing in DecisionStatusFinder");
}
}

public DecisionStatusEnum GetDecisionStatus(Movement movement, AlvsDecision decision)
{
return _finders
.First(f => f.finder(movement, decision))
.status;
}

private static bool BtmsMadeSameDecisionAsAlvs(Movement movement, AlvsDecision decision)
{
return decision.Context.DecisionComparison!.Checks.All(c =>
c.AlvsDecisionCode == c.BtmsDecisionCode);
}

private static bool BtmMadeSameDecisionTypeAsAlvs(Movement movement, AlvsDecision decision)
{
return decision.Context.DecisionComparison!.Checks.All(c =>
c.AlvsDecisionCode.First() == c.BtmsDecisionCode?.First());
}

private static bool NoImportNotificationsLinked(Movement movement, AlvsDecision decision)
{
return movement.Relationships.Notifications.Data.Count == 0;
}

private static bool NoAlvsDecisions(Movement movement, AlvsDecision decision)
{
return movement.AlvsDecisionStatus.Decisions.Count == 0;
}

private static bool HasChedppChecks(Movement movement, AlvsDecision decision)
{
return movement.BtmsStatus.ChedTypes.Contains(ImportNotificationTypeEnum.Chedpp);
}

private static bool AlvsX00CaseSensitivity(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool AlvsX00WrongDocumentReferenceFormat(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool AlvsX00NotBtms(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool ReliesOnCDMS205(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool ReliesOnCDMS249(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool HasOtherDataErrors(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool HasGenericDataErrors(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool HasMultipleChedTypes(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool HasMultipleCheds(Movement movement, AlvsDecision decision)
{
return false;
}

private static bool InvestigationNeeded(Movement movement, AlvsDecision decision)
{
return false;
}
}
10 changes: 0 additions & 10 deletions Btms.Business/Builders/DecisionStatusEnumFinders.cs

This file was deleted.

102 changes: 58 additions & 44 deletions Btms.Business/Builders/MovementBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Btms.Business.Extensions;
using Btms.Common.Extensions;
using Btms.Model;
using Btms.Model.Auditing;
Expand All @@ -9,7 +10,7 @@

namespace Btms.Business.Builders;

public class MovementBuilder(ILogger<MovementBuilder> logger, Movement movement, bool hasChanges = false)
public class MovementBuilder(ILogger<MovementBuilder> logger, DecisionStatusFinder decisionStatusFinder, Movement movement, bool hasChanges = false)
{
private Movement? _movement = movement;
public bool HasChanges = hasChanges;
Expand Down Expand Up @@ -364,56 +365,69 @@ private void CompareDecisions(AlvsDecision alvsDecision, CdsDecision btmsDecisio
throw new InvalidDataException("Should only be comparing when it's been paired");
}

var btmsCheckDictionary = btmsDecision
.Items!
.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c }))
.ToDictionary(ic => (ic.Item.ItemNumber, ic.Check.CheckCode!), ic => ic.Check.DecisionCode!);

var alvsChecks = alvsDecision.Decision
.Items!.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c }))
.Select(ic =>
{
var decisionCode =
btmsCheckDictionary!.GetValueOrDefault((ic.Item.ItemNumber, ic.Check.CheckCode!), null);
return new ItemCheck()
{
ItemNumber = ic.Item!.ItemNumber,
CheckCode = ic.Check!.CheckCode!,
AlvsDecisionCode = ic.Check!.DecisionCode!,
BtmsDecisionCode = decisionCode
};
})
.ToList();
var btmsCheckDictionary = btmsDecision.GetCheckDictionary();
//
// var btmsCheckDictionary = btmsDecision
// .Items!
// .SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c }))
// .ToDictionary(ic => (ic.Item.ItemNumber, ic.Check.CheckCode!), ic => ic.Check.DecisionCode!);

var alvsChecks = alvsDecision.GetItemChecks(btmsCheckDictionary);
// var alvsChecks = alvsDecision.Decision
// .Items!.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c }))
// .Select(ic =>
// {
// var decisionCode =
// btmsCheckDictionary!.GetValueOrDefault((ic.Item.ItemNumber, ic.Check.CheckCode!), null);
// return new ItemCheck()
// {
// ItemNumber = ic.Item!.ItemNumber,
// CheckCode = ic.Check!.CheckCode!,
// AlvsDecisionCode = ic.Check!.DecisionCode!,
// BtmsDecisionCode = decisionCode
// };
// })
// .ToList();

alvsDecision.Context.DecisionComparison.Checks = alvsChecks;
alvsDecision.Context.AlvsCheckStatus = GetAlvsCheckStatus(alvsChecks);
alvsDecision.Context.BtmsCheckStatus = GeBtmsCheckStatus(alvsChecks);

var decisionStatus = DecisionStatusEnum.InvestigationNeeded;
var checksMatch = alvsChecks.All(c => c.AlvsDecisionCode == c.BtmsDecisionCode);
var checkTypesMatch = alvsChecks.All(c => c.AlvsDecisionCode.First() == c.BtmsDecisionCode?.First());

if (checksMatch)

var decisionStatus =
decisionStatusFinder.GetDecisionStatus(_movement, alvsDecision);

if (decisionStatus == DecisionStatusEnum.BtmsMadeSameDecisionAsAlvs)
{
alvsDecision.Context.DecisionComparison.DecisionMatched = true;
decisionStatus = DecisionStatusEnum.BtmsMadeSameDecisionAsAlvs;
}
else if (checkTypesMatch)
{
decisionStatus = DecisionStatusEnum.BtmMadeSameDecisionTypeAsAlvs;
}
else if (_movement.Relationships.Notifications.Data.Count == 0)
{
decisionStatus = DecisionStatusEnum.NoImportNotificationsLinked;
}
else if (_movement.AlvsDecisionStatus.Decisions.Count == 0)
{
decisionStatus = DecisionStatusEnum.NoAlvsDecisions;
}
else if (_movement.BtmsStatus.ChedTypes.Contains(ImportNotificationTypeEnum.Chedpp))
{
decisionStatus = DecisionStatusEnum.HasChedppChecks;
}
// var checksMatch = alvsChecks.All(c => c.AlvsDecisionCode == c.BtmsDecisionCode);

// if (checksMatch)
// {
// alvsDecision.Context.DecisionComparison.DecisionMatched = true;
// decisionStatus = DecisionStatusEnum.BtmsMadeSameDecisionAsAlvs;
// }
// else
// {
// decisionStatus = decisionStatusFinder.GetDecisionStatus(_movement, alvsDecision);
// }

// else if (checkTypesMatch)
// {
// decisionStatus = DecisionStatusEnum.BtmMadeSameDecisionTypeAsAlvs;
// }
// else if (_movement.Relationships.Notifications.Data.Count == 0)
// {
// decisionStatus = DecisionStatusEnum.NoImportNotificationsLinked;
// }
// else if (_movement.AlvsDecisionStatus.Decisions.Count == 0)
// {
// decisionStatus = DecisionStatusEnum.NoAlvsDecisions;
// }
// else if (_movement.BtmsStatus.ChedTypes.Contains(ImportNotificationTypeEnum.Chedpp))
// {
// decisionStatus = DecisionStatusEnum.HasChedppChecks;
// }

alvsDecision.Context.DecisionComparison.DecisionStatus = decisionStatus;
}
Expand Down
6 changes: 3 additions & 3 deletions Btms.Business/Builders/MovementBuilderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Btms.Business.Builders;

public class MovementBuilderFactory(ILogger<MovementBuilder> logger)
public class MovementBuilderFactory(DecisionStatusFinder decisionStatusFinder, ILogger<MovementBuilder> logger)
{
public MovementBuilder From(CdsClearanceRequest request)
{
Expand Down Expand Up @@ -36,12 +36,12 @@ public MovementBuilder From(CdsClearanceRequest request)
BtmsStatus = MovementExtensions.GetMovementStatus(GetChedTypes(request.Items!.ToList()), documentReferenceIds, notificationRelationshipIds)
};

return new MovementBuilder(logger, movement, true);
return new MovementBuilder(logger, decisionStatusFinder, movement, true);
}

public MovementBuilder From(Movement movement)
{
return new MovementBuilder(logger, movement, true);
return new MovementBuilder(logger, decisionStatusFinder, movement, true);
}

private ImportNotificationTypeEnum[] GetChedTypes(List<Items>? items = null)
Expand Down
27 changes: 27 additions & 0 deletions Btms.Business/Extensions/MovementExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,31 @@ public static MovementStatus GetMovementStatus(ImportNotificationTypeEnum[] ched
: LinkStatusEnum.Investigate
};
}

public static Dictionary<(int, string), string?> GetCheckDictionary(this CdsDecision decision)
{
return decision
.Items!
.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c }))
.ToDictionary(ic => (ic.Item.ItemNumber, ic.Check.CheckCode!), ic => ic.Check.DecisionCode);
}

public static List<ItemCheck> GetItemChecks(this AlvsDecision alvsDecision, IReadOnlyDictionary<(int, string), string?> compareTo)
{
return alvsDecision.Decision
.Items!.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c }))
.Select(ic =>
{
var decisionCode =
compareTo.GetValueOrDefault((ic.Item.ItemNumber, ic.Check.CheckCode!), null);
return new ItemCheck()
{
ItemNumber = ic.Item!.ItemNumber,
CheckCode = ic.Check!.CheckCode!,
AlvsDecisionCode = ic.Check!.DecisionCode!,
BtmsDecisionCode = decisionCode
};
})
.ToList();
}
}
1 change: 1 addition & 0 deletions Btms.Business/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public static IServiceCollection AddBusinessServices(this IServiceCollection ser
services.AddScoped<IDecisionFinder, ChedPPDecisionFinder>();
services.AddScoped<IDecisionFinder, IuuDecisionFinder>();

services.AddTransient<DecisionStatusFinder>();
services.AddTransient<MovementBuilderFactory>();
services.AddScoped<IPreProcessor<ImportNotification, Model.Ipaffs.ImportNotification>, ImportNotificationPreProcessor>();
services.AddScoped<IPreProcessor<AlvsClearanceRequest, Model.Movement>, MovementPreProcessor>();
Expand Down
Loading

0 comments on commit 58de882

Please sign in to comment.