using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LCU.API.Collections.RepoApi.DataAccess; using LCU.API.Collections.RepoApi.Domain; using LCU.API.Collections.RepoApi.Domain.Extensions; using LCU.API.Collections.RepoApi.Exceptions; using LCU.API.Collections.RepoApi.Models; using LCU.API.Collections.RepoApi.Services; using LCU.API.Collections.RepoApi.Services.Producer; using LCU.API.Collections.RepoApiTests.Domain; using LCU.Shared.Collections.RepoApiLib.Models; using LCU.Shared.Collections.RepoApiLib.Models.Producer; using LCU.Shared.Collections.RepoApiLib.Models.Settings; using Moq; using Xunit; namespace LCU.API.Collections.RepoApiTests.Services.Processor { public class RepoAccountProcessorIntegrationTest { private readonly RepoAccountProcessor _repoAccountProcessor; private readonly IRepoAccountProcessorService _repoAccountProcessorService; private readonly Mock _mockAccountAlertCheckService; private readonly Mock _mockSettingsService; private readonly Mock _mockRepoAccountService; private readonly Mock _mockCollectionsDao; private readonly Mock _mockCoreDao; private readonly Mock _mockRepoLetterService; private readonly Mock _mockEmailer; private readonly Mock _mockAuctionAssignmentService; private readonly Mock _mockEventAlertService; private readonly Mock _mockRepoCompanySelectionService; public RepoAccountProcessorIntegrationTest() { _mockAccountAlertCheckService = new Mock(); _mockSettingsService = new Mock(); _mockRepoAccountService = new Mock(); _mockCollectionsDao = new Mock(); _mockCoreDao = new Mock(); _mockEmailer = new Mock(); _mockAuctionAssignmentService = new Mock(); _mockRepoLetterService = new Mock(); _mockEventAlertService = new Mock(); _mockRepoCompanySelectionService = new Mock(); var repoSettings = DbContextFromJson.GetTestObjectFromFile("Services/Processor/repoSettings.json"); _mockSettingsService.Setup(x => x.GetCachedRepoSettingsAsync()).ReturnsAsync(repoSettings); _repoAccountProcessorService = new RepoAccountProcessorService( _mockCoreDao.Object, new RedemptionExpiredDateCalculator(), _mockAccountAlertCheckService.Object, _mockEventAlertService.Object, _mockRepoCompanySelectionService.Object); _repoAccountProcessor = new RepoAccountProcessor( _repoAccountProcessorService, _mockAccountAlertCheckService.Object, _mockCollectionsDao.Object, _mockEmailer.Object, _mockSettingsService.Object, _mockRepoAccountService.Object, _mockRepoLetterService.Object, _mockCoreDao.Object, _mockAuctionAssignmentService.Object); // _mockRepoAccountProcessorService.Setup(mock => mock.TryUpdateCollateralRetitleDate(It.IsAny(), It.IsAny())); } [Fact] public async Task Basic_Construct_Test() { Assert.NotNull(_repoAccountProcessor); await Assert.ThrowsAsync(() => { return _repoAccountProcessor.HandleAccount(null); }); } /** * Use this test to make more tests when things go wrong, you can dump raw JSON files from the sources into the test * and make sure you get expected results. Remember to remove member's PII. */ [Fact] public async Task Should_Create_Account() { var testInput = DbContextFromJson.GetTestObjectFromFile("Services/Processor/newAccount.json"); Assert.NotNull(testInput); _mockCollectionsDao.Setup(cd => cd.RetrieveAccountAsync(It.IsAny())).ReturnsAsync(testInput.TemenosAccount); _mockRepoAccountService.Setup(ras => ras.GetNewestOpenAccount(It.IsAny())) .ReturnsAsync((RepoAccount) null); _mockCoreDao.Setup(cd => cd.RetrieveLoanAsync(It.IsAny())).ReturnsAsync(testInput.LoanDetail); _mockCoreDao.Setup(cd => cd.RetrieveMemberAsync(It.IsAny())).ReturnsAsync(testInput.MemberDetail); _mockCoreDao.Setup(cd => cd.RetrieveTransactionsAsync(It.IsAny())).ReturnsAsync(testInput.CoreTransactions); _mockCoreDao.Setup(cd => cd.RetrieveCollateralAsync(It.IsAny())).ReturnsAsync(testInput.CollateralDetails); _mockRepoLetterService.Setup(x => x.ListByAccountIdAsync(It.IsAny())).ReturnsAsync( RepoLetterService.ProcessLetters(testInput.TemenosHistory, testInput.RepoLetters)); _mockAuctionAssignmentService.Setup(x => x.GetListByIdsAsync(It.IsAny>())) .ReturnsAsync(new List()); var result = await _repoAccountProcessor.HandleAccount(new ProcessingItem() { AccountNo = "6466120143" }); Assert.Equal(RepoProcessingResult.Created, result); } [Fact] public void Should_Select_Correct_Case() { /** * Given an account with three cases, choose the correct one: * 1. Wrong case type * 2. Ineligible case stage (repoStatus) * 3. Eligible case with valid stage/status. */ var testInput = DbContextFromJson.GetTestObjectFromFile("Services/Processor/selectCorrectCase.json"); Assert.NotNull(testInput); var selectedCase = testInput.TemenosAccount.FindRecoveryCaseOrDefault(0); Assert.Equal( 342, selectedCase.CaseId); selectedCase = testInput.TemenosAccount.FindRecoveryCaseOrDefault(25); Assert.Equal( 25, selectedCase.CaseId); } [Fact] public async Task Should_Not_Create_Ineligible_Account_Temenos_Event() { // Temenos Events will specify a case id. var testInput = DbContextFromJson.GetTestObjectFromFile("Services/Processor/ineligibleAccount.json"); Assert.NotNull(testInput); _mockCollectionsDao.Setup(cd => cd.RetrieveAccountAsync(It.IsAny())).ReturnsAsync(testInput.TemenosAccount); _mockRepoAccountService.Setup(ras => ras.GetNewestOpenAccount(It.IsAny())) .ReturnsAsync((RepoAccount) null); _mockCoreDao.Setup(cd => cd.RetrieveLoanAsync(It.IsAny())).ReturnsAsync(testInput.LoanDetail); _mockCoreDao.Setup(cd => cd.RetrieveMemberAsync(It.IsAny())).ReturnsAsync(testInput.MemberDetail); _mockCoreDao.Setup(cd => cd.RetrieveTransactionsAsync(It.IsAny())).ReturnsAsync(testInput.CoreTransactions); _mockCoreDao.Setup(cd => cd.RetrieveCollateralAsync(It.IsAny())).ReturnsAsync(testInput.CollateralDetails); _mockRepoLetterService.Setup(x => x.ListByAccountIdAsync(It.IsAny())).ReturnsAsync( RepoLetterService.ProcessLetters(testInput.TemenosHistory, testInput.RepoLetters)); _mockAuctionAssignmentService.Setup(x => x.GetListByIdsAsync(It.IsAny>())) .ReturnsAsync(new List()); var result = await _repoAccountProcessor.HandleAccount(new ProcessingItem() { AccountNo = "6466120143", CaseId = "306" }); Assert.Equal(RepoProcessingResult.Ineligible, result); } [Fact] public async Task Should_Update_Retitled_And_Redemption_Expired_Account() { RepoAccount resultAccount = null; var testInput = DbContextFromJson.GetTestObjectFromFile("Services/Processor/update-retitle-redemption-exp.json"); Assert.NotNull(testInput); _mockCollectionsDao.Setup(cd => cd.RetrieveAccountAsync(It.IsAny())).ReturnsAsync(testInput.TemenosAccount); _mockRepoAccountService.Setup(ras => ras.GetNewestOpenAccount(It.IsAny())) .ReturnsAsync(testInput.RepoAccount); _mockRepoAccountService.Setup(x => x.UpdateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync((RepoAccount inAccount, AppUser inUser) => { resultAccount = inAccount; return inAccount; }); _mockCoreDao.Setup(cd => cd.RetrieveLoanAsync(It.IsAny())).ReturnsAsync(testInput.LoanDetail); _mockCoreDao.Setup(cd => cd.RetrieveMemberAsync(It.IsAny())).ReturnsAsync(testInput.MemberDetail); _mockCoreDao.Setup(cd => cd.RetrieveTransactionsAsync(It.IsAny())).ReturnsAsync(testInput.CoreTransactions); _mockRepoLetterService.Setup(x => x.ListByAccountIdAsync(It.IsAny())).ReturnsAsync( RepoLetterService.ProcessLetters(testInput.TemenosHistory, testInput.RepoLetters)); _mockAuctionAssignmentService.Setup(x => x.GetListByIdsAsync(It.IsAny>())) .ReturnsAsync(new List()); // Pre-Assert. Assert.Null(resultAccount); Assert.Null(testInput.RepoAccount.RedemptionExpiredDate); Assert.NotNull(testInput.TemenosAccount.Cases.First().RedemptionExpiredDateWi); var existingSelections = testInput.RepoAccount.Collaterals.First(); Assert.Null(existingSelections.RetitledInLandmarkName); Assert.NotEmpty(existingSelections.RepoCompanySelections); Assert.Collection(existingSelections.RepoCompanySelections, item => { Assert.Equal(5, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }); // Run var result = await _repoAccountProcessor.HandleAccount(new ProcessingItem() { AccountNo = "7584700143" }); // Post-Assert Assert.Equal(RepoProcessingResult.Updated, result); Assert.NotNull(resultAccount); Assert.NotNull(resultAccount.RedemptionExpiredDate); var newSelections = resultAccount.Collaterals.First(); Assert.NotNull(newSelections.RetitledInLandmarkName); Assert.Collection(newSelections.RepoCompanySelections, item => { Assert.Equal(5, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); } ); } [Fact] public async Task Should_Update_WrittenOff_And_RepoSelection_Account() { RepoAccount resultAccount = null; var testInput = DbContextFromJson.GetTestObjectFromFile("Services/Processor/written-off-account.json"); Assert.NotNull(testInput); _mockCollectionsDao.Setup(cd => cd.RetrieveAccountAsync(It.IsAny())).ReturnsAsync(testInput.TemenosAccount); _mockRepoAccountService.Setup(ras => ras.GetNewestOpenAccount(It.IsAny())) .ReturnsAsync(testInput.RepoAccount); _mockRepoAccountService.Setup(x => x.UpdateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync((RepoAccount inAccount, AppUser inUser) => { resultAccount = inAccount; return inAccount; }); _mockCoreDao.Setup(cd => cd.RetrieveLoanAsync(It.IsAny())).ReturnsAsync(testInput.LoanDetail); _mockCoreDao.Setup(cd => cd.RetrieveMemberAsync(It.IsAny())).ReturnsAsync(testInput.MemberDetail); _mockCoreDao.Setup(cd => cd.RetrieveTransactionsAsync(It.IsAny())).ReturnsAsync(testInput.CoreTransactions); _mockRepoLetterService.Setup(x => x.ListByAccountIdAsync(It.IsAny())).ReturnsAsync( RepoLetterService.ProcessLetters(testInput.TemenosHistory, testInput.RepoLetters)); _mockAuctionAssignmentService.Setup(x => x.GetListByIdsAsync(It.IsAny>())) .ReturnsAsync(new List()); // Pre-Assert. Assert.Null(resultAccount); Assert.Null(testInput.RepoAccount.ReferenceStatus); Assert.Null(testInput.RepoAccount.WrittenOffDate); var existingSelections = testInput.RepoAccount.Collaterals.First(); Assert.NotEmpty(existingSelections.RepoCompanySelections); Assert.Collection(existingSelections.RepoCompanySelections, item => { Assert.Equal(4, item.RepoCompanyId); Assert.Null(item.DateRepoed); }, item => { Assert.Equal(13, item.RepoCompanyId); Assert.Null(item.DateRepoed); }); // Run var result = await _repoAccountProcessor.HandleAccount(new ProcessingItem() { AccountNo = "5730350143" }); // Post-Assert Assert.Equal(RepoProcessingResult.Updated, result); Assert.NotNull(resultAccount); Assert.Equal("Written Off", resultAccount.ReferenceStatus); Assert.NotNull(resultAccount.WrittenOffDate); var newSelections = resultAccount.Collaterals.First(); Assert.Collection(newSelections.RepoCompanySelections, item => { Assert.Equal(4, item.RepoCompanyId); Assert.Null(item.DateRepoed); }, item => { Assert.Equal(13, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(7, item.RepoCompanyId); Assert.Null(item.DateRepoed); } ); } [Fact] public async Task Should_Update_WrittenOff_And_RepoSelection_Account2() { RepoAccount resultAccount = null; var testInput = DbContextFromJson.GetTestObjectFromFile("Services/Processor/written-off-account-2.json"); Assert.NotNull(testInput); _mockCollectionsDao.Setup(cd => cd.RetrieveAccountAsync(It.IsAny())).ReturnsAsync(testInput.TemenosAccount); _mockRepoAccountService.Setup(ras => ras.GetNewestOpenAccount(It.IsAny())) .ReturnsAsync(testInput.RepoAccount); _mockRepoAccountService.Setup(x => x.UpdateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync((RepoAccount inAccount, AppUser inUser) => { resultAccount = inAccount; return inAccount; }); _mockCoreDao.Setup(cd => cd.RetrieveLoanAsync(It.IsAny())).ReturnsAsync(testInput.LoanDetail); _mockCoreDao.Setup(cd => cd.RetrieveMemberAsync(It.IsAny())).ReturnsAsync(testInput.MemberDetail); _mockCoreDao.Setup(cd => cd.RetrieveTransactionsAsync(It.IsAny())).ReturnsAsync(testInput.CoreTransactions); _mockRepoLetterService.Setup(x => x.ListByAccountIdAsync(It.IsAny())).ReturnsAsync( RepoLetterService.ProcessLetters(testInput.TemenosHistory, testInput.RepoLetters)); _mockAuctionAssignmentService.Setup(x => x.GetListByIdsAsync(It.IsAny>())) .ReturnsAsync(new List()); // Pre-Assert. Assert.Null(resultAccount); Assert.Equal("Written Off", testInput.RepoAccount.ReferenceStatus); Assert.Null(testInput.RepoAccount.WrittenOffDate); var existingSelections = testInput.RepoAccount.Collaterals.First(); Assert.NotEmpty(existingSelections.RepoCompanySelections); Assert.Collection(existingSelections.RepoCompanySelections, item => { Assert.Equal(11, item.RepoCompanyId); Assert.Null(item.DateRepoed); }, item => { Assert.Equal(11, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(1, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(5, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(13, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(13, item.RepoCompanyId); Assert.Null(item.DateRepoed); }); // Run var result = await _repoAccountProcessor.HandleAccount(new ProcessingItem() { AccountNo = "7115520143" }); // Post-Assert Assert.Equal(RepoProcessingResult.Updated, result); Assert.NotNull(resultAccount); Assert.Equal("Written Off", resultAccount.ReferenceStatus); Assert.NotNull(resultAccount.WrittenOffDate); var newSelections = resultAccount.Collaterals.First(); Assert.Collection(existingSelections.RepoCompanySelections, item => { Assert.Equal(11, item.RepoCompanyId); Assert.Null(item.DateRepoed); }, item => { Assert.Equal(11, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(1, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(5, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(13, item.RepoCompanyId); Assert.NotNull(item.DateRepoed); }, item => { Assert.Equal(13, item.RepoCompanyId); Assert.Null(item.DateRepoed); }); } } }