Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
using EstateManagement.Client;
using EstateManagement.DataTransferObjects;
using EstateManagement.DataTransferObjects.Responses;
using EstateManagement.DataTransferObjects.Responses.Contract;
using EstateManagement.DataTransferObjects.Responses.Merchant;
using EventHandling;
using FloatAggregate;
using MessagingService.Client;
using MessagingService.DataTransferObjects;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Models;
using Moq;
Expand Down Expand Up @@ -48,6 +51,8 @@ public class TransactionDomainEventHandlerTests

private Mock<IAggregateRepository<FloatAggregate, DomainEvent>> FloatAggregateRepository;

private Mock<IMemoryCacheWrapper> MemoryCache;

private TransactionDomainEventHandler TransactionDomainEventHandler;

public TransactionDomainEventHandlerTests()
Expand All @@ -60,6 +65,7 @@ public TransactionDomainEventHandlerTests()
this.SecurityServiceClient = new Mock<ISecurityServiceClient>();
this.TransactionReceiptBuilder = new Mock<ITransactionReceiptBuilder>();
this.MessagingServiceClient = new Mock<IMessagingServiceClient>();
this.MemoryCache = new Mock<IMemoryCacheWrapper>();

IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build();
ConfigurationReader.Initialise(configurationRoot);
Expand All @@ -72,7 +78,8 @@ public TransactionDomainEventHandlerTests()
this.TransactionReceiptBuilder.Object,
this.MessagingServiceClient.Object,
this.SettlementAggregateRepository.Object,
this.FloatAggregateRepository.Object);
this.FloatAggregateRepository.Object,
this.MemoryCache.Object);
}

[Theory]
Expand Down Expand Up @@ -107,6 +114,8 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet

this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.TokenResponse);

this.MemoryCache.Setup(m => m.Set(It.IsAny<Object>(), It.IsAny<Object>(), It.IsAny<MemoryCacheEntryOptions>()));

await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None);

CalculatedFee merchantFee = transactionAggregate.GetFees().SingleOrDefault(f => f.FeeId == TestData.TransactionFeeId);
Expand All @@ -118,7 +127,7 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet
merchantFee.IsSettled.ShouldBeFalse();
}

var expectedSettlementDate = settlementSchedule switch{
DateTime expectedSettlementDate = settlementSchedule switch{
EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Monthly => transactionAggregate.TransactionDateTime.Date.AddMonths(1),
EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Weekly => transactionAggregate.TransactionDateTime.Date.AddDays(7),
_ => transactionAggregate.TransactionDateTime.Date
Expand All @@ -129,6 +138,66 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet
nonMerchantFee.ShouldNotBeNull();
}

[Theory]
[InlineData(EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Immediate)]
[InlineData(EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Weekly)]
[InlineData(EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Monthly)]
public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SuccessfulSale_FeesAlreadyCached_EventIsHandled(EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule settlementSchedule)
{
this.FloatAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.GetFloatAggregateWithCostValues);

TransactionAggregate transactionAggregate = TestData.GetCompletedAuthorisedSaleTransactionAggregate();
this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(transactionAggregate);

this.FeeCalculationManager.Setup(f => f.CalculateFees(It.IsAny<List<TransactionFeeToCalculate>>(), It.IsAny<Decimal>(), It.IsAny<DateTime>())).Returns(new List<CalculatedFee>
{
TestData.CalculatedFeeMerchantFee(TestData.TransactionFeeId),
TestData.CalculatedFeeServiceProviderFee(TestData.TransactionFeeId2)
});

this.EstateClient.Setup(e => e.GetMerchant(It.IsAny<String>(), It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new EstateManagement.DataTransferObjects.Responses.Merchant.MerchantResponse
{
SettlementSchedule = settlementSchedule,
});

this.MemoryCache.Setup(m => m.TryGetValue(It.IsAny<Object>(), out It.Ref<List<ContractProductTransactionFee>>.IsAny))
.Returns((Object key, out List<ContractProductTransactionFee> value) =>
{
value = TestData.ContractProductTransactionFees; // Set the out parameter
return true; // Return value indicating success
});

this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.TokenResponse);

this.MemoryCache.Setup(m => m.Set(It.IsAny<Object>(), It.IsAny<Object>(), It.IsAny<MemoryCacheEntryOptions>()));

await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None);

CalculatedFee merchantFee = transactionAggregate.GetFees().SingleOrDefault(f => f.FeeId == TestData.TransactionFeeId);
merchantFee.ShouldNotBeNull();
if (settlementSchedule == EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Immediate)
{
merchantFee.IsSettled.ShouldBeTrue();
}
else
{
merchantFee.IsSettled.ShouldBeFalse();
}

DateTime expectedSettlementDate = settlementSchedule switch
{
EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Monthly => transactionAggregate.TransactionDateTime.Date.AddMonths(1),
EstateManagement.DataTransferObjects.Responses.Merchant.SettlementSchedule.Weekly => transactionAggregate.TransactionDateTime.Date.AddDays(7),
_ => transactionAggregate.TransactionDateTime.Date
};
merchantFee.SettlementDueDate.ShouldBe(expectedSettlementDate);

CalculatedFee nonMerchantFee = transactionAggregate.GetFees().SingleOrDefault(f => f.FeeId == TestData.TransactionFeeId2);
nonMerchantFee.ShouldNotBeNull();
}

[Fact]
public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SuccessfulSale_MerchantWithNotSetSettlementSchedule_ErrorThrown()
{
Expand Down Expand Up @@ -158,6 +227,8 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet

this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.TokenResponse);

this.MemoryCache.Setup(m => m.Set(It.IsAny<Object>(), It.IsAny<Object>(), It.IsAny<MemoryCacheEntryOptions>()));

Should.Throw<NotSupportedException>(async () =>
{
await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None);
Expand Down Expand Up @@ -282,5 +353,114 @@ public async Task TransactionDomainEventHandler_Handle_TransactionCostInformatio
//{
// await this.TransactionDomainEventHandler.Handle(TestData.SettledMerchantFeeAddedToTransactionEvent(DateTime.MinValue), CancellationToken.None);
//}

[Fact]
public async Task TransactionDomainEventHandler_RequireFeeCalculation_IsNotAuthorised_ReturnsFalse(){

TransactionAggregate transactionAggregate = TransactionAggregate.Create(TestData.TransactionId);
transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber,
TransactionType.Sale, TestData.TransactionReference,
TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier,
TestData.TransactionAmount);
transactionAggregate.DeclineTransaction(TestData.OperatorId, "111", "SUCCESS", "0000", "SUCCESS");

var result = TransactionDomainEventHandler.RequireFeeCalculation(transactionAggregate);
result.ShouldBeFalse();
}

[Fact]
public async Task TransactionDomainEventHandler_RequireFeeCalculation_IsNotCompelted_ReturnsFalse()
{
TransactionAggregate transactionAggregate = TransactionAggregate.Create(TestData.TransactionId);
transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber,
TransactionType.Sale, TestData.TransactionReference,
TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier,
TestData.TransactionAmount);
transactionAggregate.AuthoriseTransaction(TestData.OperatorId, "111", "111", "SUCCESS", "1234", "0000", "SUCCESS");

var result = TransactionDomainEventHandler.RequireFeeCalculation(transactionAggregate);
result.ShouldBeFalse();
}

[Fact]
public async Task TransactionDomainEventHandler_RequireFeeCalculation_IsALogon_ReturnsFalse()
{
TransactionAggregate transactionAggregate = TransactionAggregate.Create(TestData.TransactionId);
transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber,
TransactionType.Logon, TestData.TransactionReference,
TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier,
TestData.TransactionAmount);
transactionAggregate.AuthoriseTransactionLocally("111", "0001", "SUCCESS");
transactionAggregate.CompleteTransaction();


var result = TransactionDomainEventHandler.RequireFeeCalculation(transactionAggregate);
result.ShouldBeFalse();
}

[Fact]
public async Task TransactionDomainEventHandler_RequireFeeCalculation_NoContractId_ReturnsFalse()
{
TransactionAggregate transactionAggregate = TransactionAggregate.Create(TestData.TransactionId);
transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber,
TransactionType.Sale, TestData.TransactionReference,
TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier,
TestData.TransactionAmount);
transactionAggregate.AuthoriseTransaction(TestData.OperatorId, "111", "111", "SUCCESS", "1234", "0000", "SUCCESS");
transactionAggregate.CompleteTransaction();


var result = TransactionDomainEventHandler.RequireFeeCalculation(transactionAggregate);
result.ShouldBeFalse();
}

[Fact]
public async Task TransactionDomainEventHandler_RequireFeeCalculation_NullAmount_ReturnsFalse()
{
TransactionAggregate transactionAggregate = TransactionAggregate.Create(TestData.TransactionId);
transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber,
TransactionType.Sale, TestData.TransactionReference,
TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier,
null);
transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId);
transactionAggregate.AuthoriseTransaction(TestData.OperatorId, "111", "111", "SUCCESS", "1234", "0000", "SUCCESS");
transactionAggregate.CompleteTransaction();


var result = TransactionDomainEventHandler.RequireFeeCalculation(transactionAggregate);
result.ShouldBeFalse();
}

[Fact]
public async Task TransactionDomainEventHandler_RequireFeeCalculation_ReturnsTrue()
{
TransactionAggregate transactionAggregate = TransactionAggregate.Create(TestData.TransactionId);
transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber,
TransactionType.Sale, TestData.TransactionReference,
TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier,
TestData.TransactionAmount);
transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId);
transactionAggregate.AuthoriseTransaction(TestData.OperatorId, "111", "111", "SUCCESS", "1234", "0000", "SUCCESS");
transactionAggregate.CompleteTransaction();


var result = TransactionDomainEventHandler.RequireFeeCalculation(transactionAggregate);
result.ShouldBeTrue();
}

[Theory]
[InlineData(SettlementSchedule.Immediate, "2024-05-01", "2024-05-01")]
[InlineData(SettlementSchedule.NotSet, "2024-05-01", "2024-05-01")]
[InlineData(SettlementSchedule.Weekly, "2024-05-01", "2024-05-08")]
[InlineData(SettlementSchedule.Monthly, "2024-05-01", "2024-06-01")]
public async Task TransactionDomainEventHandler_CalculateSettlementDate_CorrectDateReturned(SettlementSchedule settlementSchedule, String completedDateString, String expectedDateString){

DateTime completedDate = DateTime.ParseExact(completedDateString, "yyyy-MM-dd", null);
DateTime expectedDate = DateTime.ParseExact(expectedDateString, "yyyy-MM-dd", null);
DateTime result = TransactionDomainEventHandler.CalculateSettlementDate(settlementSchedule, completedDate);
result.Date.ShouldBe(expectedDate.Date);
}
}
}


41 changes: 41 additions & 0 deletions TransactionProcessor.BusinessLogic/Common/MemoryCacheWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TransactionProcessor.BusinessLogic.Common
{
public interface IMemoryCacheWrapper
{
Boolean TryGetValue<T>(Object Key, out T cache);
void Set<T>(Object key, T cache, MemoryCacheEntryOptions entryOptions);
}

public class MemoryCacheWrapper : IMemoryCacheWrapper
{
private readonly IMemoryCache MemoryCache;

public MemoryCacheWrapper(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}

public void Set<T>(Object key, T cache, MemoryCacheEntryOptions entryOptions)
{
MemoryCache.Set(key, cache, entryOptions);
}

public Boolean TryGetValue<T>(Object Key, out T cache)
{
if (MemoryCache.TryGetValue(Key, out T cachedItem))
{
cache = cachedItem;
return true;
}
cache = default(T);
return false;
}
}
}
Loading