diff --git a/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.MetadataFields.cs b/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.MetadataFields.cs new file mode 100644 index 00000000..748e1dd5 --- /dev/null +++ b/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.MetadataFields.cs @@ -0,0 +1,14 @@ +namespace TransactionProcessor.Mobile.BusinessLogic.Common; + +public static class MetadataFields +{ + public static string Amount { get; } = "Amount"; + public static string RecipientEmail { get; } = "RecipientEmail"; + public static string RecipientMobile { get; } = "RecipientMobile"; + public static string CustomerAccountNumber { get; } = "CustomerAccountNumber"; + public static string PataPawaPostPaidMessageType { get; } = "PataPawaPostPaidMessageType"; + public static string PataPawaPrePayMessageType { get; } = "PataPawaPrePayMessageType"; + public static string MeterNumber { get; } = "MeterNumber"; + public static string CustomerName { get; } = "CustomerName"; + public static string MobileNumber { get; } = "MobileNumber"; +} diff --git a/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.cs b/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.cs index 65ce2b54..88d1facb 100644 --- a/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.cs +++ b/TransactionProcessor.Mobile.BusinessLogic/Common/Extensions.cs @@ -7,7 +7,7 @@ namespace TransactionProcessor.Mobile.BusinessLogic.Common; -public static class Extensions +public static partial class Extensions { public static TransactionRecord ToTransactionRecord(this TransactionCommands.PerformLogonCommand request, Boolean isTrainingMode) { @@ -199,6 +199,7 @@ public static ReconciliationRequestMessage ToReconciliationRequest(this PerformR return reconciliationRequest; } + public static SaleTransactionRequestMessage ToSaleTransactionRequest(this PerformVoucherIssueRequestModel model) { SaleTransactionRequestMessage saleTransactionRequest = new() { @@ -214,9 +215,9 @@ public static SaleTransactionRequestMessage ToSaleTransactionRequest(this Perfor // Add the additional request data saleTransactionRequest.AdditionalRequestMetadata = new Dictionary { - {"Amount", model.VoucherAmount.ToString()}, - {"RecipientEmail", model.RecipientEmailAddress}, - {"RecipientMobile", model.RecipientMobileNumber} + {MetadataFields.Amount, model.VoucherAmount.ToString()}, + {MetadataFields.RecipientEmail, model.RecipientEmailAddress}, + {MetadataFields.RecipientMobile, model.RecipientMobileNumber} }; return saleTransactionRequest; @@ -237,8 +238,8 @@ public static SaleTransactionRequestMessage ToSaleTransactionRequest(this Perfor // Add the additional request data saleTransactionRequest.AdditionalRequestMetadata = new Dictionary { - {"Amount", model.TopupAmount.ToString()}, - {"CustomerAccountNumber", model.CustomerAccountNumber} + {MetadataFields.Amount, model.TopupAmount.ToString()}, + {MetadataFields.CustomerAccountNumber, model.CustomerAccountNumber} }; return saleTransactionRequest; @@ -256,8 +257,8 @@ public static SaleTransactionRequestMessage ToSaleTransactionRequest(this Perfor }; // Add the additional request data saleTransactionRequest.AdditionalRequestMetadata = new Dictionary { - {"CustomerAccountNumber", model.CustomerAccountNumber}, - {"PataPawaPostPaidMessageType", "VerifyAccount"} + {MetadataFields.CustomerAccountNumber, model.CustomerAccountNumber}, + {MetadataFields.PataPawaPostPaidMessageType, "VerifyAccount"} }; return saleTransactionRequest; @@ -277,19 +278,19 @@ public static SaleTransactionRequestMessage ToSaleTransactionRequest(this Perfor if (model.PostPayment){ // Add the additional request data saleTransactionRequest.AdditionalRequestMetadata = new Dictionary{ - { "CustomerAccountNumber", model.CustomerAccountNumber }, - { "CustomerName", model.CustomerAccountName }, - { "MobileNumber", model.CustomerMobileNumber }, - { "Amount", model.PaymentAmount.ToString() }, - { "PataPawaPostPaidMessageType", "ProcessBill" } + { MetadataFields.CustomerAccountNumber, model.CustomerAccountNumber }, + { MetadataFields.CustomerName, model.CustomerAccountName }, + { MetadataFields.MobileNumber, model.CustomerMobileNumber }, + { MetadataFields.Amount, model.PaymentAmount.ToString() }, + { MetadataFields.PataPawaPostPaidMessageType, "ProcessBill" } }; } else{ saleTransactionRequest.AdditionalRequestMetadata = new Dictionary{ - { "MeterNumber", model.CustomerAccountNumber }, - { "CustomerName", model.CustomerAccountName }, - { "PataPawaPrePayMessageType", "vend" }, - { "Amount", model.PaymentAmount.ToString() }, + { MetadataFields.MeterNumber, model.CustomerAccountNumber }, + { MetadataFields.CustomerName, model.CustomerAccountName }, + { MetadataFields.PataPawaPrePayMessageType, "vend" }, + { MetadataFields.Amount, model.PaymentAmount.ToString() }, }; } @@ -310,7 +311,7 @@ public static SaleTransactionRequestMessage ToSaleTransactionRequest(this Perfor // Add the additional request data saleTransactionRequest.AdditionalRequestMetadata = new Dictionary { {"MeterNumber", model.MeterNumber.ToString()}, - {"PataPawaPrePayMessageType", "meter"} + {MetadataFields.PataPawaPrePayMessageType, "meter"} }; return saleTransactionRequest; diff --git a/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs b/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs index 1ad1dd20..fa805942 100644 --- a/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs +++ b/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs @@ -321,7 +321,7 @@ private void CacheAccessToken(TokenResponseModel token) (key, value, reason, state) => { _ = AccessTokenExpired(key, value, reason, state); - }); ; + }); this.ApplicationCache.SetAccessToken(token, cacheEntryOptions); } diff --git a/TransactionProcessor.Mobile.UITests/SmokeTests/TestBackendHostSmokeTests.cs b/TransactionProcessor.Mobile.UITests/SmokeTests/TestBackendHostSmokeTests.cs index 695ba91f..3a9cc635 100644 --- a/TransactionProcessor.Mobile.UITests/SmokeTests/TestBackendHostSmokeTests.cs +++ b/TransactionProcessor.Mobile.UITests/SmokeTests/TestBackendHostSmokeTests.cs @@ -1,6 +1,8 @@ using System.Net; using System.Net.Http.Json; using System.Net.Sockets; +using System.Text; +using System.Text.Json; using NUnit.Framework; using Shouldly; using TransactionProcessor.DataTransferObjects.Responses.Merchant; @@ -84,6 +86,75 @@ public async Task Seed_CanBeApplied_AndResetRestoresDefaultMerchantState() resetMerchant.Contacts[0].ContactEmailAddress.ShouldBe("test@example.com"); } + [Test] + public async Task TransactionMixSummary_ReturnsTransactionTypeAsString() + { + await using TestBackendHost host = await TestBackendHost.StartAsync(GetFreePort()).ConfigureAwait(false); + + using HttpClient client = host.CreateClient(); + SeedReportTransaction(host, RequestKind.MobileTopup); + + StringContent requestContent = new( + JsonSerializer.Serialize(new + { + MerchantReportingId = 12345, + StartDate = new DateTime(2026, 8, 27), + EndDate = new DateTime(2026, 8, 27), + Breakdown = 1, + Measure = 1, + TopN = 5 + }, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }), + Encoding.UTF8, + "application/json"); + + HttpResponseMessage response = await client.PostAsync("/api/reporting/transactionmixsummary", requestContent).ConfigureAwait(false); + + response.StatusCode.ShouldBe(HttpStatusCode.OK); + + using JsonDocument document = JsonDocument.Parse(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + JsonElement transactionType = document.RootElement.GetProperty("drill_down_transactions") + .EnumerateArray() + .Single() + .GetProperty("transaction_type"); + + transactionType.ValueKind.ShouldBe(JsonValueKind.String); + transactionType.GetString().ShouldBe("Mobile Topup"); + } + + [Test] + public async Task RecentActivityReceiptSearch_ReturnsTransactionTypeAsString() + { + await using TestBackendHost host = await TestBackendHost.StartAsync(GetFreePort()).ConfigureAwait(false); + + using HttpClient client = host.CreateClient(); + SeedReportTransaction(host, RequestKind.BillPaymentMakePayment); + + StringContent requestContent = new( + JsonSerializer.Serialize(new + { + MerchantReportingId = 12345, + ReportDate = new DateTime(2026, 8, 27), + SearchText = (string?)null, + PageNumber = 1, + PageSize = 5 + }, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }), + Encoding.UTF8, + "application/json"); + + HttpResponseMessage response = await client.PostAsync("/api/reporting/recentactivityreceiptsearch", requestContent).ConfigureAwait(false); + + response.StatusCode.ShouldBe(HttpStatusCode.OK); + + using JsonDocument document = JsonDocument.Parse(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + JsonElement transactionType = document.RootElement.GetProperty("items") + .EnumerateArray() + .Single() + .GetProperty("transaction_type"); + + transactionType.ValueKind.ShouldBe(JsonValueKind.String); + transactionType.GetString().ShouldBe("Bill Payment"); + } + private static int GetFreePort() { using TcpListener listener = new(IPAddress.Loopback, 0); @@ -91,4 +162,27 @@ private static int GetFreePort() int port = ((IPEndPoint)listener.LocalEndpoint).Port; return port; } + + private static void SeedReportTransaction(TestBackendHost host, RequestKind transactionType) + { + BackendSeed seed = new() + { + ReportTransactions = + [ + new ReportTransactionSeed + { + Reference = "TXN-10001", + ReceiptReference = "RCPT-10001", + TransactionType = transactionType, + Product = "Custom", + Operator = "Safaricom", + Status = "Success", + Amount = 100.00m, + TransactionDateTime = new DateTime(2026, 8, 27, 9, 30, 0) + } + ] + }; + + host.ApplySeed(seed); + } } diff --git a/TransactionProcessor.Mobile.UITests/Steps/SharedSteps.cs b/TransactionProcessor.Mobile.UITests/Steps/SharedSteps.cs index 3b698d0b..b68fac91 100644 --- a/TransactionProcessor.Mobile.UITests/Steps/SharedSteps.cs +++ b/TransactionProcessor.Mobile.UITests/Steps/SharedSteps.cs @@ -417,12 +417,12 @@ public Task GivenIMakeTheFollowingManualMerchantDeposits(DataTable table) [Given(@"the following transaction mix report transactions exist")] public Task GivenTheFollowingTransactionMixReportTransactionsExist(DataTable table) { - foreach (DataTableRow row in table.Rows) - { + foreach (DataTableRow row in table.Rows) { + RequestKind requestKind = ParseRequestKind(GetString(row, "TransactionType")); this.testingContext.ScenarioSeed.ReportTransactions.Add(new ReportTransactionSeed { Reference = GetString(row, "Reference"), - TransactionType = GetString(row, "TransactionType"), + TransactionType = requestKind, Product = GetString(row, "Product"), Operator = GetString(row, "Operator"), Status = GetString(row, "Status"), @@ -436,6 +436,18 @@ public Task GivenTheFollowingTransactionMixReportTransactionsExist(DataTable tab return Task.CompletedTask; } + private static RequestKind ParseRequestKind(string transactionType) + { + string normalizedTransactionType = transactionType.Trim(); + return normalizedTransactionType switch + { + "Mobile Topup" => RequestKind.MobileTopup, + "Bill Payment" => RequestKind.BillPaymentMakePayment, + "Voucher Issue" => RequestKind.Voucher, + _ => Enum.Parse(normalizedTransactionType, ignoreCase: true) + }; + } + [Given(@"the following bills are available at the PataPawa PostPaid Host")] public Task GivenTheFollowingBillsAreAvailableAtThePataPawaPostPaidHost(DataTable table) { diff --git a/TransactionProcessor.Mobile.UITests/Steps/SharedStepsTests.cs b/TransactionProcessor.Mobile.UITests/Steps/SharedStepsTests.cs new file mode 100644 index 00000000..7ec9a995 --- /dev/null +++ b/TransactionProcessor.Mobile.UITests/Steps/SharedStepsTests.cs @@ -0,0 +1,32 @@ +using Reqnroll; +using Shouldly; +using TransactionProcessor.Mobile.UiTestBackend; +using TransactionProcessor.Mobile.UITests.Common; + +namespace TransactionProcessor.Mobile.UITests.Steps; + +[TestFixture] +public class SharedStepsTests +{ + [Test] + public async Task GivenTheFollowingTransactionMixReportTransactionsExist_MapsEstablishedLabelsToRequestKinds() + { + TestingContext testingContext = new(); + testingContext.TestHostHelper = new TestHostHelper(testingContext); + SharedSteps sut = new(testingContext); + + Table table = new(["Reference", "TransactionType", "Product", "Operator", "Status", "Amount", "TransactionDateTime"]); + table.AddRow(["TXN-10001", "Mobile Topup", "Custom", "Safaricom", "Success", "100.00", "Today"]); + table.AddRow(["TXN-10002", "Bill Payment", "Bill Pay (Post)", "PataPawa PostPay", "Success", "250.00", "Today"]); + table.AddRow(["TXN-10003", "Voucher Issue", "10 KES", "Voucher", "Failed", "0.00", "Today"]); + + DataTable dataTable = DataTable.FromTable(table); + + await sut.GivenTheFollowingTransactionMixReportTransactionsExist(dataTable); + + testingContext.ScenarioSeed.ReportTransactions.Count.ShouldBe(3); + testingContext.ScenarioSeed.ReportTransactions[0].TransactionType.ShouldBe(RequestKind.MobileTopup); + testingContext.ScenarioSeed.ReportTransactions[1].TransactionType.ShouldBe(RequestKind.BillPaymentMakePayment); + testingContext.ScenarioSeed.ReportTransactions[2].TransactionType.ShouldBe(RequestKind.Voucher); + } +} diff --git a/TransactionProcessor.Mobile.UiTestBackend/BackendModels.cs b/TransactionProcessor.Mobile.UiTestBackend/BackendModels.cs index 11f7208b..a91acfb7 100644 --- a/TransactionProcessor.Mobile.UiTestBackend/BackendModels.cs +++ b/TransactionProcessor.Mobile.UiTestBackend/BackendModels.cs @@ -160,11 +160,24 @@ public sealed record DepositSeed public DateTime DateTime { get; init; } = DateTime.UtcNow; } +public enum RequestKind +{ + NotSet, + Logon, + MerchantDeposit, + BillPaymentGetAccount, + BillPaymentGetMeter, + BillPaymentMakePayment, + Voucher, + MobileTopup + +} + public sealed record ReceiptSeed { public string Reference { get; init; } = string.Empty; public string ReceiptReference { get; init; } = string.Empty; - public string TransactionType { get; init; } = string.Empty; + public RequestKind TransactionType { get; init; } = RequestKind.NotSet; public string Product { get; init; } = string.Empty; public string Operator { get; init; } = string.Empty; public string Status { get; init; } = "Success"; @@ -175,7 +188,7 @@ public sealed record ReceiptSeed public sealed record ReportTransactionSeed { public string Reference { get; init; } = string.Empty; - public string TransactionType { get; init; } = string.Empty; + public RequestKind TransactionType { get; init; } = RequestKind.NotSet; public string Product { get; init; } = string.Empty; public string Operator { get; init; } = string.Empty; public string Status { get; init; } = "Success"; diff --git a/TransactionProcessor.Mobile.UiTestBackend/TestBackendHost.cs b/TransactionProcessor.Mobile.UiTestBackend/TestBackendHost.cs index c1f8979a..3aa3447f 100644 --- a/TransactionProcessor.Mobile.UiTestBackend/TestBackendHost.cs +++ b/TransactionProcessor.Mobile.UiTestBackend/TestBackendHost.cs @@ -405,7 +405,7 @@ public void ReplaceSeed(BackendSeed seed) this.runtimeReceipts.AddRange(this.Seed.Deposits.Select(deposit => new BackendRuntimeReceipt( deposit.Reference, $"RCPT-{deposit.Reference}", - "Deposit", + RequestKind.MerchantDeposit, "Deposit", "Merchant", "Success", @@ -626,7 +626,7 @@ public async Task HandleLogonAsync(LogonTransac { Reference = request.TransactionNumber, ReceiptReference = $"RCPT-{request.TransactionNumber}", - TransactionType = "Logon", + TransactionType = RequestKind.Logon, Product = "Logon", Operator = "System", Status = "Success", @@ -651,7 +651,7 @@ public async Task HandleSaleAsync(SaleTransactio lock (this.gate) { MerchantSeed merchant = this.ResolveMerchant(request.DeviceIdentifier); - (string kind, string productName, string operatorName, decimal amount, string? customerAccountNumber, string? customerAccountName, string? meterName, string? recipientEmail, string? recipientMobile) = this.InterpretSaleRequest(request); + (RequestKind kind, string productName, string operatorName, decimal amount, string? customerAccountNumber, string? customerAccountName, string? meterName, string? recipientEmail, string? recipientMobile) = this.InterpretSaleRequest(request); bool shouldFail = amount == 150m; string responseCode = shouldFail ? "1000" : "0000"; @@ -692,7 +692,7 @@ public async Task HandleSaleAsync(SaleTransactio }); } - if (kind == "BillPaymentGetAccount") + if (kind == RequestKind.BillPaymentGetAccount) { BillSeed bill = this.Seed.Bills.FirstOrDefault(b => string.Equals(b.AccountNumber, customerAccountNumber, StringComparison.OrdinalIgnoreCase)) ?? new BillSeed { AccountNumber = customerAccountNumber ?? string.Empty, AccountName = customerAccountName ?? "Mr Test Customer", Amount = amount, DueDate = DateTime.UtcNow.Date.AddDays(3) }; @@ -704,7 +704,7 @@ public async Task HandleSaleAsync(SaleTransactio ["customerBillDueDate"] = bill.DueDate.ToString("dd-MM-yyyy") }; } - else if (kind == "BillPaymentGetMeter") + else if (kind == RequestKind.BillPaymentGetMeter) { MeterSeed meter = this.Seed.Meters.FirstOrDefault(m => string.Equals(m.MeterNumber, meterName ?? string.Empty, StringComparison.OrdinalIgnoreCase)) ?? new MeterSeed { MeterNumber = meterName ?? string.Empty, CustomerName = "Mr Test Customer" }; @@ -849,7 +849,7 @@ public object BuildTransactionMixSummary(TransactionMixSummaryRequest request) .Select(t => new { reference = t.Reference, - transactionType = t.TransactionType, + transactionType = ToReportTransactionTypeLabel(t.TransactionType), product = t.Product, operatorName = t.OperatorName, status = t.Status, @@ -897,7 +897,7 @@ public object BuildRecentActivityReceiptSearch(RecentActivityReceiptSearchReques items = paged.Select(item => new { reference = item.Reference, - transactionType = item.TransactionType, + transactionType = ToReportTransactionTypeLabel(item.TransactionType), product = item.Product, operatorName = item.OperatorName, status = item.Status, @@ -1050,7 +1050,9 @@ private static CalculationType ParseCalculationType(string? calculationType) => _ => CalculationType.Fixed }; - private (string kind, string productName, string operatorName, decimal amount, string? customerAccountNumber, string? customerAccountName, string? meterName, string? recipientEmail, string? recipientMobile) InterpretSaleRequest(SaleTransactionRequestMessage request) + + + private (RequestKind kind, string productName, string operatorName, decimal amount, string? customerAccountNumber, string? customerAccountName, string? meterName, string? recipientEmail, string? recipientMobile) InterpretSaleRequest(SaleTransactionRequestMessage request) { decimal amount = request.AdditionalRequestMetadata?.TryGetValue("Amount", out string? amountText) == true && decimal.TryParse(amountText, out decimal parsedAmount) ? parsedAmount @@ -1063,33 +1065,33 @@ private static CalculationType ParseCalculationType(string? calculationType) => { if (TryGetMetadataValue(request.AdditionalRequestMetadata, "PataPawaPostPaidMessageType", out string? type) && string.Equals(type, "VerifyAccount", StringComparison.OrdinalIgnoreCase)) { - return ("BillPaymentGetAccount", productName, operatorName, amount, TryGetMetadataValue(request.AdditionalRequestMetadata, "CustomerAccountNumber", out string? accountNumber) ? accountNumber : null, request.CustomerEmailAddress, null, null, null); + return (RequestKind.BillPaymentGetAccount, productName, operatorName, amount, TryGetMetadataValue(request.AdditionalRequestMetadata, "CustomerAccountNumber", out string? accountNumber) ? accountNumber : null, request.CustomerEmailAddress, null, null, null); } - return ("BillPaymentMakePayment", productName, operatorName, amount, TryGetMetadataValue(request.AdditionalRequestMetadata, "CustomerAccountNumber", out string? accountNumber2) ? accountNumber2 : null, request.CustomerEmailAddress, null, null, null); + return (RequestKind.BillPaymentMakePayment, productName, operatorName, amount, TryGetMetadataValue(request.AdditionalRequestMetadata, "CustomerAccountNumber", out string? accountNumber2) ? accountNumber2 : null, request.CustomerEmailAddress, null, null, null); } if (request.AdditionalRequestMetadata?.ContainsKey("PataPawaPrePayMessageType") == true) { if (TryGetMetadataValue(request.AdditionalRequestMetadata, "PataPawaPrePayMessageType", out string? type) && string.Equals(type, "meter", StringComparison.OrdinalIgnoreCase)) { - return ("BillPaymentGetMeter", productName, operatorName, amount, null, null, TryGetMetadataValue(request.AdditionalRequestMetadata, "MeterNumber", out string? meterNumber) ? meterNumber : null, null, null); + return (RequestKind.BillPaymentGetMeter, productName, operatorName, amount, null, null, TryGetMetadataValue(request.AdditionalRequestMetadata, "MeterNumber", out string? meterNumber) ? meterNumber : null, null, null); } - return ("BillPaymentMakePayment", productName, operatorName, amount, null, null, TryGetMetadataValue(request.AdditionalRequestMetadata, "MeterNumber", out string? meterNumber2) ? meterNumber2 : null, null, null); + return (RequestKind.BillPaymentMakePayment, productName, operatorName, amount, null, null, TryGetMetadataValue(request.AdditionalRequestMetadata, "MeterNumber", out string? meterNumber2) ? meterNumber2 : null, null, null); } if (request.AdditionalRequestMetadata?.ContainsKey("RecipientMobile") == true) { - return ("Voucher", productName, operatorName, amount, null, null, null, TryGetMetadataValue(request.AdditionalRequestMetadata, "RecipientEmail", out string? email) ? email : null, TryGetMetadataValue(request.AdditionalRequestMetadata, "RecipientMobile", out string? mobile) ? mobile : null); + return (RequestKind.Voucher, productName, operatorName, amount, null, null, null, TryGetMetadataValue(request.AdditionalRequestMetadata, "RecipientEmail", out string? email) ? email : null, TryGetMetadataValue(request.AdditionalRequestMetadata, "RecipientMobile", out string? mobile) ? mobile : null); } if (request.AdditionalRequestMetadata?.ContainsKey("CustomerAccountNumber") == true) { - return ("MobileTopup", productName, operatorName, amount, TryGetMetadataValue(request.AdditionalRequestMetadata, "CustomerAccountNumber", out string? accountNumber3) ? accountNumber3 : null, null, null, null, null); + return (RequestKind.MobileTopup, productName, operatorName, amount, TryGetMetadataValue(request.AdditionalRequestMetadata, "CustomerAccountNumber", out string? accountNumber3) ? accountNumber3 : null, null, null, null, null); } - return ("MobileTopup", productName, operatorName, amount, null, null, null, null, null); + return (RequestKind.MobileTopup, productName, operatorName, amount, null, null, null, null, null); } private static bool TryGetMetadataValue(Dictionary? metadata, string key, out string? value) @@ -1112,6 +1114,17 @@ private static bool TryGetMetadataValue(Dictionary? metadata, st return false; } + private static string ToReportTransactionTypeLabel(RequestKind transactionType) + { + return transactionType switch + { + RequestKind.MobileTopup => "Mobile Topup", + RequestKind.BillPaymentMakePayment => "Bill Payment", + RequestKind.Voucher => "Voucher Issue", + _ => transactionType.ToString() + }; + } + private string ResolveOperatorName(Guid operatorId) { return this.Seed.Operators @@ -1126,7 +1139,7 @@ private string ResolveProductName(Guid productId) ?.DisplayText ?? "Unknown"; } - private sealed record BackendRuntimeReceipt(string Reference, string ReceiptReference, string TransactionType, string Product, string OperatorName, string Status, decimal Amount, DateTime TransactionDateTime); + private sealed record BackendRuntimeReceipt(string Reference, string ReceiptReference, RequestKind TransactionType, string Product, string OperatorName, string Status, decimal Amount, DateTime TransactionDateTime); private sealed record BackendRuntimeLog(string DeviceIdentifier, string Message, DateTime EntryDateTime, string LogLevel); } diff --git a/scripts/Run-UITests.ps1 b/scripts/Run-UITests.ps1 deleted file mode 100644 index fa52041e..00000000 --- a/scripts/Run-UITests.ps1 +++ /dev/null @@ -1,72 +0,0 @@ -param( - [Parameter(Mandatory = $true)] - [ValidateSet("Android", "Windows")] - [string]$Platform, - - [Parameter(Mandatory = $false)] - [string]$AndroidAppPath, - - [Parameter(Mandatory = $false)] - [string]$WindowsAppId, - - [Parameter(Mandatory = $false)] - [string]$Filter, - - [Parameter(Mandatory = $false)] - [string]$Configuration = "Debug", - - [Parameter(Mandatory = $false)] - [switch]$NoBuild -) - -$ErrorActionPreference = "Stop" - -$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..") -$projectPath = Join-Path $repoRoot "TransactionProcessor.Mobile.UITests\TransactionProcessor.Mobile.UITests.csproj" - -$env:UITEST_PLATFORM = $Platform -$env:UITEST_ANDROID_APP_PATH = "" -$env:UITEST_WINDOWS_APP_ID = "" - -switch ($Platform) { - "Android" { - if ([string]::IsNullOrWhiteSpace($AndroidAppPath)) { - throw "AndroidAppPath is required when Platform is Android." - } - - $env:UITEST_ANDROID_APP_PATH = $AndroidAppPath - } - "Windows" { - if ([string]::IsNullOrWhiteSpace($WindowsAppId)) { - throw "WindowsAppId is required when Platform is Windows." - } - - $env:UITEST_WINDOWS_APP_ID = $WindowsAppId - } -} - -$testArguments = @( - "test", - $projectPath, - "--configuration", - $Configuration -) - -if ($NoBuild) { - $testArguments += "--no-build" -} - -if ([string]::IsNullOrWhiteSpace($Filter) -eq $false) { - $testArguments += "--filter" - $testArguments += $Filter -} - -Write-Host "Running UI tests for $Platform with configuration $Configuration" -if ($Platform -eq "Android") { - Write-Host "Using APK: $AndroidAppPath" -} -else { - Write-Host "Using AppUserModelId: $WindowsAppId" -} - -dotnet @testArguments