using LCU.API.Internal.Operations.IncentiveApi.Services; using LCU.API.Internal.Operations.IncentiveApiLib.Repositories; using LCU.API.Internal.Operations.IncentiveApi.Services.MicroApiServices; using LCU.Library.Internal.IncentiveApiModels.Entities; using LCU.API.Internal.Operations.IncentiveApiLib.Persistence; using LCU.Library.Internal.IncentiveApiModels.Enums; using Moq; using NUnit.Framework; using System.Linq; using System.Threading.Tasks; using System.Collections.Generic; using System; using Microsoft.EntityFrameworkCore; namespace Application.UnitTests.Services { public class EStatementServiceTest { private EStatementService _referralService; private IActivityRepository _activityRepository; private IUnitOfWork _unitOfWork; private Mock _mockProcessorHistoryService; private Mock _mockCoreApiWrapperService; private Mock _mockActivityService; [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); _unitOfWork = new UnitOfWork(context); _mockProcessorHistoryService = new Mock(); _mockCoreApiWrapperService = new Mock(); _mockActivityService = new Mock(); _referralService = new EStatementService(_mockProcessorHistoryService.Object, _mockCoreApiWrapperService.Object, _mockActivityService.Object, _activityRepository); } [TestCase("1111", null)] [TestCase(null, "1111")] [Test] public async Task MatchOrExpireEstatementReferral_MatchOnPersonOrOrgNumber_MatchNoExpire(string supjectPersonNbr, string subjectOrgNbr) { // Delivery methods activity dates must precede referral source created date var deliveryMethodDaysInPast = -2; var referralDaysInPast = -5; var matchedEStatementReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = supjectPersonNbr, SubjectOrgNbr = subjectOrgNbr }, MetaData = new List { } }; matchedEStatementReferral.Id = await _activityRepository.SaveActivityAsync(matchedEStatementReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); var matchedDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 1, AccountNumber = 11111, PersonNumber = supjectPersonNbr, OrganizationNumber = subjectOrgNbr ?? "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = "0987654321", EmailAddresses = "mail@mail.com" }; var methodWithNonMatchingNumbers = new EStatementDeliveryMethod() { ActivityNumber = 2, AccountNumber = 22222, PersonNumber = "1234", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = null, EmailAddresses = null }; var methodWithMetadata = new EStatementDeliveryMethod() { ActivityNumber = 3, AccountNumber = 33333, PersonNumber = "5678", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = "2629999999,2622344555,2626788888,2624324444", EmailAddresses = "Testy1@Test.com,testy@test.com" }; var eStatmentActivities = new List() { matchedDeliveryMethod, methodWithNonMatchingNumbers, methodWithMetadata }; _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Once); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains(matchedDeliveryMethod.AccountNumber.ToString())); Assert.AreEqual(matchedDeliveryMethod.AccountNumber.ToString(), matchedEStatementReferral.Detail.AccountNumber); Assert.AreEqual(matchedEStatementReferral.Id, results.First().ActivityId); Assert.AreEqual(ActivityState.Accepted, results.First().State); } [Test] public async Task MatchOrExpireEstatementReferral_MatchOnPhoneMetaData_MatchNoExpire() { // Delivery methods activity dates must precede referral source created date var deliveryMethodDaysInPast = -2; var referralDaysInPast = -5; var matchedEStatementReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = null, SubjectOrgNbr = null }, MetaData = new List { new ActivityMetaData { MetaData = "1234567890", MetaDataType = MetaDataType.Phone } } }; matchedEStatementReferral.Id = await _activityRepository.SaveActivityAsync(matchedEStatementReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); var matchedDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 1, AccountNumber = 11111, PersonNumber = "1234", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = "1234567890,0987654321", // Additional phone number should be added to referral activity EmailAddresses = "mail@mail.com" // This email address should be added to the referral activity }; var methodWithNonMatchingMetadata = new EStatementDeliveryMethod() { ActivityNumber = 2, AccountNumber = 22222, PersonNumber = "5678", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = "0987654321", EmailAddresses = "mail@mail.com, mail2@mail.com" }; var methodWithoutMetadata = new EStatementDeliveryMethod() { ActivityNumber = 3, AccountNumber = 33333, PersonNumber = "9134", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = null, EmailAddresses = null }; var eStatmentActivities = new List() { matchedDeliveryMethod, methodWithNonMatchingMetadata, methodWithoutMetadata }; _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Once); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains(matchedDeliveryMethod.AccountNumber.ToString())); Assert.AreEqual(matchedEStatementReferral.Id, results.First().ActivityId); Assert.AreEqual(ActivityState.Accepted, results.First().State); Assert.AreEqual(2, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Phone).Count()); // Added one new phone number Assert.AreEqual(1, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Email).Count()); // Added one new email address } [Test] public async Task MatchOrExpireReferralsWithoutSales_MatchOnEmailMetaData_MatchNoExpire() { // Delivery methods activity dates must precede referral source created date var deliveryMethodDaysInPast = -2; var referralDaysInPast = -5; var matchedEStatementReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = null, SubjectOrgNbr = null }, MetaData = new List { new ActivityMetaData { MetaData = "mail@mail.com", MetaDataType = MetaDataType.Email } } }; matchedEStatementReferral.Id = await _activityRepository.SaveActivityAsync(matchedEStatementReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); var matchedDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 1, AccountNumber = 11111, PersonNumber = "1234", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = "1234567890", // This phone number should be added to referral activity EmailAddresses = "mail@mail.com, mail2@mail.com" // Additional email address should be added to the referral activity }; var methodWithNonMatchingMetadata = new EStatementDeliveryMethod() { ActivityNumber = 2, AccountNumber = 22222, PersonNumber = "5678", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = "0987654321", EmailAddresses = "mail3@mail.com, mail4@mail.com" }; var methodWithoutMetadata = new EStatementDeliveryMethod() { ActivityNumber = 3, AccountNumber = 33333, PersonNumber = "9123", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = null, EmailAddresses = null }; var eStatmentActivities = new List() { matchedDeliveryMethod, methodWithNonMatchingMetadata, methodWithoutMetadata }; _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Once); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains(matchedDeliveryMethod.AccountNumber.ToString())); Assert.AreEqual(matchedEStatementReferral.Id, results.First().ActivityId); Assert.AreEqual(ActivityState.Accepted, results.First().State); Assert.AreEqual(1, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Phone).Count()); // Added one new phone number Assert.AreEqual(2, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Email).Count()); // Added one new email address } [Test] public async Task MatchOrExpireEstatementReferral_MultipleDeliveryMethodsMatch_OneMatchNoExpire() { // Delivery methods activity dates must precede referral source created date var deliveryMethodDaysInPast = -2; var latestDeliveryMethodDaysInPast = -1; var referralDaysInPast = -5; var referralMatchingPhoneNumber = "1234567890"; var matchedEStatementReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = null, SubjectOrgNbr = null }, MetaData = new List { new ActivityMetaData { MetaData = referralMatchingPhoneNumber, MetaDataType = MetaDataType.Phone } } }; matchedEStatementReferral.Id = await _activityRepository.SaveActivityAsync(matchedEStatementReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); var matchedDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 1, AccountNumber = 11111, PersonNumber = "1234", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(latestDeliveryMethodDaysInPast), PhoneNumbers = referralMatchingPhoneNumber, EmailAddresses = "mail@mail.com" // This email address should be added to the referral activity }; var methodWithNonMatchingMetadata = new EStatementDeliveryMethod() { ActivityNumber = 2, AccountNumber = 22222, PersonNumber = "5678", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = referralMatchingPhoneNumber, EmailAddresses = "mail@mail.com, mail2@mail.com" }; var methodWithoutMetadata = new EStatementDeliveryMethod() { ActivityNumber = 3, AccountNumber = 33333, PersonNumber = "9123", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = referralMatchingPhoneNumber, EmailAddresses = null }; var eStatmentActivities = new List() { matchedDeliveryMethod, methodWithNonMatchingMetadata, methodWithoutMetadata }; _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Once); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains(matchedDeliveryMethod.AccountNumber.ToString())); Assert.AreEqual(matchedEStatementReferral.Id, results.First().ActivityId); Assert.AreEqual(ActivityState.Accepted, results.First().State); Assert.AreEqual(1, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Phone).Count()); // Did not add any phone numbers Assert.AreEqual(1, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Email).Count()); // Added one new email address } [Test] public async Task MatchOrExpireEstatementReferral_MatchMultipleOnPersNumberAndMetaData_OneMatchNoExpire() { // Delivery methods activity dates must precede referral source created date var deliveryMethodDaysInPast = -2; var firstMatchedDeliveryMethodDaysInPast = -2; var latestDeliveryMethodDaysInPast = -1; // Method with this date will match because it is newest var referralDaysInPast = -5; var referralMatchingPersNumber = "1111"; var referralMatchingPhoneNumber = "1234567890"; var referralMatchingEmail = "mail@mail.com"; var matchedEStatementReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = referralMatchingPersNumber, SubjectOrgNbr = null }, MetaData = new List { new ActivityMetaData { MetaData = referralMatchingEmail, MetaDataType = MetaDataType.Email } } }; matchedEStatementReferral.Id = await _activityRepository.SaveActivityAsync(matchedEStatementReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); // Will match on email MetaData var matchedOnEmailDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 1, AccountNumber = 11111, PersonNumber = "1234", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(latestDeliveryMethodDaysInPast), PhoneNumbers = referralMatchingPhoneNumber, EmailAddresses = referralMatchingEmail }; // Will match on PersonNumber var matchedOnPersonNumberButNotLatest = new EStatementDeliveryMethod() { ActivityNumber = 2, AccountNumber = 22222, PersonNumber = referralMatchingPersNumber, OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(firstMatchedDeliveryMethodDaysInPast), PhoneNumbers = referralMatchingPhoneNumber, EmailAddresses = referralMatchingEmail }; var nonMatchingMethod = new EStatementDeliveryMethod() { ActivityNumber = 3, AccountNumber = 33333, PersonNumber = "5678", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = null, EmailAddresses = null }; var eStatmentActivities = new List() { matchedOnEmailDeliveryMethod, matchedOnPersonNumberButNotLatest, nonMatchingMethod }; _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Once); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains(matchedOnEmailDeliveryMethod.AccountNumber.ToString())); Assert.AreEqual(matchedEStatementReferral.Id, results.First().ActivityId); Assert.AreEqual(ActivityState.Accepted, results.First().State); Assert.AreEqual(1, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Phone).Count()); // Did not add any phone numbers Assert.AreEqual(1, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Email).Count()); // Added one new email address } [Test] public async Task MatchOrExpireEstatementReferral_MultipleReferralMatches_MatchOneReferralNoExpire() { // Delivery methods activity dates must precede referral source created date var deliveryMethodDaysInPast = -2; var referralDaysInPast = -5; var latestReferral = -4; var duplicateReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "1", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(latestReferral), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = "1234", SubjectOrgNbr = null } }; duplicateReferral.Id = await _activityRepository.SaveActivityAsync(duplicateReferral); await _unitOfWork.CompleteAsync(); var matchingReferral = new Activity() { Product = Product.eStatement, EmployeeId = "2", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = "1234", SubjectOrgNbr = null } }; // Saving this referral second makes it the "latest" (last updated) and match matchingReferral.Id = await _activityRepository.SaveActivityAsync(matchingReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); var matchedDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 1, AccountNumber = 11111, PersonNumber = "1234", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = null, EmailAddresses = null }; var nonMatchedDeliveryMethod = new EStatementDeliveryMethod() { ActivityNumber = 2, AccountNumber = 22222, PersonNumber = "4321", OrganizationNumber = "0", ActivityDateTime = DateTime.Now.AddDays(deliveryMethodDaysInPast), PhoneNumbers = null, EmailAddresses = null }; var eStatmentActivities = new List() { matchedDeliveryMethod }; _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Once); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains(matchedDeliveryMethod.AccountNumber.ToString())); Assert.AreEqual(matchingReferral.Id, results.First().ActivityId); Assert.AreEqual(ActivityState.Accepted, results.First().State); } [Test] public async Task MatchOrExpireEstatementReferral_NoMatch_Expire() { var referralDaysInPast = -61; // Expires after 60 days var matchedEStatementReferral = new Activity() { Product = Product.eStatement, EmployeeId = "1", SourceId = "2", Type = ActivityType.Referral, State = ActivityState.PendingReferral, SourceCreated = DateTime.Now.AddDays(referralDaysInPast), Detail = new ActivityDetail { AccountNumber = null, SubjectPersonNbr = null, SubjectOrgNbr = null } }; matchedEStatementReferral.Id = await _activityRepository.SaveActivityAsync(matchedEStatementReferral); await _unitOfWork.CompleteAsync(); var lastRun = new ProcessorHistoryRecord() { }; _mockProcessorHistoryService.Setup(mock => mock.GetProcessorHistory(It.IsAny())).ReturnsAsync(lastRun); var eStatmentActivities = new List() { }; // Matching fails because there are no estatements to match with _mockCoreApiWrapperService.Setup(mock => mock.GetEStatmentDeliveryMethods(It.IsAny())).ReturnsAsync(eStatmentActivities); var results = await _referralService.UpdateOrExpireEStatementReferral(); _mockProcessorHistoryService.Verify(mock => mock.SaveProcessorHistory(It.IsAny()), Times.Never); Assert.IsNotNull(results); Assert.IsTrue(results.Count == 1); Assert.IsTrue(results.First().Note.Contains("expired")); Assert.AreEqual(0, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Phone).Count()); Assert.AreEqual(0, matchedEStatementReferral.MetaData.Where(x => x.MetaDataType == MetaDataType.Email).Count()); } } }