From a92a88f25c486bc46418152368060ef00751403d Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Thu, 23 Jul 2020 15:36:43 +0100 Subject: [PATCH] Updated request to take in Product Details --- .../RequestHandlerTests.cs | 2 + .../RequestTests.cs | 6 +- ...tionProcessorACLApplicationServiceTests.cs | 4 + .../ProcessSaleTransactionRequestHandler.cs | 2 + .../Requests/ProcessSaleTransactionRequest.cs | 37 ++- ...ansactionProcessorACLApplicationService.cs | 4 + ...ansactionProcessorACLApplicationService.cs | 8 + ...ansactionProcessorACL.BusinessLogic.csproj | 2 +- .../Requests/SaleTransactionRequestMessage.cs | 22 +- .../Common/ClientDetails.cs | 27 ++ .../Common/Contract.cs | 97 ++++++ .../Common/EstateDetails.cs | 218 +++++++++++++ .../Common/Product.cs | 106 +++++++ .../Common/SpecflowTableHelper.cs | 117 ++++--- .../Common/TestingContext.cs | 294 +++++++----------- .../Common/TransactionFee.cs | 44 +++ .../SaleTransaction/SalesTransaction.feature | 29 +- .../SalesTransaction.feature.cs | 200 ++++++++---- .../Shared/SharedSteps.cs | 140 ++++++++- ...actionProcessorACL.IntegrationTests.csproj | 4 +- TransactionProcessorACL.Testing/TestData.cs | 8 +- .../Controllers/TransactionController.cs | 4 +- 22 files changed, 1067 insertions(+), 308 deletions(-) create mode 100644 TransactionProcessorACL.IntegrationTests/Common/ClientDetails.cs create mode 100644 TransactionProcessorACL.IntegrationTests/Common/Contract.cs create mode 100644 TransactionProcessorACL.IntegrationTests/Common/EstateDetails.cs create mode 100644 TransactionProcessorACL.IntegrationTests/Common/Product.cs create mode 100644 TransactionProcessorACL.IntegrationTests/Common/TransactionFee.cs diff --git a/TransactionProcessorACL.BusinessLogic.Tests/RequestHandlerTests.cs b/TransactionProcessorACL.BusinessLogic.Tests/RequestHandlerTests.cs index 1244958..6803dc9 100644 --- a/TransactionProcessorACL.BusinessLogic.Tests/RequestHandlerTests.cs +++ b/TransactionProcessorACL.BusinessLogic.Tests/RequestHandlerTests.cs @@ -59,6 +59,8 @@ public async Task ProcessSaleTransactionRequestHandler_Handle_RequestIsHandled() It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny())).ReturnsAsync(TestData.ProcessSaleTransactionResponse); ProcessSaleTransactionRequestHandler requestHandler = new ProcessSaleTransactionRequestHandler(applicationService.Object); diff --git a/TransactionProcessorACL.BusinessLogic.Tests/RequestTests.cs b/TransactionProcessorACL.BusinessLogic.Tests/RequestTests.cs index dcefcea..c0e3401 100644 --- a/TransactionProcessorACL.BusinessLogic.Tests/RequestTests.cs +++ b/TransactionProcessorACL.BusinessLogic.Tests/RequestTests.cs @@ -44,7 +44,9 @@ public void ProcessSaleTransactionRequest_CanBeCreated_IsCreated() TestData.OperatorIdentifier, TestData.SaleAmount, TestData.CustomerAccountNumber, - TestData.CustomerEmailAddress); + TestData.CustomerEmailAddress, + TestData.ContractId, + TestData.ProductId); request.EstateId.ShouldBe(TestData.EstateId); request.MerchantId.ShouldBe(TestData.MerchantId); @@ -55,6 +57,8 @@ public void ProcessSaleTransactionRequest_CanBeCreated_IsCreated() request.Amount.ShouldBe(TestData.SaleAmount); request.CustomerAccountNumber.ShouldBe(TestData.CustomerAccountNumber); request.CustomerEmailAddress.ShouldBe(TestData.CustomerEmailAddress); + request.ContractId.ShouldBe(TestData.ContractId); + request.ProductId.ShouldBe(TestData.ProductId); } #endregion diff --git a/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs b/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs index 237fe54..0747cd7 100644 --- a/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs +++ b/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs @@ -114,6 +114,8 @@ public async Task TransactionProcessorACLApplicationService_ProcessSaleTransacti TestData.SaleAmount, TestData.CustomerAccountNumber, TestData.CustomerEmailAddress, + TestData.ContractId, + TestData.ProductId, CancellationToken.None); saleResponse.ShouldNotBeNull(); @@ -145,6 +147,8 @@ public async Task TransactionProcessorACLApplicationService_ProcessSaleTransacti TestData.SaleAmount, TestData.CustomerAccountNumber, TestData.CustomerEmailAddress, + TestData.ContractId, + TestData.ProductId, CancellationToken.None); saleResponse.ShouldNotBeNull(); diff --git a/TransactionProcessorACL.BusinessLogic/RequestHandlers/ProcessSaleTransactionRequestHandler.cs b/TransactionProcessorACL.BusinessLogic/RequestHandlers/ProcessSaleTransactionRequestHandler.cs index d9ea076..58dc9be 100644 --- a/TransactionProcessorACL.BusinessLogic/RequestHandlers/ProcessSaleTransactionRequestHandler.cs +++ b/TransactionProcessorACL.BusinessLogic/RequestHandlers/ProcessSaleTransactionRequestHandler.cs @@ -53,6 +53,8 @@ public async Task Handle(ProcessSaleTransactionR request.Amount, request.CustomerAccountNumber, request.CustomerEmailAddress, + request.ContractId, + request.ProductId, cancellationToken); } diff --git a/TransactionProcessorACL.BusinessLogic/Requests/ProcessSaleTransactionRequest.cs b/TransactionProcessorACL.BusinessLogic/Requests/ProcessSaleTransactionRequest.cs index f3a9cfb..1b6d8cf 100644 --- a/TransactionProcessorACL.BusinessLogic/Requests/ProcessSaleTransactionRequest.cs +++ b/TransactionProcessorACL.BusinessLogic/Requests/ProcessSaleTransactionRequest.cs @@ -30,6 +30,9 @@ public ProcessSaleTransactionRequest() /// The amount. /// The customer account number. /// The customer email address. + /// The contract identifier. + /// The product identifier. + /// The . private ProcessSaleTransactionRequest(Guid estateId, Guid merchantId, DateTime transactionDateTime, @@ -38,7 +41,9 @@ private ProcessSaleTransactionRequest(Guid estateId, String operatorIdentifier, Decimal amount, String customerAccountNumber, - String customerEmailAddress) + String customerEmailAddress, + Guid contractId, + Guid productId) { this.EstateId = estateId; this.MerchantId = merchantId; @@ -47,10 +52,12 @@ private ProcessSaleTransactionRequest(Guid estateId, this.Amount = amount; this.CustomerAccountNumber = customerAccountNumber; this.CustomerEmailAddress = customerEmailAddress; + this.ContractId = contractId; + this.ProductId = productId; this.TransactionDateTime = transactionDateTime; this.TransactionNumber = transactionNumber; } - + #endregion #region Properties @@ -79,6 +86,22 @@ private ProcessSaleTransactionRequest(Guid estateId, /// public String CustomerEmailAddress { get; private set; } + /// + /// Gets the contract identifier. + /// + /// + /// The contract identifier. + /// + public Guid ContractId { get; } + + /// + /// Gets the product identifier. + /// + /// + /// The product identifier. + /// + public Guid ProductId { get; } + /// /// Gets the device identifier. /// @@ -143,6 +166,8 @@ private ProcessSaleTransactionRequest(Guid estateId, /// The amount. /// The customer account number. /// The customer email address. + /// The contract identifier. + /// The product identifier. /// public static ProcessSaleTransactionRequest Create(Guid estateId, Guid merchantId, @@ -152,7 +177,9 @@ public static ProcessSaleTransactionRequest Create(Guid estateId, String operatorIdentifier, Decimal amount, String customerAccountNumber, - String customerEmailAddress) + String customerEmailAddress, + Guid contractId, + Guid productId) { return new ProcessSaleTransactionRequest(estateId, merchantId, @@ -162,7 +189,9 @@ public static ProcessSaleTransactionRequest Create(Guid estateId, operatorIdentifier, amount, customerAccountNumber, - customerEmailAddress); + customerEmailAddress, + contractId, + productId); } #endregion diff --git a/TransactionProcessorACL.BusinessLogic/Services/ITransactionProcessorACLApplicationService.cs b/TransactionProcessorACL.BusinessLogic/Services/ITransactionProcessorACLApplicationService.cs index 49eb33e..29e82f0 100644 --- a/TransactionProcessorACL.BusinessLogic/Services/ITransactionProcessorACLApplicationService.cs +++ b/TransactionProcessorACL.BusinessLogic/Services/ITransactionProcessorACLApplicationService.cs @@ -40,6 +40,8 @@ Task ProcessLogonTransaction(Guid estateId, /// The amount. /// The customer account number. /// The customer email address. + /// The contract identifier. + /// The product identifier. /// The cancellation token. /// Task ProcessSaleTransaction(Guid estateId, @@ -51,6 +53,8 @@ Task ProcessSaleTransaction(Guid estateId, Decimal amount, String customerAccountNumber, String customerEmailAddress, + Guid contractId, + Guid productId, CancellationToken cancellationToken); } } diff --git a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs index 0ce02ad..e1c5959 100644 --- a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs +++ b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs @@ -135,6 +135,8 @@ public async Task ProcessLogonTransaction(Guid /// The amount. /// The customer account number. /// The customer email address. + /// The contract identifier. + /// The product identifier. /// The cancellation token. /// public async Task ProcessSaleTransaction(Guid estateId, @@ -146,6 +148,8 @@ public async Task ProcessSaleTransaction(Guid es Decimal amount, String customerAccountNumber, String customerEmailAddress, + Guid contractId, + Guid productId, CancellationToken cancellationToken) { // Get a client token to call the Transaction Processor @@ -162,6 +166,10 @@ public async Task ProcessSaleTransaction(Guid es saleTransactionRequest.OperatorIdentifier = operatorIdentifier; saleTransactionRequest.CustomerEmailAddress = customerEmailAddress; + // Set the product information + saleTransactionRequest.ContractId = contractId; + saleTransactionRequest.ProductId = productId; + // Build up the metadata saleTransactionRequest.AdditionalTransactionMetadata = new Dictionary(); saleTransactionRequest.AdditionalTransactionMetadata.Add("Amount", amount.ToString()); diff --git a/TransactionProcessorACL.BusinessLogic/TransactionProcessorACL.BusinessLogic.csproj b/TransactionProcessorACL.BusinessLogic/TransactionProcessorACL.BusinessLogic.csproj index a93dbcb..62062c5 100644 --- a/TransactionProcessorACL.BusinessLogic/TransactionProcessorACL.BusinessLogic.csproj +++ b/TransactionProcessorACL.BusinessLogic/TransactionProcessorACL.BusinessLogic.csproj @@ -8,7 +8,7 @@ - + diff --git a/TransactionProcessorACL.DataTransferObjects/Requests/SaleTransactionRequestMessage.cs b/TransactionProcessorACL.DataTransferObjects/Requests/SaleTransactionRequestMessage.cs index 1981d2e..c493e04 100644 --- a/TransactionProcessorACL.DataTransferObjects/Requests/SaleTransactionRequestMessage.cs +++ b/TransactionProcessorACL.DataTransferObjects/Requests/SaleTransactionRequestMessage.cs @@ -20,6 +20,14 @@ public class SaleTransactionRequestMessage : TransactionRequestMessage /// public Decimal Amount { get; set; } + /// + /// Gets or sets the contract identifier. + /// + /// + /// The contract identifier. + /// + public Guid ContractId { get; set; } + /// /// Gets or sets the customer account number. /// @@ -28,6 +36,14 @@ public class SaleTransactionRequestMessage : TransactionRequestMessage /// public String CustomerAccountNumber { get; set; } + /// + /// Gets or sets the customer email address. + /// + /// + /// The customer email address. + /// + public String CustomerEmailAddress { get; set; } + /// /// Gets or sets the operator identifier. /// @@ -37,12 +53,12 @@ public class SaleTransactionRequestMessage : TransactionRequestMessage public String OperatorIdentifier { get; set; } /// - /// Gets or sets the customer email address. + /// Gets or sets the product identifier. /// /// - /// The customer email address. + /// The product identifier. /// - public String CustomerEmailAddress { get; set; } + public Guid ProductId { get; set; } #endregion } diff --git a/TransactionProcessorACL.IntegrationTests/Common/ClientDetails.cs b/TransactionProcessorACL.IntegrationTests/Common/ClientDetails.cs new file mode 100644 index 0000000..3d51c34 --- /dev/null +++ b/TransactionProcessorACL.IntegrationTests/Common/ClientDetails.cs @@ -0,0 +1,27 @@ +namespace TransactionProcessor.IntegrationTests.Common +{ + using System; + + public class ClientDetails + { + public String ClientId { get; private set; } + public String ClientSecret { get; private set; } + public String GrantType { get; private set; } + + private ClientDetails(String clientId, + String clientSecret, + String grantType) + { + this.ClientId = clientId; + this.ClientSecret = clientSecret; + this.GrantType = grantType; + } + + public static ClientDetails Create(String clientId, + String clientSecret, + String grantType) + { + return new ClientDetails(clientId, clientSecret, grantType); + } + } +} \ No newline at end of file diff --git a/TransactionProcessorACL.IntegrationTests/Common/Contract.cs b/TransactionProcessorACL.IntegrationTests/Common/Contract.cs new file mode 100644 index 0000000..3e83017 --- /dev/null +++ b/TransactionProcessorACL.IntegrationTests/Common/Contract.cs @@ -0,0 +1,97 @@ +namespace TransactionProcessor.IntegrationTests.Common +{ + using System; + using System.Collections.Generic; + using System.Linq; + + public class Contract + { + #region Properties + + /// + /// Gets or sets the contract identifier. + /// + /// + /// The contract identifier. + /// + public Guid ContractId { get; set; } + + /// + /// Gets or sets the description. + /// + /// + /// The description. + /// + public String Description { get; set; } + + /// + /// Gets or sets the operator identifier. + /// + /// + /// The operator identifier. + /// + public Guid OperatorId { get; set; } + + /// + /// Gets or sets the products. + /// + /// + /// The products. + /// + public List Products { get; set; } + + #endregion + + #region Methods + + /// + /// Adds the product. + /// + /// The product identifier. + /// The name. + /// The display text. + /// The value. + public void AddProduct(Guid productId, + String name, + String displayText, + Decimal? value = null) + { + Product product = new Product + { + ProductId = productId, + DisplayText = displayText, + Name = name, + Value = value + }; + + if (this.Products == null) + { + this.Products = new List(); + } + + this.Products.Add(product); + } + + /// + /// Gets the product. + /// + /// The product identifier. + /// + public Product GetProduct(Guid productId) + { + return this.Products.SingleOrDefault(p => p.ProductId == productId); + } + + /// + /// Gets the product. + /// + /// The name. + /// + public Product GetProduct(String name) + { + return this.Products.SingleOrDefault(p => p.Name == name); + } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessorACL.IntegrationTests/Common/EstateDetails.cs b/TransactionProcessorACL.IntegrationTests/Common/EstateDetails.cs new file mode 100644 index 0000000..53b7378 --- /dev/null +++ b/TransactionProcessorACL.IntegrationTests/Common/EstateDetails.cs @@ -0,0 +1,218 @@ +namespace TransactionProcessor.IntegrationTests.Common +{ + using System; + using System.Collections.Generic; + using System.Linq; + + public class EstateDetails + { + #region Fields + + /// + /// The contracts + /// + private readonly List Contracts; + + private readonly Dictionary Merchants; + + private readonly Dictionary> MerchantUsers; + + private readonly Dictionary> MerchantUsersTokens; + + private readonly Dictionary Operators; + + #endregion + + #region Constructors + + private EstateDetails(Guid estateId, + String estateName) + { + this.EstateId = estateId; + this.EstateName = estateName; + this.Merchants = new Dictionary(); + this.Operators = new Dictionary(); + this.MerchantUsers = new Dictionary>(); + this.MerchantUsersTokens = new Dictionary>(); + this.TransactionResponses = new Dictionary<(Guid merchantId, String transactionNumber, String transactionType), String>(); + this.Contracts = new List(); + } + + #endregion + + #region Properties + + public String AccessToken { get; private set; } + + public Guid EstateId { get; } + + public String EstateName { get; } + + public String EstatePassword { get; private set; } + + public String EstateUser { get; private set; } + + private Dictionary<(Guid merchantId, String transactionNumber, String transactionType), String> TransactionResponses { get; } + + #endregion + + #region Methods + + /// + /// Adds the contract. + /// + /// The contract identifier. + /// Name of the contract. + /// The operator identifier. + public void AddContract(Guid contractId, + String contractName, + Guid operatorId) + { + this.Contracts.Add(new Contract + { + ContractId = contractId, + Description = contractName, + OperatorId = operatorId, + }); + } + + public void AddMerchant(Guid merchantId, + String merchantName) + { + this.Merchants.Add(merchantName, merchantId); + } + + public void AddMerchantUser(String merchantName, + String userName, + String password) + { + if (this.MerchantUsers.ContainsKey(merchantName)) + { + Dictionary merchantUsersList = this.MerchantUsers[merchantName]; + if (merchantUsersList.ContainsKey(userName) == false) + { + merchantUsersList.Add(userName, password); + } + } + else + { + Dictionary merchantUsersList = new Dictionary(); + merchantUsersList.Add(userName, password); + this.MerchantUsers.Add(merchantName, merchantUsersList); + } + } + + public void AddMerchantUserToken(String merchantName, + String userName, + String token) + { + if (this.MerchantUsersTokens.ContainsKey(merchantName)) + { + Dictionary merchantUsersList = this.MerchantUsersTokens[merchantName]; + if (merchantUsersList.ContainsKey(userName) == false) + { + merchantUsersList.Add(userName, token); + } + } + else + { + Dictionary merchantUsersList = new Dictionary(); + merchantUsersList.Add(userName, token); + this.MerchantUsersTokens.Add(merchantName, merchantUsersList); + } + } + + public void AddOperator(Guid operatorId, + String operatorName) + { + this.Operators.Add(operatorName, operatorId); + } + + public void AddTransactionResponse(Guid merchantId, + String transactionNumber, + String transactionType, + String transactionResponse) + { + this.TransactionResponses.Add((merchantId, transactionNumber, transactionType), transactionResponse); + } + + public static EstateDetails Create(Guid estateId, + String estateName) + { + return new EstateDetails(estateId, estateName); + } + + /// + /// Gets the contract. + /// + /// Name of the contract. + /// + public Contract GetContract(String contractName) + { + if (this.Contracts.Any() == false) + { + return null; + } + + return this.Contracts.Single(c => c.Description == contractName); + } + + /// + /// Gets the contract. + /// + /// The contract identifier. + /// + public Contract GetContract(Guid contractId) + { + return this.Contracts.Single(c => c.ContractId == contractId); + } + + public Guid GetMerchantId(String merchantName) + { + return this.Merchants.Single(m => m.Key == merchantName).Value; + } + + public String GetMerchantUserToken(String merchantName) + { + KeyValuePair> x = this.MerchantUsersTokens.SingleOrDefault(x => x.Key == merchantName); + + if (x.Value != null) + { + return x.Value.First().Value; + } + + return string.Empty; + } + + public Guid GetOperatorId(String operatorName) + { + return this.Operators.Single(o => o.Key == operatorName).Value; + } + + public String GetTransactionResponse(Guid merchantId, + String transactionNumber, + String transactionType) + { + KeyValuePair<(Guid merchantId, String transactionNumber, String transactionType), String> transactionResponse = + this.TransactionResponses + .Where(t => t.Key.merchantId == merchantId && t.Key.transactionNumber == transactionNumber && t.Key.transactionType == transactionType) + .SingleOrDefault(); + + return transactionResponse.Value; + } + + public void SetEstateUser(String userName, + String password) + { + this.EstateUser = userName; + this.EstatePassword = password; + } + + public void SetEstateUserToken(String accessToken) + { + this.AccessToken = accessToken; + } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessorACL.IntegrationTests/Common/Product.cs b/TransactionProcessorACL.IntegrationTests/Common/Product.cs new file mode 100644 index 0000000..1913190 --- /dev/null +++ b/TransactionProcessorACL.IntegrationTests/Common/Product.cs @@ -0,0 +1,106 @@ +namespace TransactionProcessor.IntegrationTests.Common +{ + using System; + using System.Collections.Generic; + using System.Linq; + using EstateManagement.DataTransferObjects; + + public class Product + { + #region Properties + + /// + /// Gets or sets the display text. + /// + /// + /// The display text. + /// + public String DisplayText { get; set; } + + /// + /// Gets or sets the name. + /// + /// + /// The name. + /// + public String Name { get; set; } + + /// + /// Gets or sets the product identifier. + /// + /// + /// The product identifier. + /// + public Guid ProductId { get; set; } + + /// + /// Gets or sets the transaction fees. + /// + /// + /// The transaction fees. + /// + public List TransactionFees { get; set; } + + /// + /// Gets or sets the value. + /// + /// + /// The value. + /// + public Decimal? Value { get; set; } + + #endregion + + #region Methods + + /// + /// Adds the transaction fee. + /// + /// The transaction fee identifier. + /// Type of the calculation. + /// The description. + /// The value. + public void AddTransactionFee(Guid transactionFeeId, + CalculationType calculationType, + String description, + Decimal value) + { + TransactionFee transactionFee = new TransactionFee + { + TransactionFeeId = transactionFeeId, + CalculationType = calculationType, + Description = description, + Value = value + }; + + if (this.TransactionFees == null) + { + this.TransactionFees = new List(); + } + + this.TransactionFees.Add(transactionFee); + } + + /// + /// Gets the transaction fee. + /// + /// The transaction fee identifier. + /// + public TransactionFee GetTransactionFee(Guid transactionFeeId) + { + return this.TransactionFees.SingleOrDefault(t => t.TransactionFeeId == transactionFeeId); + } + + /// + /// Gets the transaction fee. + /// + /// The description. + /// + public TransactionFee GetTransactionFee(String description) + { + return this.TransactionFees.SingleOrDefault(t => t.Description == description); + } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessorACL.IntegrationTests/Common/SpecflowTableHelper.cs b/TransactionProcessorACL.IntegrationTests/Common/SpecflowTableHelper.cs index 186b2c4..5ac4f1a 100644 --- a/TransactionProcessorACL.IntegrationTests/Common/SpecflowTableHelper.cs +++ b/TransactionProcessorACL.IntegrationTests/Common/SpecflowTableHelper.cs @@ -10,77 +10,120 @@ public static class SpecflowTableHelper { #region Methods - public static Decimal GetDecimalValue(TableRow row, + /// + /// Gets the boolean value. + /// + /// The row. + /// The key. + /// + public static Boolean GetBooleanValue(TableRow row, String key) { String field = SpecflowTableHelper.GetStringRowValue(row, key); - return Decimal.TryParse(field, out Decimal value) ? value : -1; + return bool.TryParse(field, out Boolean value) && value; } - public static Boolean GetBooleanValue(TableRow row, + /// + /// Gets the date for date string. + /// + /// The date string. + /// The today. + /// + public static DateTime GetDateForDateString(String dateString, + DateTime today) + { + switch (dateString.ToUpper()) + { + case "TODAY": + return today.Date; + case "YESTERDAY": + return today.AddDays(-1).Date; + case "LASTWEEK": + return today.AddDays(-7).Date; + case "LASTMONTH": + return today.AddMonths(-1).Date; + case "LASTYEAR": + return today.AddYears(-1).Date; + case "TOMORROW": + return today.AddDays(1).Date; + default: + return DateTime.Parse(dateString); + } + } + + /// + /// Gets the decimal value. + /// + /// The row. + /// The key. + /// + public static Decimal GetDecimalValue(TableRow row, String key) { String field = SpecflowTableHelper.GetStringRowValue(row, key); - return Boolean.TryParse(field, out Boolean value) && value; + return decimal.TryParse(field, out Decimal value) ? value : -1; + } + + /// + /// Gets the enum value. + /// + /// + /// The row. + /// The key. + /// + public static T GetEnumValue(TableRow row, + String key) where T : struct + { + String field = SpecflowTableHelper.GetStringRowValue(row, key); + + return Enum.Parse(field, true); } + /// + /// Gets the int value. + /// + /// The row. + /// The key. + /// public static Int32 GetIntValue(TableRow row, String key) { String field = SpecflowTableHelper.GetStringRowValue(row, key); - return Int32.TryParse(field, out Int32 value) ? value : -1; + return int.TryParse(field, out Int32 value) ? value : -1; } + /// + /// Gets the short value. + /// + /// The row. + /// The key. + /// public static Int16 GetShortValue(TableRow row, String key) { String field = SpecflowTableHelper.GetStringRowValue(row, key); - if (Int16.TryParse(field, out Int16 value)) + if (short.TryParse(field, out Int16 value)) { return value; } - else - { - return -1; - } - } - public static String GetStringRowValue(TableRow row, - String key) - { - return row.TryGetValue(key, out String value) ? value : ""; + return -1; } /// - /// Gets the date for date string. + /// Gets the string row value. /// - /// The date string. - /// The today. + /// The row. + /// The key. /// - public static DateTime GetDateForDateString(String dateString, - DateTime today) + public static String GetStringRowValue(TableRow row, + String key) { - switch (dateString.ToUpper()) - { - case "TODAY": - return today.Date; - case "YESTERDAY": - return today.AddDays(-1).Date; - case "LASTWEEK": - return today.AddDays(-7).Date; - case "LASTMONTH": - return today.AddMonths(-1).Date; - case "LASTYEAR": - return today.AddYears(-1).Date; - case "TOMORROW": - return today.AddDays(1).Date; - default: - return DateTime.Parse(dateString); - } + return row.TryGetValue(key, out String value) ? value : ""; } #endregion diff --git a/TransactionProcessorACL.IntegrationTests/Common/TestingContext.cs b/TransactionProcessorACL.IntegrationTests/Common/TestingContext.cs index 78b28ae..291feb6 100644 --- a/TransactionProcessorACL.IntegrationTests/Common/TestingContext.cs +++ b/TransactionProcessorACL.IntegrationTests/Common/TestingContext.cs @@ -1,67 +1,80 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace TransactionProcessor.IntegrationTests.Common +namespace TransactionProcessor.IntegrationTests.Common { + using System; + using System.Collections.Generic; using System.Linq; - using DataTransferObjects; using global::Shared.Logger; using Shouldly; using TechTalk.SpecFlow; + /// + /// + /// public class TestingContext { - public TestingContext() - { - this.Estates = new List(); - this.Clients = new List(); - } + #region Fields - public NlogLogger Logger { get; set; } + /// + /// The clients + /// + private readonly List Clients; - public DockerHelper DockerHelper { get; set; } - - private List Clients; + /// + /// The estates + /// + private readonly List Estates; - private List Estates; + #endregion - public String AccessToken { get; set; } + #region Constructors - public EstateDetails GetEstateDetails(TableRow tableRow) + /// + /// Initializes a new instance of the class. + /// + public TestingContext() { - String estateName = SpecflowTableHelper.GetStringRowValue(tableRow, "EstateName"); - - EstateDetails estateDetails = this.Estates.SingleOrDefault(e => e.EstateName == estateName); - - estateDetails.ShouldNotBeNull(); - - return estateDetails; + this.Estates = new List(); + this.Clients = new List(); } - public EstateDetails GetEstateDetails(String estateName) - { - EstateDetails estateDetails = this.Estates.SingleOrDefault(e => e.EstateName == estateName); + #endregion - estateDetails.ShouldNotBeNull(); + #region Properties - return estateDetails; - } + /// + /// Gets or sets the access token. + /// + /// + /// The access token. + /// + public String AccessToken { get; set; } - public EstateDetails GetEstateDetails(Guid estateId) - { - EstateDetails estateDetails = this.Estates.SingleOrDefault(e => e.EstateId == estateId); + /// + /// Gets or sets the docker helper. + /// + /// + /// The docker helper. + /// + public DockerHelper DockerHelper { get; set; } - estateDetails.ShouldNotBeNull(); + /// + /// Gets or sets the logger. + /// + /// + /// The logger. + /// + public NlogLogger Logger { get; set; } - return estateDetails; - } + #endregion - public void AddEstateDetails(Guid estateId, String estateName) - { - this.Estates.Add(EstateDetails.Create(estateId, estateName)); - } + #region Methods + /// + /// Adds the client details. + /// + /// The client identifier. + /// The client secret. + /// Type of the grant. public void AddClientDetails(String clientId, String clientSecret, String grantType) @@ -69,181 +82,84 @@ public void AddClientDetails(String clientId, this.Clients.Add(ClientDetails.Create(clientId, clientSecret, grantType)); } - public ClientDetails GetClientDetails(String clientId) + /// + /// Adds the estate details. + /// + /// The estate identifier. + /// Name of the estate. + public void AddEstateDetails(Guid estateId, + String estateName) { - ClientDetails clientDetails = this.Clients.SingleOrDefault(c => c.ClientId == clientId); - - clientDetails.ShouldNotBeNull(); - - return clientDetails; + this.Estates.Add(EstateDetails.Create(estateId, estateName)); } + /// + /// Gets all estate ids. + /// + /// public List GetAllEstateIds() { return this.Estates.Select(e => e.EstateId).ToList(); } - } - - public class EstateDetails - { - private EstateDetails(Guid estateId, String estateName) - { - this.EstateId = estateId; - this.EstateName = estateName; - this.Merchants = new Dictionary(); - this.Operators = new Dictionary(); - this.MerchantUsers = new Dictionary>(); - this.MerchantUsersTokens = new Dictionary>(); - this.TransactionResponses = new Dictionary<(Guid merchantId, String transactionNumber, String transactionType), String>(); - } - - public void AddTransactionResponse(Guid merchantId, - String transactionNumber, - String transactionType, - String transactionResponse) - { - this.TransactionResponses.Add((merchantId, transactionNumber,transactionType), transactionResponse); - } - public String GetTransactionResponse(Guid merchantId, - String transactionNumber, - String transactionType) + /// + /// Gets the client details. + /// + /// The client identifier. + /// + public ClientDetails GetClientDetails(String clientId) { - KeyValuePair<(Guid merchantId, String transactionNumber, String transactionType), String> transactionResponse = - this.TransactionResponses.Where(t => t.Key.merchantId == merchantId && t.Key.transactionNumber == transactionNumber && t.Key.transactionType == transactionType).SingleOrDefault(); - - return transactionResponse.Value; - } - - private Dictionary<(Guid merchantId, String transactionNumber, String transactionType), String> TransactionResponses { get; set; } - - public String EstateUser { get; private set; } - public String EstatePassword { get; private set; } + ClientDetails clientDetails = this.Clients.SingleOrDefault(c => c.ClientId == clientId); - public String AccessToken { get; private set; } + clientDetails.ShouldNotBeNull(); - public static EstateDetails Create(Guid estateId, - String estateName) - { - return new EstateDetails(estateId, estateName); + return clientDetails; } - public void AddOperator(Guid operatorId, - String operatorName) + /// + /// Gets the estate details. + /// + /// The table row. + /// + public EstateDetails GetEstateDetails(TableRow tableRow) { - this.Operators.Add(operatorName, operatorId); - } + String estateName = SpecflowTableHelper.GetStringRowValue(tableRow, "EstateName"); - public void AddMerchant(Guid merchantId, - String merchantName) - { - this.Merchants.Add(merchantName, merchantId); - } + EstateDetails estateDetails = this.Estates.SingleOrDefault(e => e.EstateName == estateName); - public Guid GetMerchantId(String merchantName) - { - return this.Merchants.Single(m => m.Key == merchantName).Value; - } + estateDetails.ShouldNotBeNull(); - public Guid GetOperatorId(String operatorName) - { - return this.Operators.Single(o => o.Key == operatorName).Value; + return estateDetails; } - public void SetEstateUser(String userName, - String password) + /// + /// Gets the estate details. + /// + /// Name of the estate. + /// + public EstateDetails GetEstateDetails(String estateName) { - this.EstateUser = userName; - this.EstatePassword = password; - } + EstateDetails estateDetails = this.Estates.SingleOrDefault(e => e.EstateName == estateName); - public void AddMerchantUser(String merchantName, - String userName, - String password) - { - if (this.MerchantUsers.ContainsKey(merchantName)) - { - Dictionary merchantUsersList = this.MerchantUsers[merchantName]; - if (merchantUsersList.ContainsKey(userName) == false) - { - merchantUsersList.Add(userName, password); - } - } - else - { - Dictionary merchantUsersList = new Dictionary(); - merchantUsersList.Add(userName, password); - this.MerchantUsers.Add(merchantName, merchantUsersList); - } - } + estateDetails.ShouldNotBeNull(); - public void AddMerchantUserToken(String merchantName, - String userName, - String token) - { - if (this.MerchantUsersTokens.ContainsKey(merchantName)) - { - Dictionary merchantUsersList = this.MerchantUsersTokens[merchantName]; - if (merchantUsersList.ContainsKey(userName) == false) - { - merchantUsersList.Add(userName, token); - } - } - else - { - Dictionary merchantUsersList = new Dictionary(); - merchantUsersList.Add(userName, token); - this.MerchantUsersTokens.Add(merchantName, merchantUsersList); - } + return estateDetails; } - public String GetMerchantUserToken(String merchantName) - { - KeyValuePair> x = this.MerchantUsersTokens.SingleOrDefault(x => x.Key == merchantName); - - if (x.Value != null) - { - return x.Value.First().Value; - } - - return String.Empty; - } - public void SetEstateUserToken(String accessToken) + /// + /// Gets the estate details. + /// + /// The estate identifier. + /// + public EstateDetails GetEstateDetails(Guid estateId) { - this.AccessToken = accessToken; - } - - public Guid EstateId { get; private set; } - public String EstateName { get; private set; } - - private Dictionary Operators; - - private Dictionary Merchants; - - private Dictionary> MerchantUsers; - private Dictionary> MerchantUsersTokens; - } + EstateDetails estateDetails = this.Estates.SingleOrDefault(e => e.EstateId == estateId); - public class ClientDetails - { - public String ClientId { get; private set; } - public String ClientSecret { get; private set; } - public String GrantType { get; private set; } + estateDetails.ShouldNotBeNull(); - private ClientDetails(String clientId, - String clientSecret, - String grantType) - { - this.ClientId = clientId; - this.ClientSecret = clientSecret; - this.GrantType = grantType; + return estateDetails; } - public static ClientDetails Create(String clientId, - String clientSecret, - String grantType) - { - return new ClientDetails(clientId, clientSecret, grantType); - } + #endregion } -} +} \ No newline at end of file diff --git a/TransactionProcessorACL.IntegrationTests/Common/TransactionFee.cs b/TransactionProcessorACL.IntegrationTests/Common/TransactionFee.cs new file mode 100644 index 0000000..2ff4e69 --- /dev/null +++ b/TransactionProcessorACL.IntegrationTests/Common/TransactionFee.cs @@ -0,0 +1,44 @@ +namespace TransactionProcessor.IntegrationTests.Common +{ + using System; + using EstateManagement.DataTransferObjects; + + public class TransactionFee + { + #region Properties + + /// + /// Gets or sets the type of the calculation. + /// + /// + /// The type of the calculation. + /// + public CalculationType CalculationType { get; set; } + + /// + /// Gets or sets the description. + /// + /// + /// The description. + /// + public String Description { get; set; } + + /// + /// Gets or sets the transaction fee identifier. + /// + /// + /// The transaction fee identifier. + /// + public Guid TransactionFeeId { get; set; } + + /// + /// Gets or sets the value. + /// + /// + /// The value. + /// + public Decimal Value { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature b/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature index 4be12ea..e34f6e1 100644 --- a/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature +++ b/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature @@ -32,6 +32,21 @@ Background: | Test Estate 1 | Safaricom | True | True | | Test Estate 2 | Safaricom | True | True | + Given I create a contract with the following values + | EstateName | OperatorName | ContractDescription | + | Test Estate 1 | Safaricom | Safaricom Contract | + | Test Estate 2 | Safaricom | Safaricom Contract | + + When I create the following Products + | EstateName | OperatorName | ContractDescription | ProductName | DisplayText | Value | + | Test Estate 1 | Safaricom | Safaricom Contract | Variable Topup | Custom | | + | Test Estate 2 | Safaricom | Safaricom Contract | Variable Topup | Custom | | + + When I add the following Transaction Fees + | EstateName | OperatorName | ContractDescription | ProductName | CalculationType | FeeDescription | Value | + | Test Estate 1 | Safaricom | Safaricom Contract | Variable Topup | Fixed | Merchant Commission | 2.50 | + | Test Estate 2 | Safaricom | Safaricom Contract | Variable Topup | Percentage | Merchant Commission | 0.85 | + Given I create the following merchants | MerchantName | AddressLine1 | Town | Region | Country | ContactName | EmailAddress | EstateName | | Test Merchant 1 | Address Line 1 | TestTown | Test Region | United Kingdom | Test Contact 1 | testcontact1@merchant1.co.uk | Test Estate 1 | @@ -66,19 +81,19 @@ Background: Scenario: Sale Transaction Given I am logged in as "merchantuser@testmerchant1.co.uk" with password "123456" for Merchant "Test Merchant 1" for Estate "Test Estate 1" with client "merchantClient" When I perform the following transactions - | DateTime | TransactionNumber | TransactionType | MerchantName | DeviceIdentifier | EstateName | OperatorName | TransactionAmount | CustomerAccountNumber | CustomerEmailAddress | - | Today | 1 | Sale | Test Merchant 1 | 123456780 | Test Estate 1 | Safaricom | 1000.00 | 123456789 | | - | Today | 4 | Sale | Test Merchant 1 | 123456780 | Test Estate 1 | Safaricom | 1000.00 | 123456789 | testcustomer@customer.co.uk | + | DateTime | TransactionNumber | TransactionType | MerchantName | DeviceIdentifier | EstateName | OperatorName | TransactionAmount | CustomerAccountNumber | CustomerEmailAddress | ContractDescription | ProductName | + | Today | 1 | Sale | Test Merchant 1 | 123456780 | Test Estate 1 | Safaricom | 1000.00 | 123456789 | | Safaricom Contract | Variable Topup | + | Today | 4 | Sale | Test Merchant 1 | 123456780 | Test Estate 1 | Safaricom | 1000.00 | 123456789 | testcustomer@customer.co.uk | Safaricom Contract | Variable Topup | Given I am logged in as "merchantuser@testmerchant2.co.uk" with password "123456" for Merchant "Test Merchant 2" for Estate "Test Estate 1" with client "merchantClient" When I perform the following transactions - | DateTime | TransactionNumber | TransactionType | MerchantName | DeviceIdentifier | EstateName | OperatorName | TransactionAmount | CustomerAccountNumber | CustomerEmailAddress | - | Today | 2 | Sale | Test Merchant 2 | 123456781 | Test Estate 1 | Safaricom | 1000.00 | 123456789 | | + | DateTime | TransactionNumber | TransactionType | MerchantName | DeviceIdentifier | EstateName | OperatorName | TransactionAmount | CustomerAccountNumber | CustomerEmailAddress | ContractDescription | ProductName | + | Today | 2 | Sale | Test Merchant 2 | 123456781 | Test Estate 1 | Safaricom | 1000.00 | 123456789 | | Safaricom Contract | Variable Topup | Given I am logged in as "merchantuser@testmerchant3.co.uk" with password "123456" for Merchant "Test Merchant 3" for Estate "Test Estate 2" with client "merchantClient" When I perform the following transactions - | DateTime | TransactionNumber | TransactionType | MerchantName | DeviceIdentifier | EstateName | OperatorName | TransactionAmount | CustomerAccountNumber | CustomerEmailAddress | - | Today | 3 | Sale | Test Merchant 3 | 123456782 | Test Estate 2 | Safaricom | 1000.00 | 123456789 | | + | DateTime | TransactionNumber | TransactionType | MerchantName | DeviceIdentifier | EstateName | OperatorName | TransactionAmount | CustomerAccountNumber | CustomerEmailAddress | ContractDescription | ProductName | + | Today | 3 | Sale | Test Merchant 3 | 123456782 | Test Estate 2 | Safaricom | 1000.00 | 123456789 | | Safaricom Contract | Variable Topup | Then transaction response should contain the following information | EstateName | MerchantName | TransactionNumber | TransactionType | ResponseCode | ResponseMessage | diff --git a/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature.cs b/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature.cs index a6dc75a..9ed4894 100644 --- a/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature.cs +++ b/TransactionProcessorACL.IntegrationTests/SaleTransaction/SalesTransaction.feature.cs @@ -176,6 +176,72 @@ public virtual void FeatureBackground() testRunner.Given("I have created the following operators", ((string)(null)), table19, "Given "); #line hidden TechTalk.SpecFlow.Table table20 = new TechTalk.SpecFlow.Table(new string[] { + "EstateName", + "OperatorName", + "ContractDescription"}); + table20.AddRow(new string[] { + "Test Estate 1", + "Safaricom", + "Safaricom Contract"}); + table20.AddRow(new string[] { + "Test Estate 2", + "Safaricom", + "Safaricom Contract"}); +#line 35 + testRunner.Given("I create a contract with the following values", ((string)(null)), table20, "Given "); +#line hidden + TechTalk.SpecFlow.Table table21 = new TechTalk.SpecFlow.Table(new string[] { + "EstateName", + "OperatorName", + "ContractDescription", + "ProductName", + "DisplayText", + "Value"}); + table21.AddRow(new string[] { + "Test Estate 1", + "Safaricom", + "Safaricom Contract", + "Variable Topup", + "Custom", + ""}); + table21.AddRow(new string[] { + "Test Estate 2", + "Safaricom", + "Safaricom Contract", + "Variable Topup", + "Custom", + ""}); +#line 40 + testRunner.When("I create the following Products", ((string)(null)), table21, "When "); +#line hidden + TechTalk.SpecFlow.Table table22 = new TechTalk.SpecFlow.Table(new string[] { + "EstateName", + "OperatorName", + "ContractDescription", + "ProductName", + "CalculationType", + "FeeDescription", + "Value"}); + table22.AddRow(new string[] { + "Test Estate 1", + "Safaricom", + "Safaricom Contract", + "Variable Topup", + "Fixed", + "Merchant Commission", + "2.50"}); + table22.AddRow(new string[] { + "Test Estate 2", + "Safaricom", + "Safaricom Contract", + "Variable Topup", + "Percentage", + "Merchant Commission", + "0.85"}); +#line 45 + testRunner.When("I add the following Transaction Fees", ((string)(null)), table22, "When "); +#line hidden + TechTalk.SpecFlow.Table table23 = new TechTalk.SpecFlow.Table(new string[] { "MerchantName", "AddressLine1", "Town", @@ -184,7 +250,7 @@ public virtual void FeatureBackground() "ContactName", "EmailAddress", "EstateName"}); - table20.AddRow(new string[] { + table23.AddRow(new string[] { "Test Merchant 1", "Address Line 1", "TestTown", @@ -193,7 +259,7 @@ public virtual void FeatureBackground() "Test Contact 1", "testcontact1@merchant1.co.uk", "Test Estate 1"}); - table20.AddRow(new string[] { + table23.AddRow(new string[] { "Test Merchant 2", "Address Line 1", "TestTown", @@ -202,7 +268,7 @@ public virtual void FeatureBackground() "Test Contact 2", "testcontact2@merchant2.co.uk", "Test Estate 1"}); - table20.AddRow(new string[] { + table23.AddRow(new string[] { "Test Merchant 3", "Address Line 1", "TestTown", @@ -211,112 +277,112 @@ public virtual void FeatureBackground() "Test Contact 3", "testcontact3@merchant2.co.uk", "Test Estate 2"}); -#line 35 - testRunner.Given("I create the following merchants", ((string)(null)), table20, "Given "); +#line 50 + testRunner.Given("I create the following merchants", ((string)(null)), table23, "Given "); #line hidden - TechTalk.SpecFlow.Table table21 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table24 = new TechTalk.SpecFlow.Table(new string[] { "EmailAddress", "Password", "GivenName", "FamilyName", "EstateName", "MerchantName"}); - table21.AddRow(new string[] { + table24.AddRow(new string[] { "merchantuser@testmerchant1.co.uk", "123456", "TestMerchant", "User1", "Test Estate 1", "Test Merchant 1"}); - table21.AddRow(new string[] { + table24.AddRow(new string[] { "merchantuser@testmerchant2.co.uk", "123456", "TestMerchant", "User2", "Test Estate 1", "Test Merchant 2"}); - table21.AddRow(new string[] { + table24.AddRow(new string[] { "merchantuser@testmerchant3.co.uk", "123456", "TestMerchant", "User3", "Test Estate 2", "Test Merchant 3"}); -#line 41 - testRunner.Given("I have created the following security users", ((string)(null)), table21, "Given "); +#line 56 + testRunner.Given("I have created the following security users", ((string)(null)), table24, "Given "); #line hidden - TechTalk.SpecFlow.Table table22 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table25 = new TechTalk.SpecFlow.Table(new string[] { "OperatorName", "MerchantName", "MerchantNumber", "TerminalNumber", "EstateName"}); - table22.AddRow(new string[] { + table25.AddRow(new string[] { "Safaricom", "Test Merchant 1", "00000001", "10000001", "Test Estate 1"}); - table22.AddRow(new string[] { + table25.AddRow(new string[] { "Safaricom", "Test Merchant 2", "00000002", "10000002", "Test Estate 1"}); - table22.AddRow(new string[] { + table25.AddRow(new string[] { "Safaricom", "Test Merchant 3", "00000003", "10000003", "Test Estate 2"}); -#line 47 - testRunner.Given("I have assigned the following operator to the merchants", ((string)(null)), table22, "Given "); +#line 62 + testRunner.Given("I have assigned the following operator to the merchants", ((string)(null)), table25, "Given "); #line hidden - TechTalk.SpecFlow.Table table23 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table26 = new TechTalk.SpecFlow.Table(new string[] { "DeviceIdentifier", "MerchantName", "EstateName"}); - table23.AddRow(new string[] { + table26.AddRow(new string[] { "123456780", "Test Merchant 1", "Test Estate 1"}); - table23.AddRow(new string[] { + table26.AddRow(new string[] { "123456781", "Test Merchant 2", "Test Estate 1"}); - table23.AddRow(new string[] { + table26.AddRow(new string[] { "123456782", "Test Merchant 3", "Test Estate 2"}); -#line 53 - testRunner.Given("I have assigned the following devices to the merchants", ((string)(null)), table23, "Given "); +#line 68 + testRunner.Given("I have assigned the following devices to the merchants", ((string)(null)), table26, "Given "); #line hidden - TechTalk.SpecFlow.Table table24 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table27 = new TechTalk.SpecFlow.Table(new string[] { "Reference", "Amount", "DateTime", "MerchantName", "EstateName"}); - table24.AddRow(new string[] { + table27.AddRow(new string[] { "Deposit1", "2000.00", "Today", "Test Merchant 1", "Test Estate 1"}); - table24.AddRow(new string[] { + table27.AddRow(new string[] { "Deposit1", "1000.00", "Today", "Test Merchant 2", "Test Estate 1"}); - table24.AddRow(new string[] { + table27.AddRow(new string[] { "Deposit1", "1000.00", "Today", "Test Merchant 3", "Test Estate 2"}); -#line 59 - testRunner.Given("I make the following manual merchant deposits", ((string)(null)), table24, "Given "); +#line 74 + testRunner.Given("I make the following manual merchant deposits", ((string)(null)), table27, "Given "); #line hidden } @@ -335,7 +401,7 @@ public virtual void SaleTransaction() "PRTest"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Sale Transaction", null, tagsOfScenario, argumentsOfScenario); -#line 66 +#line 81 this.ScenarioInitialize(scenarioInfo); #line hidden bool isScenarioIgnored = default(bool); @@ -358,12 +424,12 @@ public virtual void SaleTransaction() #line 4 this.FeatureBackground(); #line hidden -#line 67 +#line 82 testRunner.Given("I am logged in as \"merchantuser@testmerchant1.co.uk\" with password \"123456\" for M" + "erchant \"Test Merchant 1\" for Estate \"Test Estate 1\" with client \"merchantClient" + "\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden - TechTalk.SpecFlow.Table table25 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table28 = new TechTalk.SpecFlow.Table(new string[] { "DateTime", "TransactionNumber", "TransactionType", @@ -373,8 +439,10 @@ public virtual void SaleTransaction() "OperatorName", "TransactionAmount", "CustomerAccountNumber", - "CustomerEmailAddress"}); - table25.AddRow(new string[] { + "CustomerEmailAddress", + "ContractDescription", + "ProductName"}); + table28.AddRow(new string[] { "Today", "1", "Sale", @@ -384,8 +452,10 @@ public virtual void SaleTransaction() "Safaricom", "1000.00", "123456789", - ""}); - table25.AddRow(new string[] { + "", + "Safaricom Contract", + "Variable Topup"}); + table28.AddRow(new string[] { "Today", "4", "Sale", @@ -395,16 +465,18 @@ public virtual void SaleTransaction() "Safaricom", "1000.00", "123456789", - "testcustomer@customer.co.uk"}); -#line 68 - testRunner.When("I perform the following transactions", ((string)(null)), table25, "When "); + "testcustomer@customer.co.uk", + "Safaricom Contract", + "Variable Topup"}); +#line 83 + testRunner.When("I perform the following transactions", ((string)(null)), table28, "When "); #line hidden -#line 73 +#line 88 testRunner.Given("I am logged in as \"merchantuser@testmerchant2.co.uk\" with password \"123456\" for M" + "erchant \"Test Merchant 2\" for Estate \"Test Estate 1\" with client \"merchantClient" + "\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden - TechTalk.SpecFlow.Table table26 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table29 = new TechTalk.SpecFlow.Table(new string[] { "DateTime", "TransactionNumber", "TransactionType", @@ -414,8 +486,10 @@ public virtual void SaleTransaction() "OperatorName", "TransactionAmount", "CustomerAccountNumber", - "CustomerEmailAddress"}); - table26.AddRow(new string[] { + "CustomerEmailAddress", + "ContractDescription", + "ProductName"}); + table29.AddRow(new string[] { "Today", "2", "Sale", @@ -425,16 +499,18 @@ public virtual void SaleTransaction() "Safaricom", "1000.00", "123456789", - ""}); -#line 74 - testRunner.When("I perform the following transactions", ((string)(null)), table26, "When "); + "", + "Safaricom Contract", + "Variable Topup"}); +#line 89 + testRunner.When("I perform the following transactions", ((string)(null)), table29, "When "); #line hidden -#line 78 +#line 93 testRunner.Given("I am logged in as \"merchantuser@testmerchant3.co.uk\" with password \"123456\" for M" + "erchant \"Test Merchant 3\" for Estate \"Test Estate 2\" with client \"merchantClient" + "\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden - TechTalk.SpecFlow.Table table27 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table30 = new TechTalk.SpecFlow.Table(new string[] { "DateTime", "TransactionNumber", "TransactionType", @@ -444,8 +520,10 @@ public virtual void SaleTransaction() "OperatorName", "TransactionAmount", "CustomerAccountNumber", - "CustomerEmailAddress"}); - table27.AddRow(new string[] { + "CustomerEmailAddress", + "ContractDescription", + "ProductName"}); + table30.AddRow(new string[] { "Today", "3", "Sale", @@ -455,47 +533,49 @@ public virtual void SaleTransaction() "Safaricom", "1000.00", "123456789", - ""}); -#line 79 - testRunner.When("I perform the following transactions", ((string)(null)), table27, "When "); + "", + "Safaricom Contract", + "Variable Topup"}); +#line 94 + testRunner.When("I perform the following transactions", ((string)(null)), table30, "When "); #line hidden - TechTalk.SpecFlow.Table table28 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table31 = new TechTalk.SpecFlow.Table(new string[] { "EstateName", "MerchantName", "TransactionNumber", "TransactionType", "ResponseCode", "ResponseMessage"}); - table28.AddRow(new string[] { + table31.AddRow(new string[] { "Test Estate 1", "Test Merchant 1", "1", "Sale", "0000", "SUCCESS"}); - table28.AddRow(new string[] { + table31.AddRow(new string[] { "Test Estate 1", "Test Merchant 2", "2", "Sale", "0000", "SUCCESS"}); - table28.AddRow(new string[] { + table31.AddRow(new string[] { "Test Estate 2", "Test Merchant 3", "3", "Sale", "0000", "SUCCESS"}); - table28.AddRow(new string[] { + table31.AddRow(new string[] { "Test Estate 1", "Test Merchant 1", "4", "Sale", "0000", "SUCCESS"}); -#line 83 - testRunner.Then("transaction response should contain the following information", ((string)(null)), table28, "Then "); +#line 98 + testRunner.Then("transaction response should contain the following information", ((string)(null)), table31, "Then "); #line hidden } this.ScenarioCleanup(); diff --git a/TransactionProcessorACL.IntegrationTests/Shared/SharedSteps.cs b/TransactionProcessorACL.IntegrationTests/Shared/SharedSteps.cs index bb70534..6348c9d 100644 --- a/TransactionProcessorACL.IntegrationTests/Shared/SharedSteps.cs +++ b/TransactionProcessorACL.IntegrationTests/Shared/SharedSteps.cs @@ -11,6 +11,7 @@ namespace TransactionProcessor.IntegrationTests.Shared using System.Threading.Tasks; using Common; using DataTransferObjects; + using EstateManagement.DataTransferObjects; using EstateManagement.DataTransferObjects.Requests; using EstateManagement.DataTransferObjects.Responses; using Newtonsoft.Json; @@ -158,6 +159,122 @@ await Retry.For(async () => } } + [Given(@"I create a contract with the following values")] + public async Task GivenICreateAContractWithTheFollowingValues(Table table) + { + foreach (TableRow tableRow in table.Rows) + { + EstateDetails estateDetails = this.TestingContext.GetEstateDetails(tableRow); + + String token = this.TestingContext.AccessToken; + if (String.IsNullOrEmpty(estateDetails.AccessToken) == false) + { + token = estateDetails.AccessToken; + } + + String operatorName = SpecflowTableHelper.GetStringRowValue(tableRow, "OperatorName"); + Guid operatorId = estateDetails.GetOperatorId(operatorName); + + CreateContractRequest createContractRequest = new CreateContractRequest + { + OperatorId = operatorId, + Description = SpecflowTableHelper.GetStringRowValue(tableRow, "ContractDescription") + }; + + CreateContractResponse contractResponse = + await this.TestingContext.DockerHelper.EstateClient.CreateContract(token, estateDetails.EstateId, createContractRequest, CancellationToken.None); + + estateDetails.AddContract(contractResponse.ContractId, createContractRequest.Description, operatorId); + } + } + + [When(@"I create the following Products")] + public async Task WhenICreateTheFollowingProducts(Table table) + { + foreach (TableRow tableRow in table.Rows) + { + EstateDetails estateDetails = this.TestingContext.GetEstateDetails(tableRow); + + String token = this.TestingContext.AccessToken; + if (String.IsNullOrEmpty(estateDetails.AccessToken) == false) + { + token = estateDetails.AccessToken; + } + + String contractName = SpecflowTableHelper.GetStringRowValue(tableRow, "ContractDescription"); + Contract contract = estateDetails.GetContract(contractName); + String productValue = SpecflowTableHelper.GetStringRowValue(tableRow, "Value"); + + AddProductToContractRequest addProductToContractRequest = new AddProductToContractRequest + { + ProductName = SpecflowTableHelper.GetStringRowValue(tableRow, "ProductName"), + DisplayText = SpecflowTableHelper.GetStringRowValue(tableRow, "DisplayText"), + Value = null + }; + if (String.IsNullOrEmpty(productValue) == false) + { + addProductToContractRequest.Value = Decimal.Parse(productValue); + } + + AddProductToContractResponse addProductToContractResponse = await this.TestingContext.DockerHelper.EstateClient.AddProductToContract(token, + estateDetails.EstateId, + contract.ContractId, + addProductToContractRequest, + CancellationToken.None); + + contract.AddProduct(addProductToContractResponse.ProductId, addProductToContractRequest.ProductName, addProductToContractRequest.DisplayText, + addProductToContractRequest.Value); + } + } + + [When(@"I add the following Transaction Fees")] + public async Task WhenIAddTheFollowingTransactionFees(Table table) + { + foreach (TableRow tableRow in table.Rows) + { + EstateDetails estateDetails = this.TestingContext.GetEstateDetails(tableRow); + + String token = this.TestingContext.AccessToken; + if (String.IsNullOrEmpty(estateDetails.AccessToken) == false) + { + token = estateDetails.AccessToken; + } + + String contractName = SpecflowTableHelper.GetStringRowValue(tableRow, "ContractDescription"); + String productName = SpecflowTableHelper.GetStringRowValue(tableRow, "ProductName"); + Contract contract = estateDetails.GetContract(contractName); + + Product product = contract.GetProduct(productName); + + AddTransactionFeeForProductToContractRequest addTransactionFeeForProductToContractRequest = new AddTransactionFeeForProductToContractRequest + { + Value = + SpecflowTableHelper + .GetDecimalValue(tableRow, "Value"), + Description = + SpecflowTableHelper.GetStringRowValue(tableRow, + "FeeDescription"), + CalculationType = + SpecflowTableHelper + .GetEnumValue(tableRow, + "CalculationType") + }; + + AddTransactionFeeForProductToContractResponse addTransactionFeeForProductToContractResponse = + await this.TestingContext.DockerHelper.EstateClient.AddTransactionFeeForProductToContract(token, + estateDetails.EstateId, + contract.ContractId, + product.ProductId, + addTransactionFeeForProductToContractRequest, + CancellationToken.None); + + product.AddTransactionFee(addTransactionFeeForProductToContractResponse.TransactionFeeId, + addTransactionFeeForProductToContractRequest.CalculationType, + addTransactionFeeForProductToContractRequest.Description, + addTransactionFeeForProductToContractRequest.Value); + } + } + [Given(@"I have created the following operators")] [When(@"I create the following operators")] public async Task WhenICreateTheFollowingOperators(Table table) @@ -329,6 +446,18 @@ public async Task WhenIPerformTheFollowingTransactions(Table table) Decimal transactionAmount = SpecflowTableHelper.GetDecimalValue(tableRow, "TransactionAmount"); String customerAccountNumber = SpecflowTableHelper.GetStringRowValue(tableRow, "CustomerAccountNumber"); String customerEmailAddress = SpecflowTableHelper.GetStringRowValue(tableRow, "CustomerEmailAddress"); + String contractDescription = SpecflowTableHelper.GetStringRowValue(tableRow, "ContractDescription"); + String productName = SpecflowTableHelper.GetStringRowValue(tableRow, "ProductName"); + + Guid contractId = Guid.Empty; + Guid productId = Guid.Empty; + var contract = estateDetails.GetContract(contractDescription); + if (contract != null) + { + contractId = contract.ContractId; + var product = contract.GetProduct(productName); + productId = product.ProductId; + } responseMessage = await this.PerformSaleTransaction(merchantToken, transactionDateTime, @@ -339,6 +468,8 @@ public async Task WhenIPerformTheFollowingTransactions(Table table) transactionAmount, customerAccountNumber, customerEmailAddress, + contractId, + productId, CancellationToken.None); break; @@ -482,7 +613,10 @@ private async Task PerformLogonTransaction(String merchantToken, DateTim return responseContent; } - private async Task PerformSaleTransaction(String merchantToken, DateTime transactionDateTime, String transactionType, String transactionNumber, String deviceIdentifier, String operatorIdentifier, Decimal transactionAmount, String customerAccountNumber, String customerEmailAddress, CancellationToken cancellationToken) + private async Task PerformSaleTransaction(String merchantToken, DateTime transactionDateTime, String transactionType, String transactionNumber, String deviceIdentifier, String operatorIdentifier, Decimal transactionAmount, String customerAccountNumber, String customerEmailAddress, + Guid contractId, + Guid productId, + CancellationToken cancellationToken) { SaleTransactionRequestMessage saleTransactionRequestMessage = new SaleTransactionRequestMessage { @@ -492,7 +626,9 @@ private async Task PerformSaleTransaction(String merchantToken, DateTime OperatorIdentifier = operatorIdentifier, Amount = transactionAmount, CustomerAccountNumber = customerAccountNumber, - CustomerEmailAddress = customerEmailAddress + CustomerEmailAddress = customerEmailAddress, + ContractId = contractId, + ProductId = productId }; String uri = "api/transactions"; diff --git a/TransactionProcessorACL.IntegrationTests/TransactionProcessorACL.IntegrationTests.csproj b/TransactionProcessorACL.IntegrationTests/TransactionProcessorACL.IntegrationTests.csproj index cdce886..a2a7534 100644 --- a/TransactionProcessorACL.IntegrationTests/TransactionProcessorACL.IntegrationTests.csproj +++ b/TransactionProcessorACL.IntegrationTests/TransactionProcessorACL.IntegrationTests.csproj @@ -9,7 +9,7 @@ - + @@ -20,7 +20,7 @@ - + all diff --git a/TransactionProcessorACL.Testing/TestData.cs b/TransactionProcessorACL.Testing/TestData.cs index 78d664f..6175dbb 100644 --- a/TransactionProcessorACL.Testing/TestData.cs +++ b/TransactionProcessorACL.Testing/TestData.cs @@ -115,6 +115,10 @@ public class TestData public static String CustomerEmailAddress = "testcustomer@customer.co.uk"; + public static Guid ContractId = Guid.Parse("362CCDFD-C227-4D6E-884C-D6323E278175"); + + public static Guid ProductId = Guid.Parse("B74D71CA-CC5E-4F49-8412-79D36035D68E"); + public static ProcessSaleTransactionRequest ProcessSaleTransactionRequest = ProcessSaleTransactionRequest.Create(TestData.EstateId, TestData.MerchantId, TestData.TransactionDateTime, @@ -123,6 +127,8 @@ public class TestData TestData.OperatorIdentifier, TestData.SaleAmount, TestData.CustomerAccountNumber, - TestData.CustomerEmailAddress); + TestData.CustomerEmailAddress, + TestData.ContractId, + TestData.ProductId); } } \ No newline at end of file diff --git a/TransactionProcessorACL/Controllers/TransactionController.cs b/TransactionProcessorACL/Controllers/TransactionController.cs index 885a82c..e7f431d 100644 --- a/TransactionProcessorACL/Controllers/TransactionController.cs +++ b/TransactionProcessorACL/Controllers/TransactionController.cs @@ -117,7 +117,9 @@ private ProcessSaleTransactionRequest CreateCommandFromRequest(SaleTransactionRe saleTransactionRequestMessage.OperatorIdentifier, saleTransactionRequestMessage.Amount, saleTransactionRequestMessage.CustomerAccountNumber, - saleTransactionRequestMessage.CustomerEmailAddress); + saleTransactionRequestMessage.CustomerEmailAddress, + saleTransactionRequestMessage.ContractId, + saleTransactionRequestMessage.ProductId); return request; }