using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; 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 Moq; using NUnit.Framework; using LCU.API.Internal.Operations.IncentiveApi.Services.DispersalStrategy; using LCU.API.Internal.Operations.IncentiveApi.Models; using LCU.API.Internal.Operations.IncentiveApiLib.Services; using LCU.Library.Internal.IncentiveApiModels.Requests; using LCU.API.Internal.Operations.IncentiveApi.Models.GoalDispersal; using LCU.API.Internal.Operations.IncentiveApi.Extensions; using LCU.API.Internal.Operations.IncentiveApi.Services.MicroApiServices; namespace Application.UnitTests.Services { public class GoalDispersalServiceTest { private Mock _mockGoalService; private Mock _mockDepartmentRepository; private Mock _mockNotificationService; private Mock _mockUserService; private Mock _mockGoalChangeRepository; private Mock _mockDispersalStrategyService; private IGoalDispersalService _goalDispersalService; [SetUp] public void SetUp() { _mockGoalService = new Mock(); _mockGoalChangeRepository = new Mock(); _mockDepartmentRepository = new Mock(); _mockUserService = new Mock(); _mockDispersalStrategyService = new Mock(); _mockNotificationService = new Mock(); _goalDispersalService = new GoalDispersalService(_mockUserService.Object, _mockGoalService.Object, _mockDepartmentRepository.Object, _mockNotificationService.Object, _mockDispersalStrategyService.Object); } [Test] public async Task DisperseGoalsByExtrapolatingLastMonth_OK() { var goalList = new List() { new Goal() { DepartmentId = 10, Product = Product.Mortgage, Value = 200, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() }, new Goal() { DepartmentId = 10, Product = Product.Vehicle, Value = 0, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() }, new Goal() { DepartmentId = 10, Product = Product.CheckCard, Value = 0, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() }, new Goal() { DepartmentId = 10, Product = Product.DirectDeposit, Value = 35, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() } }; var departmentGoal = new DepartmentGoals(10, 2021); departmentGoal.ApplyAll(goalList); var personnelGoals = new PersonnelGoals(10, 2021, 1, new List() { new AppUser() { PersonId = 5, EmployeeId = "5E", AdditionalPermissions = new List(), Departments = new List() { new UserDepartment() { DepartmentId = 10 } }, Role = Role.BM } }); personnelGoals.ApplyAll(goalList.Select(x => { x.EmployeeId = "5E"; return x; }).ToList()); _mockGoalService.Setup(x => x.GetAnnualDepartmentGoalsAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(departmentGoal); _mockGoalService.Setup(x => x.GetMonthlyPersonnelGoalsAsync(It.IsAny())) .ReturnsAsync(personnelGoals); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals(It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.ExtrapolateFromExistingGoals)); _mockDispersalStrategyService .Setup(x => x.DefaultWeightedDispersal(It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.DefaultDisperseWithWeights)); var results = await _goalDispersalService.DisperseGoalsByExtrapolatingLastMonth(10, 1, 2020); Assert.AreEqual(GoalDispersalStrategy.ExtrapolateFromExistingGoals, results.Strategy); _mockDispersalStrategyService.Verify(x => x.ExtrapolateFromExistingGoals(It.IsAny()), Times.Once); _mockGoalService.Verify(x => x.SaveGoalRangeAsync(It.IsAny>()), Times.Once); } [TestCase(1, 2021, 12, 2020)] [TestCase(2, 2021, 1, 2021)] [TestCase(3, 2021, 2, 2021)] [TestCase(4, 2021, 3, 2021)] [TestCase(5, 2021, 4, 2021)] [TestCase(6, 2021, 5, 2021)] [TestCase(7, 2021, 6, 2021)] [TestCase(8, 2021, 7, 2021)] [TestCase(9, 2021, 8, 2021)] [TestCase(10, 2021, 9, 2021)] [TestCase(11, 2021, 10, 2021)] [TestCase(12, 2021, 11, 2021)] public async Task DisperseGoalsByExtrapolatingLastMonth_Calculates_Year_Month_OK(int month, int year, int lastMonth, int lastMonthYear) { var goalList = new List() { new Goal() { DepartmentId = 10, Product = Product.Mortgage, Value = 200, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() } }; var departmentGoal = new DepartmentGoals(10, 2021); departmentGoal.ApplyAll(goalList); var personnelGoals = new PersonnelGoals(10, 2021, 1, new List() { new AppUser() { PersonId = 5, EmployeeId = "5E", AdditionalPermissions = new List(), Departments = new List() { new UserDepartment() { DepartmentId = 10 } }, Role = Role.BM } }); personnelGoals.ApplyAll(goalList.Select(x => { x.EmployeeId = "5E"; return x; }).ToList()); // The goals and personnel don't really matter for testing we just need some values _mockGoalService.Setup(x => x.GetAnnualDepartmentGoalsAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(departmentGoal); _mockGoalService.Setup(x => x.GetMonthlyPersonnelGoalsAsync(It.IsAny())) .ReturnsAsync(personnelGoals); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals(It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.ExtrapolateFromExistingGoals)); _mockDispersalStrategyService .Setup(x => x.DefaultWeightedDispersal(It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.DefaultDisperseWithWeights)); var results = await _goalDispersalService.DisperseGoalsByExtrapolatingLastMonth(10, month, year); Assert.NotNull(results); _mockGoalService.Verify( x => x.GetMonthlyPersonnelGoalsAsync( It.Is(x => x.Month == month && x.Year == year)), Times.Once()); _mockGoalService.Verify( x => x.GetMonthlyPersonnelGoalsAsync( It.Is(x => x.Month == lastMonth && x.Year == lastMonthYear)), Times.Once()); _mockGoalService.Verify( X => X.GetAnnualDepartmentGoalsAsync(It.Is(x => x == 10), It.Is(x => x == year)), Times.AtLeastOnce); _mockGoalService.Verify( X => X.GetAnnualDepartmentGoalsAsync(It.Is(x => x == 10), It.Is(x => x == lastMonthYear)), Times.AtLeastOnce); _mockGoalService.Verify(x => x.SaveGoalRangeAsync(It.IsAny>()), Times.Once); } [Test] public async Task DisperseGoalsByExtrapolatingLastMonth_Defaults_OK() { var goalList = new List() { new Goal() { DepartmentId = 10, Product = Product.Mortgage, Value = 0, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() }, new Goal() { DepartmentId = 10, Product = Product.Vehicle, Value = 0, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() }, new Goal() { DepartmentId = 10, Product = Product.CheckCard, Value = 0, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() }, new Goal() { DepartmentId = 10, Product = Product.DirectDeposit, Value = 0, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() } }; var departmentGoal = new DepartmentGoals(10, 2021); departmentGoal.ApplyAll(goalList); var personnelGoals = new PersonnelGoals(10, 2021, 1, new List() { new AppUser() { PersonId = 5, EmployeeId = "5E", AdditionalPermissions = new List(), Departments = new List() { new UserDepartment() { DepartmentId = 10 } }, Role = Role.BM } }); personnelGoals.ApplyAll(goalList.Select(x => { x.EmployeeId = "5E"; return x; }).ToList()); // The goals and personnel don't really matter for testing we just need some values _mockGoalService.Setup(x => x.GetAnnualDepartmentGoalsAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(departmentGoal); _mockGoalService.Setup(x => x.GetMonthlyPersonnelGoalsAsync(It.IsAny())) .ReturnsAsync(personnelGoals); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals(It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.ExtrapolateFromExistingGoals)); _mockDispersalStrategyService .Setup(x => x.DefaultWeightedDispersal(It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.DefaultDisperseWithWeights)); var results = await _goalDispersalService.DisperseGoalsByExtrapolatingLastMonth(10, 1, 2020); Assert.AreEqual(GoalDispersalStrategy.DefaultDisperseWithWeights, results.Strategy); _mockDispersalStrategyService.Verify(x => x.DefaultWeightedDispersal(It.IsAny()), Times.Once); _mockGoalService.Verify(x => x.SaveGoalRangeAsync(It.IsAny>()), Times.Once); } [Test] public async Task DisperseAllDepartmentGoalsForMonth_OK() { var goalList = new List() { new Goal() { DepartmentId = 10, Product = Product.Mortgage, Value = 200, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() } }; var departmentGoal = new DepartmentGoals(10, 2021); departmentGoal.ApplyAll(goalList); var personnelGoals = new PersonnelGoals(10, 2021, 1, new List() { new AppUser() { PersonId = 5, EmployeeId = "5E", AdditionalPermissions = new List(), Departments = new List() { new UserDepartment() { DepartmentId = 10 } }, Role = Role.BM } }); personnelGoals.ApplyAll(goalList.Select(x => { x.EmployeeId = "5E"; return x; }).ToList()); // The goals and personnel don't really matter for testing we just need some values _mockGoalService.Setup(x => x.GetAnnualDepartmentGoalsAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(departmentGoal); _mockGoalService.Setup(x => x.GetMonthlyPersonnelGoalsAsync(It.IsAny())) .ReturnsAsync(personnelGoals); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals(It.Is(x => x.DepartmentId == 0))) .Returns(new GoalDispersalReceipt(0, GoalDispersalStrategy.ExtrapolateFromExistingGoals)); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals(It.Is(x => x.DepartmentId == 1))) .Returns(new GoalDispersalReceipt(1, GoalDispersalStrategy.DefaultDisperseWithWeights)); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals(It.Is(x => x.DepartmentId == 2))) .Returns(new GoalDispersalReceipt(2, GoalDispersalStrategy.ExtrapolateFromExistingGoals)); _mockDispersalStrategyService .Setup(x => x.ExtrapolateFromExistingGoals( It.Is(x => x.DepartmentId == 3))) .Throws(new Exception("Ooops")); _mockDepartmentRepository.Setup(x => x.GetAllDepartmentsAsync()).ReturnsAsync(new List() { new Department() { Id = 0, DepartmentName = "Name0" }, new Department() { Id = 1, DepartmentName = "Name1" }, new Department() { Id = 2, }, new Department() { Id = 3, DepartmentName = "Name3" }, }); var results = await _goalDispersalService.DisperseAllDepartmentGoalsForMonth(1, 2020); Assert.Contains("0 - Name0",results.Keys); Assert.Contains("1 - Name1", results.Keys); Assert.Contains("2 - ", results.Keys); Assert.Contains("3 - Name3", results.Keys); Assert.NotNull(results["0 - Name0"]); Assert.NotNull(results["1 - Name1"]); Assert.NotNull(results["2 - "]); Assert.Null(results["3 - Name3"]); Assert.AreEqual(GoalDispersalStrategy.ExtrapolateFromExistingGoals, results["0 - Name0"].Strategy); Assert.AreEqual(GoalDispersalStrategy.DefaultDisperseWithWeights,results["1 - Name1"].Strategy); Assert.AreEqual(GoalDispersalStrategy.ExtrapolateFromExistingGoals,results["2 - "].Strategy); } [Test] public async Task CustomWeightedDispersal_OK() { var customWeightedDispersalRequest = new CustomWeightedDispersalRequest() { DepartmentId = 10, month = 01, year = 2021, DispersalProduct = Product.Mortgage, DispersalWeightByRole = new Dictionary(){ { "BM", .10 }, {"PFO", .25} } }; var users = new List() { new AppUser() { EmployeeId = "ABM1", PersonId = 1, Departments = new List() { new UserDepartment() { DepartmentId = 10, Role = Role.ABM } } }, new AppUser() { EmployeeId = "BM1", PersonId = 2, Departments = new List() { new UserDepartment() { DepartmentId = 10, Role = Role.BM } } }, new AppUser() { EmployeeId = "BM2", PersonId = 3, Departments = new List() { new UserDepartment() { DepartmentId = 10, Role = Role.BM } } }, new AppUser() { EmployeeId = "PFO1", PersonId = 4, Departments = new List() { new UserDepartment() { DepartmentId = 10, Role = Role.PFO } } }, new AppUser() { EmployeeId = "PFO2", PersonId = 5, Departments = new List() { new UserDepartment() { DepartmentId = 10, Role = Role.PFO } } }, new AppUser() { EmployeeId = "PFO3", PersonId = 6, Departments = new List() { new UserDepartment() { DepartmentId = 10, Role = Role.PFO } } } }; var deptGoals = new DepartmentGoals(10, 2021); deptGoals.ApplyAll(new List() { new Goal(){ DepartmentId = 10, Product = Product.Mortgage, Value = 200, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-1").EndOfMonth() } }); _mockGoalService.Setup(x => x.GetAnnualDepartmentGoalsAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(deptGoals); _mockUserService.Setup(x => x.FindDepartmentAssignments(It.IsAny())) .ReturnsAsync(users); _mockDispersalStrategyService .Setup(x => x.CustomWeightedDispersal(It.IsAny(), It.IsAny>(), It.IsAny())) .Returns(new GoalDispersalReceipt(10, GoalDispersalStrategy.CustomWeightedDispersal)); var receipt = await _goalDispersalService.CustomWeightedDispersal(customWeightedDispersalRequest); Assert.AreEqual(10, receipt.DepartmentId); Assert.AreEqual(GoalDispersalStrategy.CustomWeightedDispersal, receipt.Strategy); _mockDispersalStrategyService .Verify(x => x.CustomWeightedDispersal( It.Is(x => x.Equals(customWeightedDispersalRequest)), It.Is>(x => x.Count == 6), It.Is(x => x == 200))); _mockGoalService.Verify(x => x.GetAnnualDepartmentGoalsAsync(It.Is(x => x == 10), It.Is(x => x == 2021))); _mockUserService.Verify(x => x.FindDepartmentAssignments(It.Is(x => x.Month == 1 && x.Year == 2021 && x.IncludeAllPersonnel == true && x.DepartmentId == 10))); _mockGoalService.Verify(x => x.SaveGoalRangeAsync(It.IsAny>()), Times.Once); } [Test] public async Task ExecuteMonthStartDispersal_OK() { var request = new GoalDispersalRequest() { MonthsBack = 0, GoalDispersalNotification = new List { "test1@landmarkcu.com", "test2@landmarkcu.com" } }; _mockDepartmentRepository.Setup(x => x.GetAllDepartmentsAsync()).ReturnsAsync(new List() { new Department() { Id = 0, DepartmentName = "Department0" }, new Department() { Id = 10, Assignments = new List() { new UserDepartment() { Id = 100, AppUserId = new Guid("00000000-1111-1111-0000-000000000000"), DepartmentId = 10 } }, DepartmentName = "Department10" }, new Department() { Id = 2, Assignments = new List() { new UserDepartment() { Id = 22, AppUserId = new Guid("00000000-2222-0000-0000-000000000000"), DepartmentId = 2 } }, DepartmentName = "Department2" }, new Department() { Id = 3, Assignments = new List() { new UserDepartment() { Id = 33, AppUserId = new Guid("00000000-3333-0000-0000-000000000000"), DepartmentId = 3 } }, DepartmentName = "Department3" }, }); var goalUpdate = new GoalChange() { Product = Product.Mortgage, DepartmentId = 10, Value = 300, StartDate = DateTime.Parse("2021-01-01T20:00:00.000").StartOfMonth(), EndDate = DateTime.Parse("2021-01-31T23:59:00.000") }; var goal2Update = new GoalChange() { Product = Product.Mortgage, DepartmentId = 10, Value = 301, StartDate = DateTime.Parse("2021-01-01T10:00:00.000").StartOfMonth(), EndDate = DateTime.Parse("2021-01-31T21:59:00.000") }; var goal3Update = new GoalChange() { Product = Product.Mortgage, DepartmentId = 10, Value = 302, StartDate = DateTime.Parse("2021-01-01T11:30:00.000").StartOfMonth(), EndDate = DateTime.Parse("2021-01-31T03:59:00.000") }; var goalChangeList = new List() { goalUpdate, goal2Update, goal3Update }; var goal1 = new Goal() { Product = Product.Mortgage, DepartmentId = 10, Value = 303, StartDate = DateTime.Parse("2021-01-01T11:30:00.000").StartOfMonth(), EndDate = DateTime.Parse("2021-01-31T03:59:00.000") }; var goalDeptList = new List() { goal1 }; _mockGoalService.Setup(x => x.SaveGoalRangeAsync(goalChangeList)).ReturnsAsync(goalDeptList); var deptGoals = new DepartmentGoals(10, 2021); deptGoals.ApplyAll(new List() { new Goal(){ DepartmentId = 10, Product = Product.Mortgage, Value = 299, StartDate = DateTime.Parse("2021-1-1"), EndDate = DateTime.Parse("2021-1-31").EndOfMonth() }, new Goal(){ DepartmentId = 10, Product = Product.Mortgage, Value = 500, StartDate = DateTime.Parse("2021-2-1"), EndDate = DateTime.Parse("2021-2-28").EndOfMonth() } }); _mockGoalService.Setup(x => x.GetAnnualDepartmentGoalsAsync(It.IsAny(), It.IsAny())).ReturnsAsync(deptGoals); var personnelGoals = new PersonnelGoals(10, 2021, 1, new List() { new AppUser() { PersonId = 5, Id = new Guid("00000000-1111-1111-0000-000000000000"), EmployeeId = "11111", AdditionalPermissions = new List(), Departments = new List() { new UserDepartment() { DepartmentId = 10 } }, Role = Role.BM }, new AppUser() { PersonId = 7, Id = new Guid("00000000-7777-7777-0000-000000000000"), EmployeeId = "77777", AdditionalPermissions = new List(), Departments = new List() { new UserDepartment() { DepartmentId = 10 } }, Role = Role.Teller } }); personnelGoals.ApplyAll(goalDeptList.Select(x => { x.EmployeeId = "11111"; return x; }).ToList()); _mockGoalService.Setup(x => x.GetMonthlyPersonnelGoalsAsync(It.IsAny())).ReturnsAsync(personnelGoals); var receipt = new GoalDispersalReceipt(10, GoalDispersalStrategy.ExtrapolateFromExistingGoals) { GoalChanges = goalChangeList, Strategy = GoalDispersalStrategy.ExtrapolateFromExistingGoals, DepartmentId = 10, GoalDispersalErrors = new List() { new GoalDispersalReceiptItem(GoalDispersalError.NewUserRequiresManualEntry, "77777", "New user required manual entry.") { EmployeeId = "77777", ErrorType = GoalDispersalError.NewUserRequiresManualEntry } }, }; _mockDispersalStrategyService.Setup(x => x.ExtrapolateFromExistingGoals(It.IsAny())).Returns(receipt); var results = await _goalDispersalService.DisperseAllDepartmentGoalsForMonth(2, 2021); await _goalDispersalService.ExecuteMonthStartDispersal(request); _mockNotificationService.Verify(mock => mock.SendMonthStartGoalDispersalReceipt(results, request.GoalDispersalNotification), Times.Once); Assert.NotNull(results["0 - Department0"]); Assert.NotNull(results["10 - Department10"]); Assert.AreEqual(3, results["10 - Department10"].GoalChanges.Count()); Assert.AreEqual(1, results["10 - Department10"].GoalDispersalErrors.Count()); Assert.NotNull(results["2 - Department2"]); Assert.NotNull(results["3 - Department3"]); } } }