From 6c34ae7514c59f664ff428e97afc388b37304322 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Thu, 9 Jul 2026 10:04:35 +0100 Subject: [PATCH 1/2] Cache merchant details after login and reuse in account Added GetMerchantDetails to LoginPageViewModel and updated the login flow to fetch and cache merchant details. Modified MyAccountPageViewModel to use cached merchant details when available, reducing redundant queries and improving efficiency. --- .../ViewModels/LoginPageViewModel.cs | 14 ++++++++-- .../MyAccount/MyAccountPageViewModel.cs | 26 ++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs b/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs index c8cffbb8..ad71c45b 100644 --- a/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs +++ b/TransactionProcessor.Mobile.BusinessLogic/ViewModels/LoginPageViewModel.cs @@ -123,6 +123,12 @@ private async Task> PerformLogonTransaction() TransactionCommands.PerformLogonCommand command = new(DateTime.Now); return await this.Mediator.Send(command); } + + private async Task> GetMerchantDetails() + { + MerchantQueries.GetMerchantDetailsQuery query = new MerchantQueries.GetMerchantDetailsQuery(); + return await this.Mediator.Send(query); + } private async Task>> GetMerchantContractProducts() { // Get Contracts @@ -245,9 +251,13 @@ private async Task Logon(){ await this.WriteTimingTrace(sw, "After PerformLogonTransaction"); Result> getMerchantContractProductsResult = await this.GetMerchantContractProducts(); this.HandleResult(getMerchantContractProductsResult); - await this.WriteTimingTrace(sw, "After GetMerchantContractProducts"); - + + Result getMerchantDetailsResult = await this.GetMerchantDetails(); + this.HandleResult(getMerchantDetailsResult); + await this.WriteTimingTrace(sw, "After GetMerchantDetails"); + + this.ApplicationCache.SetMerchantDetails(getMerchantDetailsResult.Data); this.ApplicationCache.SetIsLoggedIn(true); this.BalanceRefresher.StartRefreshing(); diff --git a/TransactionProcessor.Mobile.BusinessLogic/ViewModels/MyAccount/MyAccountPageViewModel.cs b/TransactionProcessor.Mobile.BusinessLogic/ViewModels/MyAccount/MyAccountPageViewModel.cs index b11332cb..bd39d293 100644 --- a/TransactionProcessor.Mobile.BusinessLogic/ViewModels/MyAccount/MyAccountPageViewModel.cs +++ b/TransactionProcessor.Mobile.BusinessLogic/ViewModels/MyAccount/MyAccountPageViewModel.cs @@ -73,16 +73,24 @@ public async Task Initialise(CancellationToken cancellationToken) { new() { Title = "Logout" } ]; - MerchantQueries.GetMerchantDetailsQuery query = new MerchantQueries.GetMerchantDetailsQuery(); - - Result merchantDetailsResult = await this.Mediator.Send(query, cancellationToken); - if (merchantDetailsResult.IsFailed) { - await this.DialogService.ShowWarningToast("Unable to load merchant details. Please try again later.", cancellationToken: cancellationToken); - return; + MerchantDetailsModel merchant = this.ApplicationCache.GetMerchantDetails(); + if (merchant == null) + { + MerchantQueries.GetMerchantDetailsQuery query = new(); + + Result merchantDetailsResult = await this.Mediator.Send(query, cancellationToken); + if (merchantDetailsResult.IsFailed) + { + await this.DialogService.ShowWarningToast("Unable to load merchant details. Please try again later.", cancellationToken: cancellationToken); + return; + } + + this.MerchantName = merchantDetailsResult.Data.MerchantName; } - - this.MerchantName = merchantDetailsResult.Data.MerchantName; - + else { + this.MerchantName = merchant.MerchantName; + } + this.LastLogin = this.ApplicationCache.GetLastLoginDate(); this.IsDarkThemeEnabled = await this.ApplicationThemeService.GetDarkThemeEnabled(); } From a978d240207ecf43760683efe89babc65a8e30d8 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Thu, 9 Jul 2026 10:42:09 +0100 Subject: [PATCH 2/2] fix failing unit tests --- .../ViewModelTests/LoginPageViewModelTests.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/TransactionProcessor.Mobile.BusinessLogic.Tests/ViewModelTests/LoginPageViewModelTests.cs b/TransactionProcessor.Mobile.BusinessLogic.Tests/ViewModelTests/LoginPageViewModelTests.cs index 49da0875..76027cfd 100644 --- a/TransactionProcessor.Mobile.BusinessLogic.Tests/ViewModelTests/LoginPageViewModelTests.cs +++ b/TransactionProcessor.Mobile.BusinessLogic.Tests/ViewModelTests/LoginPageViewModelTests.cs @@ -67,12 +67,14 @@ public void LoginPageViewModel_LoginCommand_Execute_IsExecuted() this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.AccessToken)); this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.PerformLogonResponseModel)); this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.ContractProductList)); - + this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantDetailsModel)); + this.ViewModel.LogonCommand.Execute(null); this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); + this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); this.NavigationService.Verify(n => n.GoToHome(), Times.Once); } @@ -86,6 +88,8 @@ public void LoginPageViewModel_LoginCommand_Execute_ConfigUrlSet_IsExecuted(Stri this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.AccessToken)); this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.PerformLogonResponseModel)); this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.ContractProductList)); + this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantDetailsModel)); + this.ViewModel.ConfigHostUrl = configUrl; this.ViewModel.LogonCommand.Execute(null); @@ -93,6 +97,7 @@ public void LoginPageViewModel_LoginCommand_Execute_ConfigUrlSet_IsExecuted(Stri this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); + this.Mediator.Verify(x => x.Send(It.IsAny(), It.IsAny()), Times.Once); this.NavigationService.Verify(n => n.GoToHome(), Times.Once); if (String.IsNullOrEmpty(configUrl) == false){ this.ApplicationCache.Verify(v => v.SetConfigHostUrl(It.IsAny(), It.IsAny()), Times.Once); @@ -147,6 +152,9 @@ public async Task LoginPageViewModel_LoginCommand_Execute_UpdateCheckFails_Logon this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.PerformLogonResponseModel)); this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.ContractProductList)); this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantBalance)); + this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantDetailsModel)); + this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantDetailsModel)); + this.ApplicationInfoService.Setup(a => a.VersionString).Returns(TestData.ApplicationVersion); this.ApplicationInfoService.Setup(a => a.PackageName).Returns("com.transactionprocessor.mobile"); this.DeviceService.Setup(d => d.GetPlatform()).Returns("Android");