From c29b8ed955ac55c1f8e47fa154b2581997af9bc0 Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Mon, 2 Jan 2023 05:23:13 +0000 Subject: [PATCH 1/3] Fix bootstrapper tests and add mediator tests --- .../Mediator/MediatorTests.cs | 178 +++++++++++ ...actionProcessor.BusinessLogic.Tests.csproj | 4 +- .../Services/IVoucherDomainService.cs | 274 ----------------- .../Services/VoucherDomainService.cs | 280 ++++++++++++++++++ ...actionProcessor.DataTransferObjects.csproj | 1 + ...ionProcessor.ProjectionEngine.Tests.csproj | 2 +- TransactionProcessor.Testing/TestData.cs | 7 +- .../General/BootstrapperTests.cs | 3 +- ...ionProcessor.VoucherAggregate.Tests.csproj | 2 +- TransactionProcessor.sln | 10 - .../TransactionProcessor - Backup (1).csproj | 75 ----- .../TransactionProcessor - Backup.csproj | 75 ----- 12 files changed, 472 insertions(+), 439 deletions(-) create mode 100644 TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs create mode 100644 TransactionProcessor.BusinessLogic/Services/VoucherDomainService.cs delete mode 100644 TransactionProcessor/TransactionProcessor - Backup (1).csproj delete mode 100644 TransactionProcessor/TransactionProcessor - Backup.csproj diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs new file mode 100644 index 00000000..c132574d --- /dev/null +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs @@ -0,0 +1,178 @@ +using MediatR; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Moq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace TransactionProcessor.BusinessLogic.Tests.Mediator +{ + using System.Threading; + using BusinessLogic.Services; + using Lamar; + using Microsoft.Extensions.DependencyInjection; + using Models; + using Testing; + + public class MediatorTests + { + private List Requests = new List(); + + public MediatorTests() + { + this.Requests.Add(TestData.ProcessLogonTransactionRequest); + this.Requests.Add(TestData.ProcessReconciliationRequest); + this.Requests.Add(TestData.ProcessSaleTransactionRequest); + this.Requests.Add(TestData.ProcessSettlementRequest); + } + + [Fact] + public async Task Mediator_Send_RequestHandled() + { + Mock hostingEnvironment = new Mock(); + hostingEnvironment.Setup(he => he.EnvironmentName).Returns("Development"); + hostingEnvironment.Setup(he => he.ContentRootPath).Returns("/home"); + hostingEnvironment.Setup(he => he.ApplicationName).Returns("Test Application"); + + ServiceRegistry services = new ServiceRegistry(); + Startup s = new Startup(hostingEnvironment.Object); + Startup.Configuration = this.SetupMemoryConfiguration(); + + this.AddTestRegistrations(services, hostingEnvironment.Object); + s.ConfigureContainer(services); + Startup.Container.AssertConfigurationIsValid(AssertMode.Full); + + List errors = new List(); + IMediator mediator = Startup.Container.GetService(); + foreach (IBaseRequest baseRequest in this.Requests) + { + try + { + await mediator.Send(baseRequest); + } + catch (Exception ex) + { + errors.Add(ex.Message); + } + } + + if (errors.Any() == true) + { + String errorMessage = String.Join(Environment.NewLine, errors); + throw new Exception(errorMessage); + } + } + + private IConfigurationRoot SetupMemoryConfiguration() + { + Dictionary configuration = new Dictionary(); + + IConfigurationBuilder builder = new ConfigurationBuilder(); + + builder.AddInMemoryCollection(TestData.DefaultAppSettings); + + return builder.Build(); + } + + private void AddTestRegistrations(ServiceRegistry services, + IWebHostEnvironment hostingEnvironment) + { + services.AddLogging(); + DiagnosticListener diagnosticSource = new DiagnosticListener(hostingEnvironment.ApplicationName); + services.AddSingleton(diagnosticSource); + services.AddSingleton(diagnosticSource); + services.AddSingleton(hostingEnvironment); + services.AddSingleton(hostingEnvironment); + services.AddSingleton(Startup.Configuration); + + services.OverrideServices(s => { + s.AddSingleton(); + s.AddSingleton(); + s.AddSingleton(); + }); + } + } + + public class DummySettlementDomainService : ISettlementDomainService + { + public async Task ProcessSettlement(DateTime pendingSettlementDate, + Guid estateId, + CancellationToken cancellationToken) { + return new ProcessSettlementResponse(); + } + } + + public class DummyVoucherDomainService : IVoucherDomainService + { + public async Task IssueVoucher(Guid voucherId, + String operatorId, + Guid estateId, + Guid transactionId, + DateTime issuedDateTime, + Decimal value, + String recipientEmail, + String recipientMobile, + CancellationToken cancellationToken) { + return new IssueVoucherResponse(); + } + + public async Task RedeemVoucher(Guid estateId, + String voucherCode, + DateTime redeemedDateTime, + CancellationToken cancellationToken) { + return new RedeemVoucherResponse(); + } + } + + public class DummyTransactionDomainService : ITransactionDomainService + { + public async Task ProcessLogonTransaction(Guid transactionId, + Guid estateId, + Guid merchantId, + DateTime transactionDateTime, + String transactionNumber, + String deviceIdentifier, + CancellationToken cancellationToken) { + return new ProcessLogonTransactionResponse(); + } + + public async Task ProcessSaleTransaction(Guid transactionId, + Guid estateId, + Guid merchantId, + DateTime transactionDateTime, + String transactionNumber, + String deviceIdentifier, + String operatorId, + String customerEmailAddress, + Dictionary additionalTransactionMetadata, + Guid contractId, + Guid productId, + Int32 transactionSource, + CancellationToken cancellationToken) { + return new ProcessSaleTransactionResponse(); + } + + public async Task ProcessReconciliationTransaction(Guid transactionId, + Guid estateId, + Guid merchantId, + String deviceIdentifier, + DateTime transactionDateTime, + Int32 transactionCount, + Decimal transactionValue, + CancellationToken cancellationToken) { + return new ProcessReconciliationTransactionResponse(); + } + + public async Task ResendTransactionReceipt(Guid transactionId, + Guid estateId, + CancellationToken cancellationToken) { + + } + } +} diff --git a/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj b/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj index 6362ec3a..600870f6 100644 --- a/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj +++ b/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj @@ -2,11 +2,12 @@ net7.0 - Full + None false + @@ -28,6 +29,7 @@ + diff --git a/TransactionProcessor.BusinessLogic/Services/IVoucherDomainService.cs b/TransactionProcessor.BusinessLogic/Services/IVoucherDomainService.cs index b5a72230..536c0748 100644 --- a/TransactionProcessor.BusinessLogic/Services/IVoucherDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/IVoucherDomainService.cs @@ -1,26 +1,11 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace TransactionProcessor.BusinessLogic.Services { - using EstateManagement.Client; - using EstateManagement.DataTransferObjects.Responses; - using EstateReporting.Database; - using Microsoft.EntityFrameworkCore; using Models; - using NetBarcode; - using SecurityService.Client; - using SecurityService.DataTransferObjects.Responses; - using Shared.DomainDrivenDesign.EventSourcing; - using Shared.EventStore.Aggregate; - using Shared.Exceptions; - using Shared.General; - using Shared.Logger; - using VoucherAggregate; public interface IVoucherDomainService { @@ -64,263 +49,4 @@ Task RedeemVoucher(Guid estateId, #endregion } - - public class VoucherDomainService : IVoucherDomainService - { - /// - /// The voucher aggregate repository - /// - private readonly IAggregateRepository VoucherAggregateRepository; - - /// - /// The security service client - /// - private readonly ISecurityServiceClient SecurityServiceClient; - - /// - /// The estate client - /// - private readonly IEstateClient EstateClient; - - /// - /// The database context factory - /// - private readonly Shared.EntityFramework.IDbContextFactory DbContextFactory; - - private const String ConnectionStringIdentifier = "EstateReportingReadModel"; - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The voucher aggregate repository. - /// The security service client. - /// The estate client. - /// The database context factory. - public VoucherDomainService(IAggregateRepository voucherAggregateRepository, - ISecurityServiceClient securityServiceClient, - IEstateClient estateClient, - Shared.EntityFramework.IDbContextFactory dbContextFactory) - { - this.VoucherAggregateRepository = voucherAggregateRepository; - this.SecurityServiceClient = securityServiceClient; - this.EstateClient = estateClient; - this.DbContextFactory = dbContextFactory; - } - #endregion - - #region Methods - - /// - /// Issues the voucher. - /// - /// The voucher identifier. - /// The operator identifier. - /// The estate identifier. - /// The transaction identifier. - /// The issued date time. - /// The value. - /// The recipient email. - /// The recipient mobile. - /// The cancellation token. - /// - public async Task IssueVoucher(Guid voucherId, String operatorId, Guid estateId, - Guid transactionId, - DateTime issuedDateTime, - Decimal value, - String recipientEmail, String recipientMobile, CancellationToken cancellationToken) - { - await this.ValidateVoucherIssue(estateId, operatorId, cancellationToken); - - VoucherAggregate voucher = await this.VoucherAggregateRepository.GetLatestVersion(voucherId, cancellationToken); - - voucher.Generate(operatorId, estateId, transactionId, issuedDateTime, value); - - Voucher voucherModel = voucher.GetVoucher(); - - // Generate the barcode - Barcode barcode = new Barcode(voucherModel.VoucherCode); - voucher.AddBarcode(barcode.GetBase64Image()); - voucher.Issue(recipientEmail, recipientMobile, issuedDateTime); - - await this.VoucherAggregateRepository.SaveChanges(voucher, cancellationToken); - - return new IssueVoucherResponse - { - ExpiryDate = voucherModel.ExpiryDate, - Message = voucherModel.Message, - VoucherCode = voucherModel.VoucherCode, - VoucherId = voucherId - }; - } - - /// - /// Redeems the voucher. - /// - /// The estate identifier. - /// The voucher code. - /// The redeemed date time. - /// The cancellation token. - /// - /// No voucher found with voucher code [{voucherCode}] - public async Task RedeemVoucher(Guid estateId, - String voucherCode, - DateTime redeemedDateTime, - CancellationToken cancellationToken) - { - await this.ValidateVoucherRedemption(estateId, cancellationToken); - - // Find the voucher based on the voucher code - EstateReportingGenericContext context = await this.DbContextFactory.GetContext(estateId, VoucherDomainService.ConnectionStringIdentifier, cancellationToken); - - EstateReporting.Database.Entities.Voucher voucher = await context.Vouchers.SingleOrDefaultAsync(v => v.VoucherCode == voucherCode, cancellationToken); - - if (voucher == null) - { - throw new NotFoundException($"No voucher found with voucher code [{voucherCode}]"); - } - - // Now get the aggregate - VoucherAggregate voucherAggregate = await this.VoucherAggregateRepository.GetLatestVersion(voucher.VoucherId, cancellationToken); - - // Redeem the voucher - voucherAggregate.Redeem(redeemedDateTime); - - // Save the changes - await this.VoucherAggregateRepository.SaveChanges(voucherAggregate, cancellationToken); - - Voucher voucherModel = voucherAggregate.GetVoucher(); - - return new RedeemVoucherResponse - { - RemainingBalance = voucherModel.Balance, - ExpiryDate = voucherModel.ExpiryDate, - VoucherCode = voucherModel.VoucherCode - }; - } - - /// - /// Validates the voucher issue. - /// - /// The estate identifier. - /// The operator identifier. - /// The cancellation token. - /// - /// - /// Estate Id [{estateId}] is not a valid estate - /// or - /// Estate {estate.EstateName} has no operators defined - /// or - /// Operator Identifier [{operatorIdentifier}] is not a valid for estate [{estate.EstateName}] - /// - /// Estate Id [{estateId}] is not a valid estate - /// or - /// Operator Identifier [{operatorIdentifier}] is not a valid for estate [{estate.EstateName}] - private async Task ValidateVoucherIssue(Guid estateId, String operatorIdentifier, CancellationToken cancellationToken) - { - EstateResponse estate = null; - - // Validate the Estate Record is a valid estate - try - { - estate = await this.GetEstate(estateId, cancellationToken); - } - catch (Exception ex) when (ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) - { - throw new NotFoundException($"Estate Id [{estateId}] is not a valid estate"); - } - - if (estate.Operators == null || estate.Operators.Any() == false) - { - throw new NotFoundException($"Estate {estate.EstateName} has no operators defined"); - } - - EstateOperatorResponse estateOperator = estate.Operators.SingleOrDefault(o => o.Name == operatorIdentifier); - if (estateOperator == null) - { - throw new NotFoundException($"Operator Identifier [{operatorIdentifier}] is not a valid for estate [{estate.EstateName}]"); - } - - return estate; - } - - /// - /// Validates the voucher redemption. - /// - /// The estate identifier. - /// The cancellation token. - /// - /// Estate Id [{estateId}] is not a valid estate - private async Task ValidateVoucherRedemption(Guid estateId, CancellationToken cancellationToken) - { - EstateResponse estate = null; - - // Validate the Estate Record is a valid estate - try - { - estate = await this.GetEstate(estateId, cancellationToken); - } - catch (Exception ex) when (ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) - { - throw new NotFoundException($"Estate Id [{estateId}] is not a valid estate"); - } - - return estate; - } - - /// - /// The token response - /// - private TokenResponse TokenResponse; - - /// - /// Gets the estate. - /// - /// The estate identifier. - /// The cancellation token. - /// - private async Task GetEstate(Guid estateId, - CancellationToken cancellationToken) - { - this.TokenResponse = await this.GetToken(cancellationToken); - - EstateResponse estate = await this.EstateClient.GetEstate(this.TokenResponse.AccessToken, estateId, cancellationToken); - - return estate; - } - - /// - /// Gets the token. - /// - /// The cancellation token. - /// - private async Task GetToken(CancellationToken cancellationToken) - { - // Get a token to talk to the estate service - String clientId = ConfigurationReader.GetValue("AppSettings", "ClientId"); - String clientSecret = ConfigurationReader.GetValue("AppSettings", "ClientSecret"); - Logger.LogInformation($"Client Id is {clientId}"); - Logger.LogInformation($"Client Secret is {clientSecret}"); - - if (this.TokenResponse == null) - { - TokenResponse token = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken); - Logger.LogInformation($"Token is {token.AccessToken}"); - return token; - } - - if (this.TokenResponse.Expires.UtcDateTime.Subtract(DateTime.UtcNow) < TimeSpan.FromMinutes(2)) - { - Logger.LogInformation($"Token is about to expire at {this.TokenResponse.Expires.DateTime:O}"); - TokenResponse token = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken); - Logger.LogInformation($"Token is {token.AccessToken}"); - return token; - } - - return this.TokenResponse; - } - - #endregion - } } diff --git a/TransactionProcessor.BusinessLogic/Services/VoucherDomainService.cs b/TransactionProcessor.BusinessLogic/Services/VoucherDomainService.cs new file mode 100644 index 00000000..0879b9ea --- /dev/null +++ b/TransactionProcessor.BusinessLogic/Services/VoucherDomainService.cs @@ -0,0 +1,280 @@ +namespace TransactionProcessor.BusinessLogic.Services; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using EstateManagement.Client; +using EstateManagement.DataTransferObjects.Responses; +using EstateReporting.Database; +using Microsoft.EntityFrameworkCore; +using Models; +using NetBarcode; +using SecurityService.Client; +using SecurityService.DataTransferObjects.Responses; +using Shared.DomainDrivenDesign.EventSourcing; +using Shared.EventStore.Aggregate; +using Shared.Exceptions; +using Shared.General; +using Shared.Logger; +using VoucherAggregate; + +public class VoucherDomainService : IVoucherDomainService +{ + /// + /// The voucher aggregate repository + /// + private readonly IAggregateRepository VoucherAggregateRepository; + + /// + /// The security service client + /// + private readonly ISecurityServiceClient SecurityServiceClient; + + /// + /// The estate client + /// + private readonly IEstateClient EstateClient; + + /// + /// The database context factory + /// + private readonly Shared.EntityFramework.IDbContextFactory DbContextFactory; + + private const String ConnectionStringIdentifier = "EstateReportingReadModel"; + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The voucher aggregate repository. + /// The security service client. + /// The estate client. + /// The database context factory. + public VoucherDomainService(IAggregateRepository voucherAggregateRepository, + ISecurityServiceClient securityServiceClient, + IEstateClient estateClient, + Shared.EntityFramework.IDbContextFactory dbContextFactory) + { + this.VoucherAggregateRepository = voucherAggregateRepository; + this.SecurityServiceClient = securityServiceClient; + this.EstateClient = estateClient; + this.DbContextFactory = dbContextFactory; + } + #endregion + + #region Methods + + /// + /// Issues the voucher. + /// + /// The voucher identifier. + /// The operator identifier. + /// The estate identifier. + /// The transaction identifier. + /// The issued date time. + /// The value. + /// The recipient email. + /// The recipient mobile. + /// The cancellation token. + /// + public async Task IssueVoucher(Guid voucherId, String operatorId, Guid estateId, + Guid transactionId, + DateTime issuedDateTime, + Decimal value, + String recipientEmail, String recipientMobile, CancellationToken cancellationToken) + { + await this.ValidateVoucherIssue(estateId, operatorId, cancellationToken); + + VoucherAggregate voucher = await this.VoucherAggregateRepository.GetLatestVersion(voucherId, cancellationToken); + + voucher.Generate(operatorId, estateId, transactionId, issuedDateTime, value); + + Voucher voucherModel = voucher.GetVoucher(); + + // Generate the barcode + Barcode barcode = new Barcode(voucherModel.VoucherCode); + voucher.AddBarcode(barcode.GetBase64Image()); + voucher.Issue(recipientEmail, recipientMobile, issuedDateTime); + + await this.VoucherAggregateRepository.SaveChanges(voucher, cancellationToken); + + return new IssueVoucherResponse + { + ExpiryDate = voucherModel.ExpiryDate, + Message = voucherModel.Message, + VoucherCode = voucherModel.VoucherCode, + VoucherId = voucherId + }; + } + + /// + /// Redeems the voucher. + /// + /// The estate identifier. + /// The voucher code. + /// The redeemed date time. + /// The cancellation token. + /// + /// No voucher found with voucher code [{voucherCode}] + public async Task RedeemVoucher(Guid estateId, + String voucherCode, + DateTime redeemedDateTime, + CancellationToken cancellationToken) + { + await this.ValidateVoucherRedemption(estateId, cancellationToken); + + // Find the voucher based on the voucher code + EstateReportingGenericContext context = await this.DbContextFactory.GetContext(estateId, VoucherDomainService.ConnectionStringIdentifier, cancellationToken); + + EstateReporting.Database.Entities.Voucher voucher = await context.Vouchers.SingleOrDefaultAsync(v => v.VoucherCode == voucherCode, cancellationToken); + + if (voucher == null) + { + throw new NotFoundException($"No voucher found with voucher code [{voucherCode}]"); + } + + // Now get the aggregate + VoucherAggregate voucherAggregate = await this.VoucherAggregateRepository.GetLatestVersion(voucher.VoucherId, cancellationToken); + + // Redeem the voucher + voucherAggregate.Redeem(redeemedDateTime); + + // Save the changes + await this.VoucherAggregateRepository.SaveChanges(voucherAggregate, cancellationToken); + + Voucher voucherModel = voucherAggregate.GetVoucher(); + + return new RedeemVoucherResponse + { + RemainingBalance = voucherModel.Balance, + ExpiryDate = voucherModel.ExpiryDate, + VoucherCode = voucherModel.VoucherCode + }; + } + + /// + /// Validates the voucher issue. + /// + /// The estate identifier. + /// The operator identifier. + /// The cancellation token. + /// + /// + /// Estate Id [{estateId}] is not a valid estate + /// or + /// Estate {estate.EstateName} has no operators defined + /// or + /// Operator Identifier [{operatorIdentifier}] is not a valid for estate [{estate.EstateName}] + /// + /// Estate Id [{estateId}] is not a valid estate + /// or + /// Operator Identifier [{operatorIdentifier}] is not a valid for estate [{estate.EstateName}] + private async Task ValidateVoucherIssue(Guid estateId, String operatorIdentifier, CancellationToken cancellationToken) + { + EstateResponse estate = null; + + // Validate the Estate Record is a valid estate + try + { + estate = await this.GetEstate(estateId, cancellationToken); + } + catch (Exception ex) when (ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) + { + throw new NotFoundException($"Estate Id [{estateId}] is not a valid estate"); + } + + if (estate.Operators == null || estate.Operators.Any() == false) + { + throw new NotFoundException($"Estate {estate.EstateName} has no operators defined"); + } + + EstateOperatorResponse estateOperator = estate.Operators.SingleOrDefault(o => o.Name == operatorIdentifier); + if (estateOperator == null) + { + throw new NotFoundException($"Operator Identifier [{operatorIdentifier}] is not a valid for estate [{estate.EstateName}]"); + } + + return estate; + } + + /// + /// Validates the voucher redemption. + /// + /// The estate identifier. + /// The cancellation token. + /// + /// Estate Id [{estateId}] is not a valid estate + private async Task ValidateVoucherRedemption(Guid estateId, CancellationToken cancellationToken) + { + EstateResponse estate = null; + + // Validate the Estate Record is a valid estate + try + { + estate = await this.GetEstate(estateId, cancellationToken); + } + catch (Exception ex) when (ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) + { + throw new NotFoundException($"Estate Id [{estateId}] is not a valid estate"); + } + + return estate; + } + + /// + /// The token response + /// + private TokenResponse TokenResponse; + + /// + /// Gets the estate. + /// + /// The estate identifier. + /// The cancellation token. + /// + private async Task GetEstate(Guid estateId, + CancellationToken cancellationToken) + { + this.TokenResponse = await this.GetToken(cancellationToken); + + EstateResponse estate = await this.EstateClient.GetEstate(this.TokenResponse.AccessToken, estateId, cancellationToken); + + return estate; + } + + /// + /// Gets the token. + /// + /// The cancellation token. + /// + private async Task GetToken(CancellationToken cancellationToken) + { + // Get a token to talk to the estate service + String clientId = ConfigurationReader.GetValue("AppSettings", "ClientId"); + String clientSecret = ConfigurationReader.GetValue("AppSettings", "ClientSecret"); + Logger.LogInformation($"Client Id is {clientId}"); + Logger.LogInformation($"Client Secret is {clientSecret}"); + + if (this.TokenResponse == null) + { + TokenResponse token = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken); + Logger.LogInformation($"Token is {token.AccessToken}"); + return token; + } + + if (this.TokenResponse.Expires.UtcDateTime.Subtract(DateTime.UtcNow) < TimeSpan.FromMinutes(2)) + { + Logger.LogInformation($"Token is about to expire at {this.TokenResponse.Expires.DateTime:O}"); + TokenResponse token = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken); + Logger.LogInformation($"Token is {token.AccessToken}"); + return token; + } + + return this.TokenResponse; + } + + #endregion +} \ No newline at end of file diff --git a/TransactionProcessor.DataTransferObjects/TransactionProcessor.DataTransferObjects.csproj b/TransactionProcessor.DataTransferObjects/TransactionProcessor.DataTransferObjects.csproj index c1ae885f..0069e495 100644 --- a/TransactionProcessor.DataTransferObjects/TransactionProcessor.DataTransferObjects.csproj +++ b/TransactionProcessor.DataTransferObjects/TransactionProcessor.DataTransferObjects.csproj @@ -2,6 +2,7 @@ net7.0;netstandard2.0 + None diff --git a/TransactionProcessor.ProjectionEngine.Tests/TransactionProcessor.ProjectionEngine.Tests.csproj b/TransactionProcessor.ProjectionEngine.Tests/TransactionProcessor.ProjectionEngine.Tests.csproj index c1fcf421..53f4fa4d 100644 --- a/TransactionProcessor.ProjectionEngine.Tests/TransactionProcessor.ProjectionEngine.Tests.csproj +++ b/TransactionProcessor.ProjectionEngine.Tests/TransactionProcessor.ProjectionEngine.Tests.csproj @@ -4,7 +4,7 @@ net7.0 enable enable - + None false diff --git a/TransactionProcessor.Testing/TestData.cs b/TransactionProcessor.Testing/TestData.cs index 3479a2f0..4ec597a7 100644 --- a/TransactionProcessor.Testing/TestData.cs +++ b/TransactionProcessor.Testing/TestData.cs @@ -299,7 +299,12 @@ public static Dictionary AdditionalTransactionMetaDataForPataPaw new Dictionary { ["AppSettings:ClientId"] = "clientId", - ["AppSettings:ClientSecret"] = "clientSecret" + ["AppSettings:ClientSecret"] = "clientSecret", + ["AppSettings:UseConnectionStringConfig"] = "false", + ["EventStoreSettings:ConnectionString"] = "https://127.0.0.1:2113", + ["SecurityConfiguration:Authority"] = "https://127.0.0.1", + ["AppSettings:EstateManagementApi"] = "http://127.0.0.1", + ["AppSettings:SecurityService"] = "http://127.0.0.1" }; public static EstateResponse GetEmptyEstateResponse => diff --git a/TransactionProcessor.Tests/General/BootstrapperTests.cs b/TransactionProcessor.Tests/General/BootstrapperTests.cs index 413626f2..7fefcce1 100644 --- a/TransactionProcessor.Tests/General/BootstrapperTests.cs +++ b/TransactionProcessor.Tests/General/BootstrapperTests.cs @@ -22,7 +22,7 @@ public class BootstrapperTests /// /// Verifies the bootstrapper is valid. /// - [Fact(Skip="Needs investigated")] + [Fact] public void VerifyBootstrapperIsValid() { Mock hostingEnvironment = new Mock(); @@ -74,6 +74,7 @@ private void AddTestRegistrations(IServiceCollection services, services.AddSingleton(diagnosticSource); services.AddSingleton(hostingEnvironment); services.AddSingleton(hostingEnvironment); + services.AddSingleton(Startup.Configuration); } #endregion diff --git a/TransactionProcessor.VoucherAggregate.Tests/TransactionProcessor.VoucherAggregate.Tests.csproj b/TransactionProcessor.VoucherAggregate.Tests/TransactionProcessor.VoucherAggregate.Tests.csproj index 2fc452de..c8c6da4a 100644 --- a/TransactionProcessor.VoucherAggregate.Tests/TransactionProcessor.VoucherAggregate.Tests.csproj +++ b/TransactionProcessor.VoucherAggregate.Tests/TransactionProcessor.VoucherAggregate.Tests.csproj @@ -4,7 +4,7 @@ net7.0 enable enable - + None false diff --git a/TransactionProcessor.sln b/TransactionProcessor.sln index a361e4a5..b2c7deef 100644 --- a/TransactionProcessor.sln +++ b/TransactionProcessor.sln @@ -53,16 +53,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TransactionProcessor.Vouche EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TransactionProcessor.VoucherAggregate.Tests", "TransactionProcessor.VoucherAggregate.Tests\TransactionProcessor.VoucherAggregate.Tests.csproj", "{7A31BE33-D9CC-41C7-837E-72FC14333212}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AD0B19E7-39FD-4D69-947D-E4307C872B59}" - ProjectSection(SolutionItems) = preProject - .github\workflows\buildwindowsimage.yml = .github\workflows\buildwindowsimage.yml - .github\workflows\createrelease.yml = .github\workflows\createrelease.yml - .github\workflows\nightlybuild.yml = .github\workflows\nightlybuild.yml - .github\workflows\pullrequest.yml = .github\workflows\pullrequest.yml - .github\workflows\pushtomaster.yml = .github\workflows\pushtomaster.yml - .github\workflows\release-management.yml = .github\workflows\release-management.yml - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/TransactionProcessor/TransactionProcessor - Backup (1).csproj b/TransactionProcessor/TransactionProcessor - Backup (1).csproj deleted file mode 100644 index be621bff..00000000 --- a/TransactionProcessor/TransactionProcessor - Backup (1).csproj +++ /dev/null @@ -1,75 +0,0 @@ - - - - net7.0 - Linux - - - - D:\Projects\StuartFerguson\TransactionProcessor\TransactionProcessor\TransactionProcessor.xml - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - - - - dockerfile - - - - diff --git a/TransactionProcessor/TransactionProcessor - Backup.csproj b/TransactionProcessor/TransactionProcessor - Backup.csproj deleted file mode 100644 index e0aee85f..00000000 --- a/TransactionProcessor/TransactionProcessor - Backup.csproj +++ /dev/null @@ -1,75 +0,0 @@ - - - - net7.0 - Linux - - - - D:\Projects\StuartFerguson\TransactionProcessor\TransactionProcessor\TransactionProcessor.xml - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - - - - dockerfile - - - - From f4088ce39db55675d523b0c83ab4076df1a7d72b Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Mon, 2 Jan 2023 05:52:12 +0000 Subject: [PATCH 2/3] code review issues --- .../Mediator/DummySettlementDomainService.cs | 16 ++++ .../Mediator/DummyTransactionDomainService.cs | 54 +++++++++++++ .../Mediator/DummyVoucherDomainService.cs | 29 +++++++ .../Mediator/MediatorTests.cs | 79 ------------------- 4 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 TransactionProcessor.BusinessLogic.Tests/Mediator/DummySettlementDomainService.cs create mode 100644 TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs create mode 100644 TransactionProcessor.BusinessLogic.Tests/Mediator/DummyVoucherDomainService.cs diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummySettlementDomainService.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummySettlementDomainService.cs new file mode 100644 index 00000000..31fb049d --- /dev/null +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummySettlementDomainService.cs @@ -0,0 +1,16 @@ +namespace TransactionProcessor.BusinessLogic.Tests.Mediator; + +using System; +using System.Threading; +using System.Threading.Tasks; +using BusinessLogic.Services; +using Models; + +public class DummySettlementDomainService : ISettlementDomainService +{ + public async Task ProcessSettlement(DateTime pendingSettlementDate, + Guid estateId, + CancellationToken cancellationToken) { + return new ProcessSettlementResponse(); + } +} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs new file mode 100644 index 00000000..9973e379 --- /dev/null +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs @@ -0,0 +1,54 @@ +namespace TransactionProcessor.BusinessLogic.Tests.Mediator; + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using BusinessLogic.Services; +using Models; + +public class DummyTransactionDomainService : ITransactionDomainService +{ + public async Task ProcessLogonTransaction(Guid transactionId, + Guid estateId, + Guid merchantId, + DateTime transactionDateTime, + String transactionNumber, + String deviceIdentifier, + CancellationToken cancellationToken) { + return new ProcessLogonTransactionResponse(); + } + + public async Task ProcessSaleTransaction(Guid transactionId, + Guid estateId, + Guid merchantId, + DateTime transactionDateTime, + String transactionNumber, + String deviceIdentifier, + String operatorId, + String customerEmailAddress, + Dictionary additionalTransactionMetadata, + Guid contractId, + Guid productId, + Int32 transactionSource, + CancellationToken cancellationToken) { + return new ProcessSaleTransactionResponse(); + } + + public async Task ProcessReconciliationTransaction(Guid transactionId, + Guid estateId, + Guid merchantId, + String deviceIdentifier, + DateTime transactionDateTime, + Int32 transactionCount, + Decimal transactionValue, + CancellationToken cancellationToken) { + return new ProcessReconciliationTransactionResponse(); + } + + public async Task ResendTransactionReceipt(Guid transactionId, + Guid estateId, + CancellationToken cancellationToken) { + + } +} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyVoucherDomainService.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyVoucherDomainService.cs new file mode 100644 index 00000000..c8d34247 --- /dev/null +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyVoucherDomainService.cs @@ -0,0 +1,29 @@ +namespace TransactionProcessor.BusinessLogic.Tests.Mediator; + +using System; +using System.Threading; +using System.Threading.Tasks; +using BusinessLogic.Services; +using Models; + +public class DummyVoucherDomainService : IVoucherDomainService +{ + public async Task IssueVoucher(Guid voucherId, + String operatorId, + Guid estateId, + Guid transactionId, + DateTime issuedDateTime, + Decimal value, + String recipientEmail, + String recipientMobile, + CancellationToken cancellationToken) { + return new IssueVoucherResponse(); + } + + public async Task RedeemVoucher(Guid estateId, + String voucherCode, + DateTime redeemedDateTime, + CancellationToken cancellationToken) { + return new RedeemVoucherResponse(); + } +} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs index c132574d..4ce02bc1 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs @@ -13,11 +13,9 @@ namespace TransactionProcessor.BusinessLogic.Tests.Mediator { - using System.Threading; using BusinessLogic.Services; using Lamar; using Microsoft.Extensions.DependencyInjection; - using Models; using Testing; public class MediatorTests @@ -98,81 +96,4 @@ private void AddTestRegistrations(ServiceRegistry services, }); } } - - public class DummySettlementDomainService : ISettlementDomainService - { - public async Task ProcessSettlement(DateTime pendingSettlementDate, - Guid estateId, - CancellationToken cancellationToken) { - return new ProcessSettlementResponse(); - } - } - - public class DummyVoucherDomainService : IVoucherDomainService - { - public async Task IssueVoucher(Guid voucherId, - String operatorId, - Guid estateId, - Guid transactionId, - DateTime issuedDateTime, - Decimal value, - String recipientEmail, - String recipientMobile, - CancellationToken cancellationToken) { - return new IssueVoucherResponse(); - } - - public async Task RedeemVoucher(Guid estateId, - String voucherCode, - DateTime redeemedDateTime, - CancellationToken cancellationToken) { - return new RedeemVoucherResponse(); - } - } - - public class DummyTransactionDomainService : ITransactionDomainService - { - public async Task ProcessLogonTransaction(Guid transactionId, - Guid estateId, - Guid merchantId, - DateTime transactionDateTime, - String transactionNumber, - String deviceIdentifier, - CancellationToken cancellationToken) { - return new ProcessLogonTransactionResponse(); - } - - public async Task ProcessSaleTransaction(Guid transactionId, - Guid estateId, - Guid merchantId, - DateTime transactionDateTime, - String transactionNumber, - String deviceIdentifier, - String operatorId, - String customerEmailAddress, - Dictionary additionalTransactionMetadata, - Guid contractId, - Guid productId, - Int32 transactionSource, - CancellationToken cancellationToken) { - return new ProcessSaleTransactionResponse(); - } - - public async Task ProcessReconciliationTransaction(Guid transactionId, - Guid estateId, - Guid merchantId, - String deviceIdentifier, - DateTime transactionDateTime, - Int32 transactionCount, - Decimal transactionValue, - CancellationToken cancellationToken) { - return new ProcessReconciliationTransactionResponse(); - } - - public async Task ResendTransactionReceipt(Guid transactionId, - Guid estateId, - CancellationToken cancellationToken) { - - } - } } From f201d1174a8ecf9878d8cca7d3ae67be9ecdf2d2 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Mon, 2 Jan 2023 06:16:00 +0000 Subject: [PATCH 3/3] Last review issue --- .../Mediator/DummyTransactionDomainService.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs index 9973e379..9f89921c 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyTransactionDomainService.cs @@ -48,7 +48,6 @@ public async Task ProcessReconciliatio public async Task ResendTransactionReceipt(Guid transactionId, Guid estateId, - CancellationToken cancellationToken) { - + CancellationToken cancellationToken) { } -} \ No newline at end of file +}