using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LCU.API.Internal.Operations.IncentiveApiLib.Persistence; using LCU.API.Internal.Operations.IncentiveApiLib.Repositories; using LCU.API.Internal.Operations.IncentiveApi.Services; using LCU.Library.Internal.IncentiveApiModels.Entities; using LCU.Library.Internal.IncentiveApiModels.Enums; using LCU.API.Internal.Operations.IncentiveApiLib.Extensions; using Microsoft.EntityFrameworkCore; using Moq; using NUnit.Framework; using NewLoanSaleActivity = LCU.API.Internal.Operations.IncentiveApi.Models.ExternalActivities.NewLoanSaleActivity; using LCU.API.Internal.Operations.IncentiveApi.Exceptions; using LCU.API.Internal.Operations.IncentiveApiLib.Services; using LCU.Library.Internal.IncentiveApiModels.Common; using LCU.API.Internal.Operations.IncentiveApi.Models.DataTransfer; using LCU.API.Internal.Operations.IncentiveApi.Services.DuplicateDetection; using LCU.API.Internal.Operations.IncentiveApi.Models.ExternalActivities; using LCU.API.Internal.Operations.IncentiveApi.Services.MicroApiServices; using LCU.Library.Internal.IncentiveApiModels.Requests; namespace Application.UnitTests.Services { public class ActivityServiceTest { private ActivityService _activityService; private IActivityRepository _activityRepository; private IActivityChangeRepository _activityChangeRepository; private IActivityTransferActionRepository _activityTransferActionRepository; private ActivityService _mockedActivityService; private Mock _mockActivityRepository; private Mock _mockUnitOfWork; private Mock _mockActivityChangeRepository; private Mock _mockActivityTransferActionRepository; private Mock _mockUserService; private Mock _mockNotificationService; private Mock _mockDuplicateDetector; private Mock _mockAuthorizationService; [SetUp] public void Setup() { var mockDateTime = new DateTimeService(); var mockCurrentUserService = Mock.Of(); Mock.Get(mockCurrentUserService).Setup(s => s.GetCurrentUser()).Returns(new ApplicationUser() { Email = "JohnTest@test.com", }); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .EnableSensitiveDataLogging(true) .Options; var context = new ApplicationDbContext(options, mockCurrentUserService, mockDateTime); _activityRepository = new ActivityRepository(context); _activityChangeRepository = new ActivityChangeRepository(context); _activityTransferActionRepository = new ActivityTransferActionRepository(context); _mockUserService = new Mock(); _mockNotificationService = new Mock(); _mockDuplicateDetector = new Mock(); _mockAuthorizationService = new Mock(); _activityService = new ActivityService(_activityRepository, _activityChangeRepository, _activityTransferActionRepository, _mockUserService.Object, _mockNotificationService.Object, _mockDuplicateDetector.Object, _mockAuthorizationService.Object, new UnitOfWork(context)); //Create Fully Mocked Activity Service for Conditional Testing _mockActivityRepository = new Mock(); _mockActivityChangeRepository = new Mock(); _mockActivityTransferActionRepository = new Mock(); _mockUnitOfWork = new Mock(); _mockedActivityService = new ActivityService(_mockActivityRepository.Object, _mockActivityChangeRepository.Object, _mockActivityTransferActionRepository.Object, _mockUserService.Object, _mockNotificationService.Object, _mockDuplicateDetector.Object, _mockAuthorizationService.Object, _mockUnitOfWork.Object); } [Test] public async Task Basic_Flow() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); var saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsEmpty(saved); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity = new Activity() { Id = 1, SourceId = "1", DepartmentId = 10, EmployeeId = "113322" }; var result = await _activityService.SaveActivityAsync(activity); Assert.NotNull(result); saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsNotEmpty(saved); _mockDuplicateDetector.Verify(x => x.TryFindDuplicates(It.IsAny()), Times.Once); } [Test] public async Task BasicSaveWithGapLogging_Flow() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); var saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsEmpty(saved); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Dna, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = "No company", AccountBalance = 100000, IsGapInsuranceEligible = false, } }; var result = await _activityService.SaveActivityAsync(activity); Assert.NotNull(result); saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsNotEmpty(saved); _mockDuplicateDetector.Verify(x => x.TryFindDuplicates(It.IsAny()), Times.Once); } [Test] public async Task BasicSaveWithNoGapLogging_Flow() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); var saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsEmpty(saved); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Dna, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = "company LLC", AccountBalance = 100000, IsGapInsuranceEligible = false, } }; var result = await _activityService.SaveActivityAsync(activity); Assert.NotNull(result); saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsNotEmpty(saved); _mockDuplicateDetector.Verify(x => x.TryFindDuplicates(It.IsAny()), Times.Once); } [Test] public void LogGapInformationFalseWithLLC() { var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Dna, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = " llc", AccountBalance = 100000, IsGapInsuranceEligible = false, } }; var result = ActivityService.LogGapInformation(activity); Assert.False(result); } [Test] public void LogGapInformationTrueWithoutLLC() { var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Dna, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = "Normal Member", AccountBalance = 100000, IsGapInsuranceEligible = false, } }; var result = ActivityService.LogGapInformation(activity); Assert.True(result); } [Test] public void LogGapInformationFalseWithInc() { var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Dna, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = " Inc", AccountBalance = 100000, IsGapInsuranceEligible = false, } }; var result = ActivityService.LogGapInformation(activity); Assert.False(result); } [Test] public void LogGapInformationFalseWithoutSourceDna() { var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Allied, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = "Normal", AccountBalance = 100000, IsGapInsuranceEligible = false, } }; var result = ActivityService.LogGapInformation(activity); Assert.False(result); } [Test] public void LogGapInformationFalseWithoutBalanceAmount() { var activity = new Activity() { Id = 1, SourceId = "1", SourceSystem = SystemType.Allied, DepartmentId = 10, EmployeeId = "113322", Product = Product.Vehicle, Detail = new() { MemberName = "Normal", AccountBalance = 100001, IsGapInsuranceEligible = false, } }; var result = ActivityService.LogGapInformation(activity); Assert.False(result); } [Test] public async Task Save_RequiresValues_OK() { var saved = await _activityService.GetActivitiesAsync(); Assert.NotNull(saved); Assert.IsEmpty(saved); var activity = new Activity() { }; Assert.ThrowsAsync(async () => await _activityService.SaveActivityAsync(activity)); activity = new Activity() { EmployeeId = "Test", DepartmentId = -1, }; Assert.ThrowsAsync(async () => await _activityService.SaveActivityAsync(activity)); activity = new Activity() { DepartmentId = 5, EmployeeId = null, }; Assert.ThrowsAsync(async () => await _activityService.SaveActivityAsync(activity)); } [Test] public async Task DuplicateActivity_BasicFlow() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity1 = new Activity() { DepartmentId = 55, EmployeeId = "1", Type = ActivityType.Referral, Product = Product.CheckCard, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = "2", State = ActivityState.PendingReferral, Detail = new ActivityDetail() { MemberName = "John Doe", SubjectPersonNbr = "12345", SubjectOrgNbr = "123" } }; await _activityService.SaveActivityAsync(activity1); _mockDuplicateDetector.Verify(x => x.TryFindDuplicates(It.IsAny()), Times.Once); var found = await _activityService.GetActivitiesAsync(); Assert.NotNull(found); Assert.IsNotEmpty(found); Assert.AreEqual(1, found.Count()); Assert.AreEqual(0, found.Count(x => x.State == ActivityState.Rejected)); var changes = await _activityChangeRepository.GetActivityChangesByActivityId(found.First().Id); Assert.NotNull(changes); Assert.IsEmpty(changes); _mockDuplicateDetector.Reset(); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List() { activity1 }); var activity2 = new Activity() { DepartmentId = 55, EmployeeId = "1", Type = ActivityType.Referral, Product = Product.CheckCard, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = "1", State = ActivityState.PendingReferral, Detail = new ActivityDetail() { MemberName = "John Doe", SubjectPersonNbr = "12345", SubjectOrgNbr = "123" } }; await _activityService.SaveActivityAsync(activity2); found = await _activityService.GetActivitiesAsync(); Assert.NotNull(found); Assert.IsNotEmpty(found); Assert.AreEqual(2, found.Count()); Assert.AreEqual(1, found.Count(x => x.State == ActivityState.Rejected)); var rejected = found.First(x => x.State == ActivityState.Rejected); changes = await _activityChangeRepository.GetActivityChangesByActivityId(rejected.Id); Assert.NotNull(changes); Assert.IsNotEmpty(changes); Assert.AreEqual(changes.First().ActivityId, rejected.Id); Assert.AreEqual(changes.First().State, ActivityState.Rejected); _mockDuplicateDetector.Verify(x => x.TryFindDuplicates(It.IsAny()), Times.Once); } [Test] public async Task Basic_State_Change_Flow() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activityAccepted = DateTime.Today.AddDays(-2); var activity = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = activityAccepted, SourceId = "2", State = ActivityState.Created }; var activityId = await _activityService.SaveActivityAsync(activity); var stateChange1 = new ActivityStateChange() { ActivityId = activityId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Rejected }; var updatedActivity = await _activityService.ApplyStateChange(stateChange1); Assert.NotNull(updatedActivity); Assert.AreEqual(ActivityState.Rejected, updatedActivity.State); Assert.AreEqual(0, updatedActivity.MatchingActivityId); // It was rejected, so the accepted date should change... Assert.AreNotEqual(activityAccepted, updatedActivity.Accepted); var stateChange2 = new ActivityStateChange() { ActivityId = activityId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.ManualReview }; activity.Accepted = activityAccepted; updatedActivity = await _activityService.ApplyStateChange(stateChange2); Assert.NotNull(updatedActivity); Assert.AreEqual(ActivityState.ManualReview, updatedActivity.State); // don't change the date, it wasn't accepted or rejected. Assert.AreEqual(activityAccepted, updatedActivity.Accepted); var result = await _activityChangeRepository.GetActivityChangesByActivityId(activityId); Assert.NotNull(result); Assert.AreEqual(2, result.Count); Assert.AreNotEqual(activity.Created, activity.LastUpdated); updatedActivity = await _activityRepository.GetActivityById(activityId); Assert.AreEqual(ActivityState.ManualReview, updatedActivity.State); var stateChange3 = new ActivityStateChange() { ActivityId = activityId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Accepted, AcceptedDate = DateTime.Parse("2/8/2022") }; activity.Accepted = activityAccepted; updatedActivity = await _activityService.ApplyStateChange(stateChange3); Assert.NotNull(updatedActivity); Assert.AreEqual(ActivityState.Accepted, updatedActivity.State); // date is changed and set to +12 of StateChange AcceptedDate Assert.AreEqual(DateTime.Parse("2/8/2022").Date.AddHours(12), updatedActivity.Accepted); var result2 = await _activityChangeRepository.GetActivityChangesByActivityId(activityId); Assert.NotNull(result2); Assert.AreEqual(3, result2.Count); Assert.AreNotEqual(activity.Created, activity.LastUpdated); updatedActivity = await _activityRepository.GetActivityById(activityId); Assert.AreEqual(ActivityState.Accepted, updatedActivity.State); } [Test] public async Task Exception_State_Change() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activityAccepted = DateTime.Today.AddDays(-2); var activity = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = activityAccepted, SourceId = "2", State = ActivityState.Accepted }; var activityId = await _activityService.SaveActivityAsync(activity); var stateChange1 = new ActivityStateChange() { ActivityId = 9999999, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Rejected }; Assert.ThrowsAsync(async () => { await _activityService.ApplyStateChange(stateChange1); }); var stateChange2 = new ActivityStateChange() { ActivityId = activityId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Rejected, ActivityMatchId = activityId }; Assert.ThrowsAsync(async () => { await _activityService.ApplyStateChange(stateChange2); }); } [Test] public async Task Basic_State_Change_Duplicate_Reject() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activityAccepted = DateTime.Today.AddDays(-2); var activity = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = activityAccepted, SourceId = "1", State = ActivityState.Accepted }; var activityId = await _activityService.SaveActivityAsync(activity); var duplicate = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = activityAccepted, SourceId = "2", State = ActivityState.Accepted }; var duplicateId = await _activityService.SaveActivityAsync(duplicate); activity = await _activityService.GetActivity(activityId); duplicate = await _activityService.GetActivity(duplicateId); Assert.AreEqual(ActivityState.Accepted, activity.State); Assert.AreEqual(0, activity.MatchingActivityId); Assert.AreEqual(ActivityState.Accepted, duplicate.State); Assert.AreEqual(0, duplicate.MatchingActivityId); var stateChange1 = new ActivityStateChange() { ActivityId = duplicateId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Rejected, ActivityMatchId = activityId }; var updatedActivity = await _activityService.ApplyStateChange(stateChange1); activity = await _activityService.GetActivity(activityId); duplicate = await _activityService.GetActivity(duplicateId); Assert.NotNull(activity); Assert.NotNull(duplicate); Assert.AreEqual(ActivityState.Rejected, duplicate.State); Assert.AreEqual(activityId, duplicate.MatchingActivityId); Assert.AreEqual(0, activity.MatchingActivityId); // It was rejected, so the accepted date should change... Assert.AreNotEqual(activityAccepted, duplicate.Accepted); } [Test] public async Task Basic_State_Change_Manual_Review() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activityAccepted = DateTime.Today.AddDays(-2).AddHours(12); var activity = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = activityAccepted, SourceId = "2", State = ActivityState.Accepted }; var activityId = await _activityService.SaveActivityAsync(activity); activity = await _activityService.GetActivity(activityId); Assert.AreEqual(ActivityState.Accepted, activity.State); Assert.AreEqual(0, activity.MatchingActivityId); var stateChange1 = new ActivityStateChange() { ActivityId = activityId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.ManualReview }; var updatedActivity = await _activityService.ApplyStateChange(stateChange1); activity = await _activityService.GetActivity(activityId); Assert.NotNull(activity); Assert.AreEqual(ActivityState.ManualReview, activity.State); Assert.AreEqual(0, activity.MatchingActivityId); // accepted date should not change... Assert.AreEqual(activityAccepted, activity.Accepted); } [Test] public async Task ApplyStateChange_Exception_No_Existing_Activity() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, SourceId = "2", State = ActivityState.Created }; var activityId = await _activityService.SaveActivityAsync(activity); var stateChange1 = new ActivityStateChange() { ActivityId = 1155151511, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Rejected }; Assert.ThrowsAsync(async () => { await _activityService.ApplyStateChange(stateChange1); }); var result = await _activityChangeRepository.GetActivityChangesByActivityId(1155151511); Assert.NotNull(result); Assert.AreEqual(0, result.Count); } [Test] public async Task ApplyStateChange_No_Change() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, LastUpdated = DateTime.Parse("1999/12/31"), Accepted = DateTime.Now, SourceId = "1", State = ActivityState.Created }; var activityId = await _activityService.SaveActivityAsync(activity); var stateChange1 = new ActivityStateChange() { ActivityId = activityId, Created = DateTime.Today, CreatedBy = "DNA", CreatedByType = UserType.System, State = ActivityState.Created }; System.Threading.Thread.Sleep(100); //Assert that no change has been made to the existing activity for duplicate state activity = await _activityService.ApplyStateChange(stateChange1); Assert.AreNotEqual(activity.Created, activity.LastUpdated); var result = await _activityChangeRepository.GetActivityChangesByActivityId(activityId); Assert.NotNull(result); Assert.AreEqual(1, result.Count); } [Test] public async Task GetActivityForStateUpdate_Exception_No_Existing_Activity() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); var existingActivity = new Activity { Id = 1, DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.GAPInsurance, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), State = ActivityState.Accepted, SourceId = "1", Detail = new ActivityDetail() { AccountNumber = "867530986", MemberName = "ORLANDO TESTCUSTOMER10" } }; var activityId = await _activityService.SaveActivityAsync(existingActivity); var updateActivity = new Activity { DepartmentId = existingActivity.DepartmentId, EmployeeId = existingActivity.EmployeeId, Type = existingActivity.Type, Product = existingActivity.Product, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = existingActivity.SourceId, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), State = existingActivity.State, Detail = existingActivity.Detail }; Assert.DoesNotThrowAsync(async () => { await _activityService.GetActivityForStateUpdate(existingActivity); }); Assert.DoesNotThrowAsync(async () => { await _activityService.GetActivityForStateUpdate(updateActivity); }); } [Test] public async Task GetActivityForStateUpdate_Ok() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); var existingActivity = new Activity { Id = 1, DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.GAPInsurance, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = "2", State = ActivityState.Accepted, Detail = new ActivityDetail() { AccountNumber = "867530986", MemberName = "ORLANDO TESTCUSTOMER10" } }; var activityId = await _activityService.SaveActivityAsync(existingActivity); var updateActivity = new Activity { DepartmentId = existingActivity.DepartmentId, EmployeeId = existingActivity.EmployeeId, Type = existingActivity.Type, Product = existingActivity.Product, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = existingActivity.SourceId, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), State = ActivityState.Rejected, Detail = existingActivity.Detail }; System.Threading.Thread.Sleep(100); var returnedActivity = await _activityService.GetActivityForStateUpdate(updateActivity); Assert.AreNotEqual(existingActivity, updateActivity); Assert.AreEqual(existingActivity, returnedActivity); } [Test] public async Task ListByFilterAsync_JustPage_Ok() { _mockActivityRepository.Setup(x => x.GetPagedFilteredActivities(It.IsAny())) .ReturnsAsync(new PagedResult() { Items = new List(), Total = 1000 }); _mockActivityRepository.Setup(x => x.GetActivitiesAsync(It.IsAny(), It.IsAny())) .Verifiable(); var result = await _mockedActivityService.ListByFilterAsync(new ActivityFilter() { Page = 1, Limit = 100 }); Assert.NotNull(result); Assert.AreEqual(1000, result.Total); //When states null, calls GetActivityAsync _mockActivityRepository.Verify( x => x.GetPagedFilteredActivities(It.IsAny()), Times.Once); _mockActivityRepository.Verify(x => x.GetActivitiesAsync(It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task ListByFilterAsync_NoResults_Ok() { _mockActivityRepository.Setup(x => x.GetPagedFilteredActivities(It.IsAny())) .ReturnsAsync(new PagedResult() { Items = new List(), Total = 0 }); _mockActivityRepository.Setup(x => x.GetActivitiesAsync(It.IsAny(), It.IsAny())) .Verifiable(); var result = await _mockedActivityService.ListByFilterAsync(new ActivityFilter() { Page = 1, Limit = 100 }); Assert.NotNull(result); Assert.AreEqual(0, result.Total); _mockActivityRepository.Verify( x => x.GetPagedFilteredActivities(It.IsAny()), Times.Once); _mockActivityRepository.Verify(x => x.GetActivitiesAsync(It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task GetDepartmentActivityForMonthRangeAsync_BasicFlow() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); _mockDuplicateDetector.Setup(x => x.TryFindDuplicates(It.IsAny())) .ReturnsAsync(new List()); var activity1 = new Activity() { DepartmentId = 55, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, SourceId = "1", Accepted = DateTime.Today }; await _activityService.SaveActivityAsync(activity1); var activity2 = new Activity() { DepartmentId = 56, EmployeeId = "11771", Type = ActivityType.Sale, Product = Product.CheckCard, SourceId = "2", Accepted = DateTime.Today }; await _activityService.SaveActivityAsync(activity2); var activity3 = new Activity() { DepartmentId = 55, EmployeeId = "11772", Type = ActivityType.Sale, Product = Product.CheckCard, SourceId = "3", Accepted = DateTime.Today.AddMonths(-1) }; await _activityService.SaveActivityAsync(activity3); var user = new AppUser() { Role = Role.Admin, AdEmail = "tester@test.com", BaseRole = "Tester", EmployeeId = "11771", FullName = "Test McTester", HomeDepartment = "HOME", PersonId = 11771, Departments = new List() { new UserDepartment() { DepartmentId = 55, Department = new Department() { Id = 55, State = DepartmentState.Active, DepartmentName = "Test", BusinessLineCode = BusinessLine.Operations.Code } } } }; var range = new MonthRange ( DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Year, DateTime.Today.Month ); var found = await _activityService.GetDepartmentActivityForMonthRangeAsync(user.Departments, range); Assert.NotNull(found); Assert.IsNotEmpty(found.First().Progress.ProductActivity); Assert.IsNotEmpty(found.First().ActivityAudit); Assert.AreEqual(1, found.First().ActivityAudit.Count()); } [Test] public async Task GetDepartmentActivityForMonthRangeAsync_NoAssignmentInMonthRange_ReturnsEmpty() { var userDepartments = new List { new UserDepartment() { DepartmentId = 55, Department = new Department() { Id = 55, State = DepartmentState.Active, DepartmentName = "Test", BusinessLineCode = BusinessLine.Operations.Code }, StartDate = DateTime.Today, EndDate = DateTime.Today } }; var range = new MonthRange( 2021, 11, 2021, 12 ); var found = await _activityService.GetDepartmentActivityForMonthRangeAsync(userDepartments, range); Assert.IsEmpty(found); } [Test] public async Task GetActivity_ReturnsActivity() { var activityFromRepo = new Activity { Id = 3, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, Detail = new ActivityDetail(), ActivityPayouts = new List() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(3)) .ReturnsAsync(activityFromRepo); var result = await _mockedActivityService.GetActivity(3); Assert.NotNull(result); Assert.AreEqual(3, result.Id); } [Test] public async Task MatchOrExpireReferrals_Match_OnPersonId() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }); var activityOne = new Activity { Id = 67260, DepartmentId = 53, EmployeeId = "9585", Type = ActivityType.Sale, Product = Product.NewChecking, Accepted = DateTime.Today, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = "255557196", State = ActivityState.Accepted, Detail = new ActivityDetail { IsDebtProtectionEligible = false, SubjectPersonNbr = "80542" } }; var activityTwo = new Activity { Id = 67247, DepartmentId = 53, EmployeeId = "12133", Type = ActivityType.Referral, Product = Product.NewChecking, Accepted = DateTime.Today, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceId = "4977", State = ActivityState.PendingReferral, Detail = new ActivityDetail { IsDebtProtectionEligible = false, SubjectPersonNbr = "80542" } }; await _activityService.SaveActivityAsync(activityOne); await _activityService.SaveActivityAsync(activityTwo); await _activityService.MatchOrExpireReferrals(); var activityOneStateChanges = await _activityService.GetActivityStateChanges(activityOne.Id); var activityTwoStateChanges = await _activityService.GetActivityStateChanges(activityTwo.Id); Assert.NotNull(activityOneStateChanges); Assert.NotNull(activityTwoStateChanges); Assert.IsEmpty(activityOneStateChanges); Assert.IsNotEmpty(activityTwoStateChanges); Assert.AreEqual(activityOne.Id, activityTwoStateChanges.FirstOrDefault().ActivityMatchId); _mockUserService.Verify(mock => mock.GetUserByEmployeeIdAsync(It.IsAny()), Times.Never); } [Test] public async Task MatchOrExpireReferrals_NoMatch_NoExpire() { var referral1 = new Activity { Id = 1, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, Detail = new ActivityDetail(), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), ActivityPayouts = new List() }; var referral2 = new Activity { Id = 2, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, Detail = new ActivityDetail(), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), ActivityPayouts = new List() }; var basicList = new List() { referral1, referral2 }; _mockActivityRepository.Setup(mock => mock.FindUnmatchedReferrals()) .ReturnsAsync(basicList); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral1)) .ReturnsAsync((Activity)null); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral2)) .ReturnsAsync((Activity)null); _mockActivityRepository.Setup(mock => mock.GetActivityById(1)) .ReturnsAsync(referral1); _mockActivityRepository.Setup(mock => mock.GetActivityById(2)) .ReturnsAsync(referral2); _mockActivityChangeRepository.Setup(mock => mock.SaveActivityStateChange(It.IsAny())) .Verifiable(); _mockUnitOfWork.Setup(mock => mock.CompleteAsync()).Verifiable(); var results = await _mockedActivityService.MatchOrExpireReferrals(); Assert.NotNull(results); Assert.IsEmpty(results); _mockActivityRepository.Verify(mock => mock.FindUnmatchedReferrals(), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral1), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral2), Times.Once); _mockActivityRepository.Verify(mock => mock.GetActivityById(1), Times.Never); _mockActivityRepository.Verify(mock => mock.GetActivityById(2), Times.Never); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Never); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); _mockUserService.Verify(mock => mock.GetUserByEmployeeIdAsync(It.IsAny()), Times.Never); } [Test] public async Task MatchOrExpireReferrals_Match_NoExpire() { var referral1 = new Activity { Id = 1, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), Detail = new ActivityDetail(), ActivityPayouts = new List() }; var referral2 = new Activity { Id = 2, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), Detail = new ActivityDetail(), ActivityPayouts = new List() }; var sale1 = new Activity { Id = 3, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today, SourceCreated = DateTime.Today, Detail = new ActivityDetail(), ActivityPayouts = new List() }; var basicList = new List() { referral1, referral2 }; _mockActivityRepository.Setup(mock => mock.FindUnmatchedReferrals()) .ReturnsAsync(basicList); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral1)) .ReturnsAsync((Activity)sale1); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral2)) .ReturnsAsync((Activity)null); _mockActivityRepository.Setup(mock => mock.GetActivityById(1)) .ReturnsAsync(referral1); _mockActivityRepository.Setup(mock => mock.GetActivityById(2)) .ReturnsAsync(referral2); _mockActivityRepository.Setup(mock => mock.GetActivityById(3)) .ReturnsAsync(sale1); _mockActivityChangeRepository.Setup(mock => mock.SaveActivityStateChange(It.IsAny())) .Verifiable(); _mockUnitOfWork.Setup(mock => mock.CompleteAsync()).Verifiable(); var results = await _mockedActivityService.MatchOrExpireReferrals(); Assert.NotNull(results); Assert.IsNotEmpty(results); Assert.AreEqual(ActivityState.Accepted, results.First().State); _mockActivityRepository.Verify(mock => mock.FindUnmatchedReferrals(), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral1), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral2), Times.Once); _mockActivityRepository.Verify(mock => mock.GetActivityById(1), Times.Once); _mockActivityRepository.Verify(mock => mock.GetActivityById(2), Times.Never); // They matched! so they should be linked together. Assert.AreEqual(sale1.Id, referral1.MatchingActivityId); Assert.AreEqual(referral1.Id, sale1.MatchingActivityId); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Once); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Once); _mockUserService.Verify(mock => mock.GetUserByEmployeeIdAsync(It.IsAny()), Times.Never); } [Test] public async Task MatchOrExpireReferrals_NoMatch_Expire() { var referral1 = new Activity { Id = 1, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(61)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(61)), Detail = new ActivityDetail(), ActivityPayouts = new List() }; var referral2 = new Activity { Id = 2, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.CheckCard, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(7)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), Detail = new ActivityDetail(), ActivityPayouts = new List() }; var referral3 = new Activity { Id = 3, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.FirstMortgageReferral, Accepted = DateTime.Today.Subtract(TimeSpan.FromDays(121)), SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(121)), Detail = new ActivityDetail(), ActivityPayouts = new List() }; var basicList = new List() { referral1, referral2, referral3 }; _mockActivityRepository.Setup(mock => mock.FindUnmatchedReferrals()) .ReturnsAsync(basicList); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral1)) .ReturnsAsync((Activity)null); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral2)) .ReturnsAsync((Activity)null); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral3)) .ReturnsAsync((Activity)null); _mockActivityRepository.Setup(mock => mock.GetActivityById(1)) .ReturnsAsync(referral1); _mockActivityRepository.Setup(mock => mock.GetActivityById(2)) .ReturnsAsync(referral2); _mockActivityRepository.Setup(mock => mock.GetActivityById(3)) .ReturnsAsync(referral3); _mockActivityChangeRepository.Setup(mock => mock.SaveActivityStateChange(It.IsAny())) .Verifiable(); _mockUnitOfWork.Setup(mock => mock.CompleteAsync()).Verifiable(); var results = await _mockedActivityService.MatchOrExpireReferrals(); Assert.NotNull(results); Assert.IsNotEmpty(results); Assert.AreEqual(ActivityState.Rejected, results.Single(r => r.ActivityId == 1).State); Assert.AreEqual(ActivityState.Rejected, results.Single(r => r.ActivityId == 3).State); _mockActivityRepository.Verify(mock => mock.FindUnmatchedReferrals(), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral1), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral2), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral3), Times.Once); _mockActivityRepository.Verify(mock => mock.GetActivityById(1), Times.Once); _mockActivityRepository.Verify(mock => mock.GetActivityById(2), Times.Never); _mockActivityRepository.Verify(mock => mock.GetActivityById(3), Times.Once); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Exactly(2)); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Exactly(2)); } [Test] public async Task MatchOrExpireReferrals_SameEmployeeOnMatchedActivities_RejectReferral() { var referral = new Activity { Id = 1, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Referral, Product = Product.NewChecking, // Only NewChecking referrals are rejected in this scenario Accepted = DateTime.Today, SourceCreated = DateTime.Today.Subtract(TimeSpan.FromDays(7)), Detail = new ActivityDetail(), ActivityPayouts = new List() }; var sale = new Activity { Id = 3, DepartmentId = 32, EmployeeId = "1", Type = ActivityType.Sale, Product = Product.NewChecking, Accepted = DateTime.Today, SourceCreated = DateTime.Today, Detail = new ActivityDetail(), ActivityPayouts = new List() }; var creditedEmployee = new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "1", Departments = { new UserDepartment { DepartmentId = 1 } } }; _mockActivityRepository.Setup(mock => mock.FindUnmatchedReferrals()) .ReturnsAsync(new List() { referral }); _mockActivityRepository.Setup(mock => mock.FindUnmatchedSaleForReferral(referral)) .ReturnsAsync((Activity)sale); _mockActivityRepository.Setup(mock => mock.GetActivityById(referral.Id)) .ReturnsAsync(referral); _mockActivityRepository.Setup(mock => mock.GetActivityById(sale.Id)) .ReturnsAsync(sale); _mockUserService.Setup(mock => mock.GetUserByEmployeeIdAsync(sale.EmployeeId)) .ReturnsAsync(creditedEmployee); _mockActivityChangeRepository.Setup(mock => mock.SaveActivityStateChange(It.IsAny())) .Verifiable(); _mockUnitOfWork.Setup(mock => mock.CompleteAsync()).Verifiable(); var results = await _mockedActivityService.MatchOrExpireReferrals(); Assert.NotNull(results); Assert.IsNotEmpty(results); //There are two state changes, one for accepted and the other for rejected Assert.IsTrue(results.Count == 2); Assert.AreEqual(ActivityState.Accepted, results.ElementAt(0).State); Assert.AreEqual(ActivityState.Rejected, results.ElementAt(1).State); _mockActivityRepository.Verify(mock => mock.FindUnmatchedReferrals(), Times.Once); _mockActivityRepository.Verify(mock => mock.FindUnmatchedSaleForReferral(referral), Times.Once); _mockActivityRepository.Verify(mock => mock.GetActivityById(1), Times.Exactly(2)); // They matched! so they should be linked together. Assert.AreEqual(sale.Id, referral.MatchingActivityId); Assert.AreEqual(referral.Id, sale.MatchingActivityId); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Exactly(2)); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Exactly(2)); _mockUserService.Verify(mock => mock.GetUserByEmployeeIdAsync(sale.EmployeeId), Times.Once()); } [Test] public void GetActivityAuthorizedCommands_ActivityIsNull_ThrowsNotFoundException() { _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)) .ReturnsAsync((Activity)null); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.GetActivityAuthorizedCommands(new AppUser(), 1); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("No activity with Id 1 could be found", exception.Message); } [Test] public async Task GetActivityAuthorizedCommands_PendingTransferActivity_ReturnsAuthCommands() { var inThePast = DateTime.Now.AddDays(-90); var targetDepartmentId = 2; var user = new AppUser { Departments = new List() { new UserDepartment() { DepartmentId = targetDepartmentId, StartDate = inThePast, EndDate = null, Role = Role.BOM } } }; var activity = new Activity() { Id = 1, State = ActivityState.PendingTransfer, DepartmentId = 1 }; var activityTransferAction = new ActivityTransferAction() { NewActivityDepartmentId = targetDepartmentId }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)) .ReturnsAsync(activity); _mockAuthorizationService.Setup(mock => mock.ValidateHierarchicalDepartmentPermission(user, Role.DepartmentManagerRoles, activity.DepartmentId)) .ReturnsAsync(false); _mockAuthorizationService.Setup(mock => mock.AppUserCanMakeStateChange(user, activity, It.IsAny(), It.IsAny())) .ReturnsAsync(true); _mockActivityTransferActionRepository.Setup(mock => mock.GetRequestedTransferActionByActivityId(activity.Id)) .ReturnsAsync(activity.State == ActivityState.PendingTransfer ? activityTransferAction : null); var authorizedCommands = await _mockedActivityService.GetActivityAuthorizedCommands(user, activity.Id); Assert.IsTrue(authorizedCommands.AllowedChanges.Contains(ActivityState.Transferred)); Assert.IsTrue(authorizedCommands.AllowedChanges.Contains(ActivityState.Accepted)); Assert.IsTrue(authorizedCommands.CanApproveTransferFrom); Assert.IsTrue(authorizedCommands.CanApproveTransferTo); } [Test] public void GetActivity_NotFound() { _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(3)) .ReturnsAsync((Activity)null); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.GetActivity(3); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("No activity with Id 3 could be found", exception.Message); } [Test] public void ValidateCanApplyActivityStateChange_NotFound() { var user = new AppUser(); var stateChange = new ActivityStateChange { ActivityId = 11, Note = "Change", State = ActivityState.Accepted }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync((Activity)null); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("No activity with Id 11 could be found", exception.Message); } [Test] public void ValidateCanApplyActivityStateChange_HasPayouts() { var user = new AppUser(); var stateChange = new ActivityStateChange { ActivityId = 11, Note = "Change", State = ActivityState.Accepted }; var activityWithPayouts = new Activity { ActivityPayouts = new List { new ActivityPayoutLineItem() } }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityWithPayouts); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("Cannot change the state of an activity that has a payout.", exception.Message); } [Test] public void ValidateCanApplyActivityStateChange_AcceptedDateToFarInThePast() { var user = new AppUser(); var stateChange = new ActivityStateChange { ActivityId = 11, AcceptedDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1).AddMonths(-1).AddDays(-1), Note = "Change", State = ActivityState.Accepted }; var activity = new Activity(); _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())).ReturnsAsync(activity); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("Cannot change the accepted date of an activity to a date that's already paid out, or is greater than 1 month from now.", exception.Message); } [Test] public void ValidateCanApplyActivityStateChange_AcceptedDateToFarInTheFuture() { var user = new AppUser(); var stateChange = new ActivityStateChange { ActivityId = 11, AcceptedDate = DateTime.Now.AddMonths(1).AddDays(1), Note = "Change", State = ActivityState.Accepted }; var activity = new Activity(); _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())).ReturnsAsync(activity); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("Cannot change the accepted date of an activity to a date that's already paid out, or is greater than 1 month from now.", exception.Message); } [Test] public void ValidateCanApplyActivityStateChange_NotAuthorized() { var user = new AppUser { Role = Role.UNKNOWN_ROLE, AdditionalPermissions = new List() }; var stateChange = new ActivityStateChange { ActivityId = 11, Note = "Change", State = ActivityState.Accepted }; var activityFromRepo = new Activity { State = ActivityState.ManualReview, ActivityPayouts = new List() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); Assert.AreEqual(StateChangeRequirement.AdminOrPermission, activityFromRepo.RequiredToChangeState(stateChange.State)); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("User does not have the permission to change the activity state.", exception.Message); } [Test] public async Task ValidateCanApplyActivityStateChange_ApproveSalesAsync() { var userDepartment = new UserDepartment() { DepartmentId = 55, Department = new Department() { Id = 55, State = DepartmentState.Active, DepartmentName = "Test", BusinessLineCode = BusinessLine.Operations.Code }, StartDate = DateTime.Today, Role = Role.Admin }; var user = new AppUser { AdditionalPermissions = new List(), Departments = new List { userDepartment } }; var stateChange = new ActivityStateChange { ActivityId = 11, Note = "Change", State = ActivityState.Accepted, AcceptedDate = DateTime.Now.AddDays(-1) }; var activityFromRepo = new Activity { ActivityPayouts = new List(), Type = ActivityType.Sale, State = ActivityState.ManualReview }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); _mockAuthorizationService.Setup(mock => mock.ValidateHierarchicalDepartmentPermission(user, It.IsAny>(), It.IsAny())) .ReturnsAsync(true); // Type = Sale, State = ManualReview activityFromRepo.Type = ActivityType.Sale; activityFromRepo.State = ActivityState.ManualReview; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); Assert.AreEqual(StateChangeRequirement.AdminOrPermission, activityFromRepo.RequiredToChangeState(stateChange.State)); await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); // Type = Sale, State = PendingReverral activityFromRepo.Type = ActivityType.Sale; activityFromRepo.State = ActivityState.PendingReferral; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); // Type = Referral, State = ManualReview activityFromRepo.Type = ActivityType.Referral; activityFromRepo.State = ActivityState.ManualReview; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); // Type = Referral, State = PendingReferral activityFromRepo.Type = ActivityType.Referral; activityFromRepo.State = ActivityState.PendingReferral; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); } [Test] public async Task ValidateCanApplyActivityStateChange_ApproveReferralsAsync() { var userDepartment = new UserDepartment() { DepartmentId = 55, Department = new Department() { Id = 55, State = DepartmentState.Active, DepartmentName = "Test", BusinessLineCode = BusinessLine.Operations.Code }, StartDate = DateTime.Parse("2021-11-02"), Role = Role.DepartmentManagerRoles.First() }; var user = new AppUser { AdditionalPermissions = new List(), Departments = new List { userDepartment } }; var stateChange = new ActivityStateChange { ActivityId = 11, Note = "Change", State = ActivityState.Accepted }; var activityFromRepo = new Activity { ActivityPayouts = new List(), Type = ActivityType.Referral, State = ActivityState.ManualReview }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activityFromRepo); _mockAuthorizationService.Setup(mock => mock.ValidateHierarchicalDepartmentPermission(user, It.IsAny>(), It.IsAny())) .ReturnsAsync(true); // Type = Referral, State = ManualReview activityFromRepo.Type = ActivityType.Referral; activityFromRepo.State = ActivityState.ManualReview; Assert.AreEqual(StateChangeRequirement.AdminOrPermission, activityFromRepo.RequiredToChangeState(stateChange.State)); Assert.ThrowsAsync(async () => { await _mockedActivityService.ValidateCanApplyActivityStateChange(user, stateChange); }); // Type = Referral, Accepted => Manual Review activityFromRepo.Type = ActivityType.Referral; activityFromRepo.State = ActivityState.Accepted; userDepartment.Role = Role.Admin; stateChange.State = ActivityState.ManualReview; Assert.AreEqual(StateChangeRequirement.AdminOrPermission, activityFromRepo.RequiredToChangeState(stateChange.State)); } [Test] public async Task RequestTransfer_Ok() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 2, NewEmployeeId = "C0000" }; var activtyFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List(), DepartmentId = 1, Accepted = DateTime.Today }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activtyFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(It.IsAny())) .ReturnsAsync(activtyFromRepo); var user1 = new List { new AppUser { AdEmail = "user1@landmarkcu.com" } }; var user2 = new List { new AppUser { AdEmail = "user2@landmarkcu.com" } }; _mockUserService.Setup(mock => mock.FindDepartmentManagers(1)) .ReturnsAsync(user1); _mockUserService.Setup(mock => mock.FindDepartmentManagers(2)) .ReturnsAsync(user2); var user3 = new AppUser { Id = Guid.NewGuid(), AdEmail = "newguiduser@landmarkcu.com" }; _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(user3); _mockActivityTransferActionRepository .Setup(mock => mock.SaveTransferAsync(It.IsAny())) .Callback(transfer => transfer.RequestedActivity = activtyFromRepo); var result = await _mockedActivityService.RequestTransfer(request); Assert.NotNull(result); Assert.AreEqual(ActivityState.Accepted, result.ActivityStateBeforeTransfer); Assert.AreEqual(1, result.RequestedActivityId); Assert.AreEqual(ActivityTransferState.Requested, result.State); Assert.AreEqual(2, result.NewActivityDepartmentId); Assert.AreEqual("C0000", result.NewActivityEmployeeId); Assert.AreEqual(activtyFromRepo.State, ActivityState.PendingTransfer); Assert.AreEqual(DateTime.Today, activtyFromRepo.Accepted); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(mock => mock.SaveTransferAsync(It.Is(action => action.Id == 0)), Times.Once); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.Is(change => change.ActivityId == 1 && change.Note == "" && change.State == ActivityState.PendingTransfer ))); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Once); // Verify notification sent _mockNotificationService.Verify(mock => mock.SendTransferRequestInitiatedNotification( It.IsAny(), It.Is>(recipients => recipients.Count == 2 && recipients.Contains("user1@landmarkcu.com") && recipients.Contains("user2@landmarkcu.com")) ), Times.Once); } [Test] public async Task RequestTransfer_DuplicateEmailAddresses() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 2, NewEmployeeId = "C0000" }; var activtyFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List(), DepartmentId = 1 }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activtyFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(It.IsAny())) .ReturnsAsync(activtyFromRepo); var user1 = new List { new AppUser { AdEmail = "single@landmarkcu.com" } }; var user2 = new List { new AppUser { AdEmail = "single@landmarkcu.com" } }; var user3 = new AppUser { Id = Guid.NewGuid(), AdEmail = "newguiduser@landmarkcu.com" }; _mockUserService.Setup(mock => mock.FindDepartmentManagers(1)) .ReturnsAsync(user1); _mockUserService.Setup(mock => mock.FindDepartmentManagers(2)) .ReturnsAsync(user2); _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(user3); _mockActivityTransferActionRepository .Setup(mock => mock.SaveTransferAsync(It.IsAny())) .Callback(transfer => transfer.RequestedActivity = activtyFromRepo); var result = await _mockedActivityService.RequestTransfer(request); Assert.NotNull(result); _mockNotificationService.Verify(mock => mock.SendTransferRequestInitiatedNotification( It.IsAny(), It.Is>(recipients => recipients.Count == 1 && recipients.Contains("single@landmarkcu.com")) ), Times.Once); } [Test] public void RequestTransfer_NotFoundException() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 2, NewEmployeeId = "C0000" }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync((Activity)null); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.RequestTransfer(request); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("No activity with Id 1 could be found", exception.Message); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); _mockNotificationService.Verify(mock => mock.SendTransferRequestInitiatedNotification(It.IsAny(), It.IsAny>()), Times.Never); } [Test] public void RequestTransfer_HasPayout_BadActivityTransferRequestException() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 2, NewEmployeeId = "C0000" }; var activtyFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List { new ActivityPayoutLineItem() } }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activtyFromRepo); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.RequestTransfer(request); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("Cannot request a transfer of an activity that has a payout.", exception.Message); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); _mockNotificationService.Verify(mock => mock.SendTransferRequestInitiatedNotification(It.IsAny(), It.IsAny>()), Times.Never); } [Test] public void RequestTransfer_IneligibleActivityState_BadActivityTransferRequestException() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 2, NewEmployeeId = "C0000" }; var activtyFromRepo = new Activity { Id = 1, State = ActivityState.Created, ActivityPayouts = new List() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(It.IsAny())) .ReturnsAsync(activtyFromRepo); var exception = Assert.ThrowsAsync(async () => { await _mockedActivityService.RequestTransfer(request); }); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("Cannot request a transfer that isn't pending or approved.", exception.Message); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); _mockNotificationService.Verify(mock => mock.SendTransferRequestInitiatedNotification(It.IsAny(), It.IsAny>()), Times.Never); } [Test] public async Task RequestTransferToOwnDepartment_Ok() { var employee = new AppUser { Id = Guid.NewGuid(), AdEmail = "NewGuidUser@landmarkcu.com", EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }; var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 1, NewEmployeeId = employee.EmployeeId }; var activityFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List(), DepartmentId = 2, EmployeeId = employee.EmployeeId, Detail = new ActivityDetail() }; _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())) .ReturnsAsync(employee); _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)).ReturnsAsync(activityFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(It.IsAny())).ReturnsAsync(activityFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(It.IsAny())).ReturnsAsync(activityFromRepo); _mockActivityTransferActionRepository.Setup(mock => mock.SaveTransferAsync(It.Is(x => x.Id == 0 && x.ActivityStateBeforeTransfer == ActivityState.Accepted && x.RequestedActivityId == 1 && x.State == ActivityTransferState.Accepted && x.NewActivityDepartmentId == 1 && x.NewActivityEmployeeId == "C0000" ))) .ReturnsAsync(1); var result = await _mockedActivityService.TransferToOwnDepartment(request, employee); Assert.NotNull(result); Assert.AreEqual(ActivityState.Accepted, result.ActivityStateBeforeTransfer); Assert.AreEqual(1, result.RequestedActivityId); Assert.AreEqual(1, result.NewActivityDepartmentId); Assert.AreEqual("C0000", result.NewActivityEmployeeId); Assert.AreEqual(ActivityTransferState.Accepted, result.State); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Exactly(2)); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Exactly(3)); } [Test] public void RequestTransferToOwnDepartment_ActivityNotFound_NotFoundExceptionThrown() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 1, NewEmployeeId = "C0000" }; var employee = new AppUser { EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)).ReturnsAsync((Activity)null); Assert.ThrowsAsync(() => _mockedActivityService.TransferToOwnDepartment(request, employee)); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Never); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); } [Test] public void RequestTransferToOwnDepartment_DoesNotBelongToCaller_AuthorizationExceptionThrown() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 1, NewEmployeeId = "C0000" }; var employee = new AppUser { EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }; var activityFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List(), DepartmentId = 2, EmployeeId = "C0001", Detail = new ActivityDetail() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)).ReturnsAsync(activityFromRepo); Assert.ThrowsAsync(() => _mockedActivityService.TransferToOwnDepartment(request, employee)); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Never); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); } [Test] public void RequestTransferToOwnDepartment_EmployeeDoesNotHaveDepartment_BadActivityTransferActionExceptionThrown() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 1, NewEmployeeId = "C0000" }; var employee = new AppUser { EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 2 } } }; var activityFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List(), DepartmentId = 2, EmployeeId = "C0000", Detail = new ActivityDetail() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)).ReturnsAsync(activityFromRepo); Assert.ThrowsAsync(() => _mockedActivityService.TransferToOwnDepartment(request, employee)); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Never); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); } [Test] public void RequestTransferToOwnDepartment_HasPayouts_BadActivityTransferActionExceptionThrown() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 1, NewEmployeeId = "C0000" }; var employee = new AppUser { EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }; var activityFromRepo = new Activity { Id = 1, State = ActivityState.Accepted, ActivityPayouts = new List { new ActivityPayoutLineItem { ActivityId = 1 } }, DepartmentId = 2, EmployeeId = "C0000", Detail = new ActivityDetail() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)).ReturnsAsync(activityFromRepo); Assert.ThrowsAsync(() => _mockedActivityService.TransferToOwnDepartment(request, employee)); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Never); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); } [Test] public void RequestTransferToOwnDepartment_NotAcceptedState_BadActivityTransferActionExceptionThrown() { var request = new ActivityTransferRequest { ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, NewDepartmentId = 1, NewEmployeeId = "C0000" }; var employee = new AppUser { EmployeeId = "C0000", Departments = { new UserDepartment { DepartmentId = 1 } } }; var activityFromRepo = new Activity { Id = 1, State = ActivityState.PendingReferral, ActivityPayouts = new List(), DepartmentId = 2, EmployeeId = "C0000", Detail = new ActivityDetail() }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(1)).ReturnsAsync(activityFromRepo); Assert.ThrowsAsync(() => _mockedActivityService.TransferToOwnDepartment(request, employee)); // Verify transfer action and state change is saved _mockActivityTransferActionRepository.Verify(); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange(It.IsAny()), Times.Never); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Never); } [Test] public async Task ApproveTransfer_Reject() { var approver = new AppUser { AdEmail = "manager@landmarkcu.com", EmployeeId = "M0000" }; var approval = new ActivityTransferApprovalRequest { Id = 1, ApprovalState = ActivityTransferState.Rejected }; var transferActionFromRepo = new ActivityTransferAction { State = ActivityTransferState.Requested, RequestedActivity = new Activity { DepartmentId = 2 }, NewActivityDepartmentId = 3, ActivityStateBeforeTransfer = ActivityState.ManualReview, RequestedActivityId = 4 }; var activityFromRepo = new Activity { State = ActivityState.PendingTransfer }; _mockActivityTransferActionRepository.Setup(mock => mock.GetTransferActionById(1)) .ReturnsAsync(transferActionFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(4)) .ReturnsAsync(activityFromRepo); _mockAuthorizationService .Setup(mock => mock.AppUserCanMakeStateChange(approver, It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(true); var result = await _mockedActivityService.ApproveTransfer(approver, approval); Assert.NotNull(result); Assert.AreEqual(ActivityTransferState.Rejected, result.State); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 4 && x.Note.Equals("Activity transfer has been rejected.") && x.State == ActivityState.ManualReview) ), Times.Once); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Once); } [Test] public async Task ApproveTransfer_Approve_ReturnsUpdatedTransferAction() { var approver = new AppUser { AdEmail = "manager@landmarkcu.com", EmployeeId = "M0000", FullName = "Manager, Approving" }; var approval = new ActivityTransferApprovalRequest { Id = 1, ApprovalState = ActivityTransferState.Accepted }; var transferActionFromRepo = new ActivityTransferAction { Id = 6, State = ActivityTransferState.Requested, RequestedActivity = new Activity { DepartmentId = 2 }, NewActivityDepartmentId = 3, NewActivityEmployeeId = "N0000", ActivityStateBeforeTransfer = ActivityState.ManualReview, RequestedActivityId = 4 }; var activityFromRepo = new Activity { State = ActivityState.PendingTransfer }; _mockActivityTransferActionRepository.Setup(mock => mock.GetTransferActionById(1)) .ReturnsAsync(transferActionFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(4)) .ReturnsAsync(activityFromRepo); var mockActivityToTransfer = new Activity { Accepted = new DateTime(2021, 9, 22), DepartmentId = 2, Detail = new ActivityDetail { AccountBalance = 100.00, AccountNewBalance = 99.00, AccountNumber = "888888", AccountStatus = "Open", AgreementNumber = "999", BranchOrgName = "Org Name", BranchOrgNbr = "Org Number", DnaPersonNbr = "DNA number", MemberName = "Member Name", StationName = "Station Name", SubjectOrgNbr = "Subject Org Number", SubjectPersonNbr = "Subject Person Number" }, EmployeeEmail = "employee@landmarkcu.com", EmployeeId = "E0000", Id = 4, MatchingActivityId = 0, Product = Product.CheckCard, SourceCreated = new DateTime(2021, 9, 22), SourceId = "Source ID", SourceSystem = SystemType.Dna, State = ActivityState.PendingTransfer, Type = ActivityType.Sale }; var mockActivityAfterTransfer = new Activity { Accepted = new DateTime(2021, 9, 22), DepartmentId = 3, Detail = new ActivityDetail { AccountBalance = 100.00, AccountNewBalance = 99.00, AccountNumber = "888888", AccountStatus = "Open", AgreementNumber = "999", BranchOrgName = "Org Name", BranchOrgNbr = "Org Number", DnaPersonNbr = "DNA number", MemberName = "Member Name", StationName = "Station Name", SubjectOrgNbr = "Subject Org Number", SubjectPersonNbr = "Subject Person Number" }, EmployeeEmail = "employee@landmarkcu.com", EmployeeId = "E0000", Id = 50, MatchingActivityId = 0, Product = Product.CheckCard, SourceCreated = new DateTime(2021, 9, 22), SourceId = "Source ID", SourceSystem = SystemType.Dna, State = ActivityState.PendingTransfer, Type = ActivityType.Sale }; var newUser = new AppUser { AdEmail = "newEmployee@landmarkcu.com" }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(4)) .ReturnsAsync(mockActivityToTransfer); _mockUserService.Setup(mock => mock.GetUserByEmployeeIdAsync("N0000")) .ReturnsAsync(newUser); _mockActivityRepository.Setup(mock => mock.GetActivityById(4)) .ReturnsAsync(mockActivityToTransfer); _mockActivityRepository.Setup(mock => mock.GetActivityById(50)) .ReturnsAsync(mockActivityAfterTransfer); // simulate repo assigning a ID to newly save activity _mockUnitOfWork.Setup(mock => mock.CompleteAsync()) .Callback(() => transferActionFromRepo.NewActivity.Id = 50); _mockAuthorizationService .Setup(mock => mock.AppUserCanMakeStateChange(approver, It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(true); var result = await _mockedActivityService.ApproveTransfer(approver, approval); // Assert transfer action is updated Assert.AreEqual(6, result.Id); Assert.AreEqual("Manager, Approving", result.NewDepartmentApprover); Assert.AreEqual(DateTime.Today.Date, result.NewDepartmentApproved.Value.Date); Assert.AreEqual("Manager, Approving", result.RequestedDepartmentApprover); Assert.AreEqual(DateTime.Today.Date, result.RequestedDepartmentApproved.Value.Date); Assert.AreEqual(ActivityTransferState.Accepted, result.State); // Assert new department, employee, and state before transfer are all updated on the new activity Assert.AreEqual(50, result.NewActivity.Id); Assert.AreEqual(3, result.NewActivity.DepartmentId); Assert.AreEqual("newEmployee@landmarkcu.com", result.NewActivity.EmployeeEmail); Assert.AreEqual("N0000", result.NewActivity.EmployeeId); Assert.AreEqual(ActivityState.ManualReview, result.NewActivity.State); } [Test] public async Task ApproveTransfer_Approve_AddsActivityStateChanges() { var approver = new AppUser { AdEmail = "manager@landmarkcu.com", EmployeeId = "M0000", FullName = "Manager, Approving" }; var approval = new ActivityTransferApprovalRequest { Id = 1, ApprovalState = ActivityTransferState.Accepted }; var transferActionFromRepo = new ActivityTransferAction { Id = 6, State = ActivityTransferState.Requested, RequestedActivity = new Activity { DepartmentId = 2 }, NewActivityDepartmentId = 3, NewActivityEmployeeId = "N0000", ActivityStateBeforeTransfer = ActivityState.ManualReview, RequestedActivityId = 4 }; var activityFromRepo = new Activity { Id = 50, State = ActivityState.PendingTransfer }; _mockActivityTransferActionRepository.Setup(mock => mock.GetTransferActionById(1)) .ReturnsAsync(transferActionFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(4)) .ReturnsAsync(activityFromRepo); _mockAuthorizationService .Setup(mock => mock.AppUserCanMakeStateChange(approver, It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(true); var mockActivityToTransfer = new Activity { Accepted = new DateTime(2021, 9, 22), DepartmentId = 2, Detail = new ActivityDetail(), EmployeeEmail = "employee@landmarkcu.com", EmployeeId = "E0000", Id = 4, MatchingActivityId = 0, State = ActivityState.PendingTransfer, }; var newUser = new AppUser { AdEmail = "newEmployee@landmarkcu.com" }; _mockActivityRepository.Setup(mock => mock.GetActivityIncludingPayouts(4)) .ReturnsAsync(mockActivityToTransfer); _mockUserService.Setup(mock => mock.GetUserByEmployeeIdAsync("N0000")) .ReturnsAsync(newUser); _mockActivityRepository.Setup(mock => mock.GetActivityById(50)) .ReturnsAsync(mockActivityToTransfer); // simulate repo assigning a ID to newly save activity _mockUnitOfWork.Setup(mock => mock.CompleteAsync()) .Callback(() => transferActionFromRepo.NewActivity.Id = 50); var result = await _mockedActivityService.ApproveTransfer(approver, approval); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 50 && x.Note.Equals("Activity has been transferred from Activity ID: 4") && x.State == ActivityState.ManualReview) ), Times.Once); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 4 && x.Note.Equals("Activity has been transferred to Activity ID: 50") && x.State == ActivityState.Transferred) ), Times.Once); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Exactly(3)); } [Test] public void ApproveTransfer_Manager_NotFoundException() { var approval = new ActivityTransferApprovalRequest { Id = 1, ApprovalState = ActivityTransferState.Accepted }; _mockActivityTransferActionRepository.Setup(mock => mock.GetTransferActionById(3)) .ReturnsAsync((ActivityTransferAction)null); var exception = Assert.ThrowsAsync(async () => await _mockedActivityService.ApproveTransfer(new AppUser(), approval)); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("No activity transfer action with Id 1 could be found", exception.Message); } [Test] public void ApproveTransfer_Manager_BadActivityTransferActionException() { var approval = new ActivityTransferApprovalRequest { Id = 1, ApprovalState = ActivityTransferState.Accepted }; var transferActionFromRepo = new ActivityTransferAction { State = ActivityTransferState.Accepted }; _mockActivityTransferActionRepository.Setup(mock => mock.GetTransferActionById(1)) .ReturnsAsync(transferActionFromRepo); var exception = Assert.ThrowsAsync(async () => await _mockedActivityService.ApproveTransfer(new AppUser(), approval)); Assert.NotNull(exception); Assert.IsInstanceOf(exception); Assert.AreEqual("Approval has already been decided for this activity", exception.Message); transferActionFromRepo.State = ActivityTransferState.Rejected; var exception2 = Assert.ThrowsAsync(async () => await _mockedActivityService.ApproveTransfer(new AppUser(), approval)); Assert.NotNull(exception2); Assert.IsInstanceOf(exception2); Assert.AreEqual("Approval has already been decided for this activity", exception.Message); } [Test] public void ApproveTransfer_Manager_NotAuthorizedException() { var nonManagerUser = new AppUser { AdEmail = "teller@landmarkcu.com", EmployeeId = "C0000" }; var managerUser = new AppUser { AdEmail = "manager@landmarkcu.com", EmployeeId = "M0000" }; var approval = new ActivityTransferApprovalRequest { Id = 1, ApprovalState = ActivityTransferState.Accepted }; var transferActionFromRepo = new ActivityTransferAction { State = ActivityTransferState.Requested, RequestedActivity = new Activity { DepartmentId = 2 }, NewActivityDepartmentId = 3 }; _mockActivityTransferActionRepository.Setup(mock => mock.GetTransferActionById(1)) .ReturnsAsync(transferActionFromRepo); _mockUserService.Setup(mock => mock.FindDepartmentManagers(It.IsAny())) .ReturnsAsync(new List { managerUser }); var exception = Assert.ThrowsAsync(async () => await _mockedActivityService.ApproveTransfer(nonManagerUser, approval)); Assert.NotNull(exception); Assert.IsInstanceOf(exception); } [Test] public async Task GetRequestedTransfer_ReturnsAction() { var actionFromRepo = new ActivityTransferAction { Id = 1, NewActivityEmployeeId = "C0000", NewActivityDepartmentId = 88 }; _mockActivityTransferActionRepository .Setup(mock => mock.GetRequestedTransferActionByActivityId(It.IsAny())) .ReturnsAsync(actionFromRepo); var result = await _mockedActivityService.GetRequestedTransfer(1); Assert.AreEqual(1, result.Id); Assert.AreEqual("C0000", result.NewActivityEmployeeId); Assert.AreEqual(88, result.NewActivityDepartmentId); } [Test] public async Task RejectPendingTransfers_Ok() { var range = new MonthRange ( DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Year, DateTime.Today.Month ); var activityFromRepo = new Activity { Id = 1, State = ActivityState.PendingTransfer, Accepted = DateTime.Today.Date }; var transferActionFromRepo = new ActivityTransferAction { State = ActivityTransferState.Requested, RequestedActivity = activityFromRepo, NewActivityDepartmentId = 3, ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, }; var transfers = new List(); transfers.Add(transferActionFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(1)) .ReturnsAsync(activityFromRepo); _mockActivityTransferActionRepository .Setup(mock => mock.GetActiveTransfersForStateAsync(ActivityState.Accepted)) .ReturnsAsync(transfers); _mockActivityChangeRepository.Setup(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 1 && x.Note.Equals("Activity transfer has been rejected.") && x.State == ActivityState.Accepted) )).Verifiable(); await _mockedActivityService.CancelPendingTransfersBetween(range); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 1 && x.Note.Equals("Activity transfer has been rejected.") && x.State == ActivityState.Accepted) ), Times.Once); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Once); } [TestCase("07-01-2021", 1)] [TestCase("07-31-2021", 1)] [TestCase("08-01-2021", 1)] [TestCase("08-31-2021", 1)] [TestCase("09-01-2021", 0)] public async Task RejectPendingTransfers_Ok_MonthBorders(string dateString, int timesCalled) { var range = new MonthRange(2021, 7, 2021, 8); var activityFromRepo = new Activity { Id = 1, State = ActivityState.PendingTransfer, Accepted = DateTime.Parse(dateString) }; var transferActionFromRepo = new ActivityTransferAction { State = ActivityTransferState.Requested, RequestedActivity = activityFromRepo, NewActivityDepartmentId = 3, ActivityStateBeforeTransfer = ActivityState.Accepted, RequestedActivityId = 1, }; var transfers = new List(); transfers.Add(transferActionFromRepo); _mockActivityRepository.Setup(mock => mock.GetActivityById(1)) .ReturnsAsync(activityFromRepo); _mockActivityTransferActionRepository .Setup(mock => mock.GetActiveTransfersForStateAsync(ActivityState.Accepted)) .ReturnsAsync(transfers); _mockActivityChangeRepository.Setup(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 1 && x.Note.Equals("Activity transfer has been rejected.") && x.State == ActivityState.Accepted) )).Verifiable(); await _mockedActivityService.CancelPendingTransfersBetween(range); _mockActivityChangeRepository.Verify(mock => mock.SaveActivityStateChange( It.Is(x => x.ActivityId == 1 && x.Note.Equals("Activity transfer has been rejected.") && x.State == ActivityState.Accepted) ), Times.Exactly(timesCalled)); _mockUnitOfWork.Verify(mock => mock.CompleteAsync(), Times.Exactly(timesCalled)); } [Test] public async Task FilterExternalActivitiesByExistingSourceId_OK() { _mockActivityRepository.Setup(x => x.GetActivitiesBySourceId(It.IsAny>())).ReturnsAsync( new List() { new Activity() { SourceId = "1", Type = ActivityType.Sale, Product = Product.Mortgage }, new Activity() { SourceId = "2", Type = ActivityType.Sale, Product = Product.Mortgage }, new Activity() { SourceId = "3", Type = ActivityType.Sale, Product = Product.Mortgage }, new Activity() { SourceId = "4", Type = ActivityType.Sale, Product = Product.Vehicle }, new Activity() { SourceId = "5", Type = ActivityType.Sale, Product = Product.Vehicle }, new Activity() { SourceId = "6", Type = ActivityType.Referral, Product = Product.Vehicle } }); var results = await _mockedActivityService.FilterExternalActivitiesByExistingSourceId( new List() { new NewLoanSaleActivity() { ActivityNbr = 1, MinorAccountType = "FE01", }, new NewLoanSaleActivity() { ActivityNbr = 5, MinorAccountType = "FE01", }, new NewLoanSaleActivity() { ActivityNbr = 5, MinorAccountType = "DV01" }, new NewLoanSaleActivity() { ActivityNbr = 6, MinorAccountType = "DV01" }, new NewLoanSaleActivity() { ActivityNbr = 7, MinorAccountType = "DV01" } }); Assert.NotNull(results); Assert.AreEqual(3, results.Count); Assert.False(results.Any(x => x.GetSourceId() == "1" && x.GetProductType() == Product.Mortgage)); Assert.True(results.Any(x => x.GetSourceId() == "5" && x.GetProductType() == Product.Mortgage)); Assert.False(results.Any(x => x.GetSourceId() == "5" && x.GetProductType() == Product.Vehicle)); Assert.True(results.Any(x => x.GetSourceId() == "6" && x.GetProductType() == Product.Vehicle)); Assert.True(results.Any(x => x.GetSourceId() == "7" && x.GetProductType() == Product.Vehicle)); } [Test] public async Task NoEmployeeFoundWhenSavingNewActivityThrowsNotFoundException() { _mockUserService.Setup(mock => mock.GetActiveUserByEmployeeIdAsync(It.IsAny())).ReturnsAsync((AppUser)null); _mockUserService.Setup(mock => mock.GetUserByEmployeeIdAsync(It.IsAny())).ReturnsAsync((AppUser)null); var activity = new Activity() { Id = 1, SourceId = "1", DepartmentId = 10, EmployeeId = "113322" }; //Assert Assert.ThrowsAsync(async () => await _activityService.SaveActivityAsync(activity)); } } }