diff --git a/src/CommitmentsV2/SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests/EventHandlers/ApprenticeshipWithdrawnEventHandlerTests.cs b/src/CommitmentsV2/SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests/EventHandlers/ApprenticeshipWithdrawnEventHandlerTests.cs index 8406c3b89..ca15b9742 100644 --- a/src/CommitmentsV2/SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests/EventHandlers/ApprenticeshipWithdrawnEventHandlerTests.cs +++ b/src/CommitmentsV2/SFA.DAS.CommitmentsV2.MessageHandlers.UnitTests/EventHandlers/ApprenticeshipWithdrawnEventHandlerTests.cs @@ -29,7 +29,7 @@ public async Task Handle_Should_Send_StopApprenticeshipCommand_When_Apprenticesh // Arrange var message = new ApprenticeshipWithdrawnEvent { ApprovalsApprenticeshipId = 1, Reason = reason, EmployerAccountId = 2, LearningKey = Guid.NewGuid(), LastDayOfLearning = new DateTime(2022, 7, 12)}; var context = new Mock(); - var apprenticeship = new Apprenticeship { Id = 1 }; + var apprenticeship = new Apprenticeship { Id = 1, StartDate= new DateTime(2022, 7, 12) }; var mockDbContext = GetMockDbContext(apprenticeship); var handler = new ApprenticeshipWithdrawnEventHandler(_loggerMock.Object, new Lazy(() => mockDbContext.Object), _mediatorMock.Object); diff --git a/src/CommitmentsV2/SFA.DAS.CommitmentsV2.Messages/Events/ApprenticeshipStopBackEvent.cs b/src/CommitmentsV2/SFA.DAS.CommitmentsV2.Messages/Events/ApprenticeshipStopBackEvent.cs new file mode 100644 index 000000000..f5f00e7a0 --- /dev/null +++ b/src/CommitmentsV2/SFA.DAS.CommitmentsV2.Messages/Events/ApprenticeshipStopBackEvent.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SFA.DAS.CommitmentsV2.Messages.Events +{ + public class ApprenticeshipStopBackEvent + { + public long? ApprenticeshipId { get; set; } + public string Uln { get; set; } + public long ProviderId { get; set; } + public long? LearnerDataId { get; set; } + } +} diff --git a/src/CommitmentsV2/SFA.DAS.CommitmentsV2.UnitTests/Application/Commands/StopApprenticeshipCommandHandlerTests.cs b/src/CommitmentsV2/SFA.DAS.CommitmentsV2.UnitTests/Application/Commands/StopApprenticeshipCommandHandlerTests.cs index 1ae49952e..94e695b06 100644 --- a/src/CommitmentsV2/SFA.DAS.CommitmentsV2.UnitTests/Application/Commands/StopApprenticeshipCommandHandlerTests.cs +++ b/src/CommitmentsV2/SFA.DAS.CommitmentsV2.UnitTests/Application/Commands/StopApprenticeshipCommandHandlerTests.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using AutoFixture; using AutoFixture.NUnit3; using FluentAssertions; @@ -11,23 +6,31 @@ using Microsoft.Extensions.Logging; using Moq; using Newtonsoft.Json; +using Newtonsoft.Json; using NServiceBus; +using NServiceBus.Features; using SFA.DAS.CommitmentsV2.Application.Commands.StopApprenticeship; using SFA.DAS.CommitmentsV2.Configuration; +using SFA.DAS.CommitmentsV2.Configuration; using SFA.DAS.CommitmentsV2.Data; using SFA.DAS.CommitmentsV2.Domain.Exceptions; using SFA.DAS.CommitmentsV2.Domain.Interfaces; +using SFA.DAS.CommitmentsV2.Domain.Interfaces; using SFA.DAS.CommitmentsV2.Messages.Commands; using SFA.DAS.CommitmentsV2.Messages.Events; using SFA.DAS.CommitmentsV2.Models; using SFA.DAS.CommitmentsV2.Shared.Interfaces; using SFA.DAS.CommitmentsV2.Types; using SFA.DAS.Encoding; +using SFA.DAS.NServiceBus.Services; using SFA.DAS.Testing.AutoFixture; using SFA.DAS.UnitOfWork.Context; -using Newtonsoft.Json; -using SFA.DAS.CommitmentsV2.Configuration; -using SFA.DAS.CommitmentsV2.Domain.Interfaces; +using SFA.DAS.UnitOfWork.NServiceBus.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace SFA.DAS.CommitmentsV2.UnitTests.Application.Commands { @@ -41,6 +44,8 @@ public class StopApprenticeshipCommandHandlerTests private Mock _encodingService; private ProviderCommitmentsDbContext _dbContext; private ProviderCommitmentsDbContext _confirmationDbContext; + private Mock _eventPublisher; + private UnitOfWorkContext _unitOfWorkContext { get; set; } private IRequestHandler _handler; private Mock _resolveOverlappingTrainingDateRequestService; @@ -63,6 +68,7 @@ public void Init() _encodingService = new Mock(); _logger = new Mock>(); _unitOfWorkContext = new UnitOfWorkContext(); + _eventPublisher = new Mock(); _resolveOverlappingTrainingDateRequestService = new Mock(); _resolveOverlappingTrainingDateRequestService @@ -75,7 +81,8 @@ public void Init() _encodingService.Object, _logger.Object, new CommitmentsV2Configuration { ProviderCommitmentsBaseUrl = ProviderCommitmentsBaseUrl }, - _resolveOverlappingTrainingDateRequestService.Object); + _resolveOverlappingTrainingDateRequestService.Object, + _eventPublisher.Object); } [TearDown] @@ -380,6 +387,48 @@ public async Task Handle_WhenHandlingCommand_StoppingApprenticeship_ThenResolveO .Verify(x => x.Resolve(It.IsAny(), It.IsAny(), Types.OverlappingTrainingDateRequestResolutionType.ApprenticeshipStopped), Times.Once); } + [Test] + public async Task Handle_WhenHandlingCommand_StoppingApprenticeship_ThenEmitEventIfStartandStopDateAreSame() + { + // Arrange + var apprenticeship = await SetupApprenticeship(); + var stopDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1); + apprenticeship.StartDate = stopDate; + var command = new StopApprenticeshipCommand(apprenticeship.Cohort.EmployerAccountId, apprenticeship.Id, stopDate, false, new UserInfo(), Party.Employer); + + // Act + await _handler.Handle(command, new CancellationToken()); + // Simulate Unit of Work contex transaction ending in http request. + await _dbContext.SaveChangesAsync(); + + // Assert + _eventPublisher.Verify(p => p.Publish(It.Is( + e => e.ApprenticeshipId == null)), + Times.Once); + + } + + [Test] + public async Task Handle_WhenHandlingCommand_StoppingApprenticeship_ThenShouldNotEmitEventIfStartandStopDateAreSame() + { + // Arrange + var apprenticeship = await SetupApprenticeship(); + var stopDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1); + var command = new StopApprenticeshipCommand(apprenticeship.Cohort.EmployerAccountId, apprenticeship.Id, stopDate, false, new UserInfo(), Party.Employer); + + // Act + await _handler.Handle(command, new CancellationToken()); + // Simulate Unit of Work contex transaction ending in http request. + await _dbContext.SaveChangesAsync(); + + // Assert + _eventPublisher.Verify(p => p.Publish(It.Is( + e => e.ApprenticeshipId == null)), + Times.Never); + + } + + private static bool VerifyTokens(IDictionary actualTokens, Dictionary expectedTokens) { actualTokens.Should().BeEquivalentTo(expectedTokens); diff --git a/src/CommitmentsV2/SFA.DAS.CommitmentsV2/Application/Commands/StopApprenticeship/StopApprenticeshipCommandHandler.cs b/src/CommitmentsV2/SFA.DAS.CommitmentsV2/Application/Commands/StopApprenticeship/StopApprenticeshipCommandHandler.cs index 1b5ba5284..793555b15 100644 --- a/src/CommitmentsV2/SFA.DAS.CommitmentsV2/Application/Commands/StopApprenticeship/StopApprenticeshipCommandHandler.cs +++ b/src/CommitmentsV2/SFA.DAS.CommitmentsV2/Application/Commands/StopApprenticeship/StopApprenticeshipCommandHandler.cs @@ -1,14 +1,18 @@ using Microsoft.Extensions.Logging; using NServiceBus; +using SFA.DAS.ApprenticeCommitments.Messages.Events; using SFA.DAS.CommitmentsV2.Configuration; using SFA.DAS.CommitmentsV2.Data; using SFA.DAS.CommitmentsV2.Data.Extensions; using SFA.DAS.CommitmentsV2.Domain.Exceptions; using SFA.DAS.CommitmentsV2.Domain.Interfaces; using SFA.DAS.CommitmentsV2.Messages.Commands; +using SFA.DAS.CommitmentsV2.Messages.Events; using SFA.DAS.CommitmentsV2.Shared.Interfaces; using SFA.DAS.CommitmentsV2.Types; using SFA.DAS.Encoding; +using SFA.DAS.NServiceBus; +using SFA.DAS.NServiceBus.Services; namespace SFA.DAS.CommitmentsV2.Application.Commands.StopApprenticeship; @@ -19,7 +23,8 @@ public class StopApprenticeshipCommandHandler( IEncodingService encodingService, ILogger logger, CommitmentsV2Configuration commitmentsV2Configuration, - IResolveOverlappingTrainingDateRequestService resolveOverlappingTrainingDateRequestService) + IResolveOverlappingTrainingDateRequestService resolveOverlappingTrainingDateRequestService, + IEventPublisher eventPublisher) : IRequestHandler { private const string StopNotificationEmailTemplate = "ProviderApprenticeshipStopNotification"; @@ -49,6 +54,20 @@ await resolveOverlappingTrainingDateRequestService.Resolve( logger.LogInformation("Sending email to Provider {ProviderId}, template {StopNotificationEmailTemplate}", apprenticeship.Cohort.ProviderId, StopNotificationEmailTemplate); + if (apprenticeship.StartDate == request.StopDate) + { + var events = new ApprenticeshipStopBackEvent() + { + ApprenticeshipId = null, + LearnerDataId = apprenticeship.LearnerDataId, + Uln = apprenticeship.Uln, + ProviderId = apprenticeship.Cohort.ProviderId + }; + + logger.LogInformation("Emitting stop back event for {ApprenticeshipId}", apprenticeship.Id); + await eventPublisher.Publish(events); + } + await NotifyProvider( apprenticeship.Cohort.ProviderId, apprenticeship.Id,