private bool ProcessTraineeshipApplication(ApplicationStatusSummary applicationStatusSummary) { var traineeshipApplicationDetail = _traineeshipApplicationReadRepository.Get(applicationStatusSummary.LegacyApplicationId); if (traineeshipApplicationDetail == null && applicationStatusSummary.LegacyCandidateId != 0) { // in some cases the application can't be found using the application IDs so use legacy candidate and vacancy IDs var candidate = _candidateReadRepository.Get(applicationStatusSummary.LegacyCandidateId, false); if (candidate == null) { return(false); } traineeshipApplicationDetail = _traineeshipApplicationReadRepository.GetForCandidate(candidate.EntityId, applicationStatusSummary.LegacyVacancyId); } if (traineeshipApplicationDetail == null) { return(false); } _applicationStatusUpdateStrategy.Update(traineeshipApplicationDetail, applicationStatusSummary); return(true); }
public void ConsumeShouldProcessMessageCorrectly() { _applicationStatusProcessorMock.Setup(x => x.ProcessApplicationStatuses(It.IsAny <ApplicationStatusSummary>())); _bus.Setup(x => x.PublishMessage(It.IsAny <VacancyStatusSummary>())); var appStatusSummary = new ApplicationStatusSummary { ApplicationId = Guid.NewGuid(), LegacyVacancyId = 101, ApplicationStatus = ApplicationStatuses.Submitted, VacancyStatus = VacancyStatuses.Live, ClosingDate = DateTime.Now, LegacyApplicationId = 1001, UnsuccessfulReason = "Because" }; var task = _applicationStatusSummaryConsumerAsync.Consume(appStatusSummary); task.Wait(); _applicationStatusProcessorMock.Verify(x => x.ProcessApplicationStatuses(It.Is <ApplicationStatusSummary>(y => y == appStatusSummary))); _bus.Verify( x => x.PublishMessage( It.Is <VacancyStatusSummary>( v => v.LegacyVacancyId == appStatusSummary.LegacyVacancyId && v.ClosingDate == appStatusSummary.ClosingDate && v.DateTime < DateTime.Now && v.VacancyStatus == appStatusSummary.VacancyStatus))); }
public void ShouldSaveWhenTraineeshipApplicationOrVacancyUpdated(bool updated) { // Arrange. var today = DateTime.Today; var tomorrow = DateTime.Today.AddDays(1); var traineeshipApplicationDetail = new TraineeshipApplicationDetail { EntityId = Guid.NewGuid(), Vacancy = new TraineeshipSummary { ClosingDate = tomorrow } }; var applicationStatusSummary = new ApplicationStatusSummary { ClosingDate = updated ? today : tomorrow }; // Act. _strategy.Update(traineeshipApplicationDetail, applicationStatusSummary); // Assert. var times = updated ? 1 : 0; _mockTraineeshipApplicationWriteRepository.Verify(mock => mock .Save(traineeshipApplicationDetail), Times.Exactly(times)); }
public void ShouldUpdateClosingDate( int oldClosingDateOffset, int newClosingDateOffset, bool expected) { // Arrange. var today = DateTime.Today; var detail = new ApprenticeshipApplicationDetail { Vacancy = new ApprenticeshipSummary { ClosingDate = today.AddDays(oldClosingDateOffset) } }; var summary = new ApplicationStatusSummary { ClosingDate = today.AddDays(newClosingDateOffset) }; // Act. var actual = detail.UpdateApprenticeshipApplicationDetail(summary, _mockReadRepository.Object, _mockWriteRepository.Object); // Assert. actual.Should().Be(expected); detail.Vacancy.ClosingDate.Should().Be(summary.ClosingDate); }
public void ShouldSendAlertWhenApprenticeshipApplicationOrVacancyUpdated(bool updated) { // Arrange. var today = DateTime.Today; var tomorrow = DateTime.Today.AddDays(1); var apprenticeshipApplicationDetail = new ApprenticeshipApplicationDetail { EntityId = Guid.NewGuid(), Status = ApplicationStatuses.Submitted, Vacancy = new ApprenticeshipSummary { ClosingDate = tomorrow } }; var applicationStatusSummary = new ApplicationStatusSummary { ClosingDate = updated ? today : tomorrow }; // Act. _strategy.Update(apprenticeshipApplicationDetail, applicationStatusSummary); // Assert. var times = updated ? 1 : 0; _mockApplicationStatusAlertStrategy.Verify(mock => mock .Send(apprenticeshipApplicationDetail.Status, applicationStatusSummary), Times.Exactly(times)); }
public void ShouldNotPublishMessageWhenReprocessingApplicationStatusSummary() { // Arrange. _applicationStatusProcessorMock.Setup(x => x.ProcessApplicationStatuses(It.IsAny <ApplicationStatusSummary>(), true)); _serviceBus.Setup(x => x.PublishMessage(It.IsAny <VacancyStatusSummary>())); var appStatusSummary = new ApplicationStatusSummary { ApplicationId = Guid.NewGuid(), LegacyVacancyId = 101, ApplicationStatus = ApplicationStatuses.Submitted, VacancyStatus = VacancyStatuses.Live, ClosingDate = DateTime.UtcNow, LegacyApplicationId = 1001, UnsuccessfulReason = "Because" }; // Act. var state = _applicationStatusSummarySubscriber.Consume(appStatusSummary); // Assert. state.Should().NotBeNull(); state.Should().Be(ServiceBusMessageStates.Complete); _applicationStatusProcessorMock.Verify(x => x.ProcessApplicationStatuses(It.Is <ApplicationStatusSummary>(y => y == appStatusSummary), true)); _serviceBus.Verify(mock => mock.PublishMessage(It.IsAny <VacancyStatusSummary>()), Times.Never); }
private void SetDecision(Guid applicationId, ApplicationStatuses applicationStatus, string candidateApplicationFeedback = null) { var apprenticeshipApplication = _apprenticeshipApplicationReadRepository.Get(applicationId); var legacyApplicationId = apprenticeshipApplication.LegacyApplicationId; if (legacyApplicationId == 0) { legacyApplicationId = _referenceNumberRepository.GetNextLegacyApplicationId(); } var applicationStatusSummary = new ApplicationStatusSummary { // CRITICAL: make the update look like it came from legacy AVMS application ApplicationId = Guid.Empty, ApplicationStatus = applicationStatus, LegacyApplicationId = legacyApplicationId, LegacyCandidateId = 0, // not required LegacyVacancyId = 0, // not required VacancyStatus = apprenticeshipApplication.VacancyStatus, ClosingDate = apprenticeshipApplication.Vacancy.ClosingDate, UpdateSource = ApplicationStatusSummary.Source.Raa //Ensure this update is from RAA so ownership of the application is verified }; if (candidateApplicationFeedback != null) { applicationStatusSummary.UnsuccessfulReason = candidateApplicationFeedback; } _applicationStatusUpdateStrategy.Update(apprenticeshipApplication, applicationStatusSummary); _serviceBus.PublishMessage(new ApprenticeshipApplicationUpdate(applicationId, ApplicationUpdateType.Update)); }
private bool ProcessApprenticeshipApplication(ApplicationStatusSummary applicationStatusSummary) { var apprenticeshipApplicationDetail = default(ApprenticeshipApplicationDetail); if (applicationStatusSummary.ApplicationId != Guid.Empty) { apprenticeshipApplicationDetail = _apprenticeshipApplicationReadRepository.Get(applicationStatusSummary.ApplicationId); } if (apprenticeshipApplicationDetail == null && applicationStatusSummary.LegacyApplicationId != 0) { apprenticeshipApplicationDetail = _apprenticeshipApplicationReadRepository.Get(applicationStatusSummary.LegacyApplicationId); } if (apprenticeshipApplicationDetail == null && applicationStatusSummary.LegacyCandidateId != 0) { // in some cases the application can't be found using the application IDs so use legacy candidate and vacancy IDs var candidate = _candidateReadRepository.Get(applicationStatusSummary.LegacyCandidateId); apprenticeshipApplicationDetail = _apprenticeshipApplicationReadRepository.GetForCandidate(candidate.EntityId, applicationStatusSummary.LegacyVacancyId); } if (apprenticeshipApplicationDetail == null) { return(false); // not necessarily an error as may be a traineeship } _applicationStatusUpdateStrategy.Update(apprenticeshipApplicationDetail, applicationStatusSummary); return(true); }
public void ProcessApplicationStatuses(ApplicationStatusSummary applicationStatusSummary, bool strictEtlValidation) { _logger.Debug("Processing application summary status update for application with legacy application ID '{0}'", applicationStatusSummary.LegacyApplicationId); if (!ProcessApprenticeshipApplication(applicationStatusSummary, strictEtlValidation) && !ProcessTraineeshipApplication(applicationStatusSummary)) { var message = string.Format("Unable to find/update apprenticeship or traineeship application status for application with legacy application ID '{0}', application ID '{1}' and legacy candidate ID '{2}'. Check the audit repository to see if the candidate and application was deleted", applicationStatusSummary.LegacyApplicationId, applicationStatusSummary.ApplicationId, applicationStatusSummary.LegacyCandidateId); if (applicationStatusSummary.ApplicationId != Guid.Empty && applicationStatusSummary.LegacyApplicationId == 0) { _logger.Info(message + ". It was likely a draft that was deleted by the candidate."); } else { if (strictEtlValidation) { _logger.Warn(message); } else { _logger.Info(message); } } } }
public static bool UpdateApprenticeshipApplicationDetail( this ApprenticeshipApplicationDetail apprenticeshipApplication, ApplicationStatusSummary applicationStatusSummary, IApprenticeshipApplicationReadRepository apprenticeshipApplicationReadRepository, IApprenticeshipApplicationWriteRepository apprenticeshipApplicationWriteRepository) { var updated = false; if (applicationStatusSummary.IsLegacySystemUpdate()) { // Only update application status etc. if update originated from Legacy system. if (apprenticeshipApplication.Status != applicationStatusSummary.ApplicationStatus) { var ignoreOwnershipCheck = applicationStatusSummary.UpdateSource == ApplicationStatusSummary.Source.Raa; updated = apprenticeshipApplicationWriteRepository.UpdateApplicationStatus(apprenticeshipApplication, applicationStatusSummary.ApplicationStatus, ignoreOwnershipCheck); if (updated) { //Ensure passed in entity is up to date with any changes var updatedApplication = apprenticeshipApplicationReadRepository.Get(apprenticeshipApplication.EntityId); apprenticeshipApplication.Status = updatedApplication.Status; apprenticeshipApplication.IsArchived = updatedApplication.IsArchived; apprenticeshipApplication.DateUpdated = updatedApplication.DateUpdated; apprenticeshipApplication.SuccessfulDateTime = updatedApplication.SuccessfulDateTime; apprenticeshipApplication.UnsuccessfulDateTime = updatedApplication.UnsuccessfulDateTime; } } if (apprenticeshipApplication.LegacyApplicationId != applicationStatusSummary.LegacyApplicationId) { // Ensure the application is linked to the legacy application. apprenticeshipApplication.LegacyApplicationId = applicationStatusSummary.LegacyApplicationId; updated = true; } if (apprenticeshipApplication.UnsuccessfulReason != applicationStatusSummary.UnsuccessfulReason && apprenticeshipApplication.Status == ApplicationStatuses.Unsuccessful) { apprenticeshipApplication.UnsuccessfulReason = applicationStatusSummary.UnsuccessfulReason; updated = true; } } if (apprenticeshipApplication.VacancyStatus != applicationStatusSummary.VacancyStatus) { apprenticeshipApplication.VacancyStatus = applicationStatusSummary.VacancyStatus; updated = true; } if (apprenticeshipApplication.Vacancy.ClosingDate != applicationStatusSummary.ClosingDate) { apprenticeshipApplication.Vacancy.ClosingDate = applicationStatusSummary.ClosingDate; updated = true; } return(updated); }
public ApplicationStatusSummary Build() { var summary = new ApplicationStatusSummary { ApplicationId = _applicationId, LegacyApplicationId = _legacyApplicationId, ApplicationStatus = _applicationStatus, UnsuccessfulReason = _unsuccessfulReason }; return(summary); }
public void ShouldIdentifyNonLegacySystemUpdate() { // Arrange. var summary = new ApplicationStatusSummary { ApplicationId = Guid.NewGuid() }; // Act. var actual = summary.IsLegacySystemUpdate(); // Assert. actual.Should().BeFalse(); }
public void Update( ApprenticeshipApplicationDetail apprenticeshipApplication, ApplicationStatusSummary applicationStatusSummary) { var originalLegacyApplicationId = apprenticeshipApplication.LegacyApplicationId; var originalStatus = apprenticeshipApplication.Status; var originalVacancyStatus = apprenticeshipApplication.VacancyStatus; var originalClosingDate = apprenticeshipApplication.Vacancy.ClosingDate; var originalUnsuccessfulReason = apprenticeshipApplication.UnsuccessfulReason; var originalUnSuccessfulDateTime = apprenticeshipApplication.UnsuccessfulDateTime; // invoked because the status of the apprenticeshipApplication / vacancy *may* have changed if (apprenticeshipApplication.UpdateApprenticeshipApplicationDetail(applicationStatusSummary, _apprenticeshipApplicationReadRepository, _apprenticeshipApplicationWriteRepository)) { const string format = "Updating apprenticeship application (id='{0}', vacancy id='{1}', candidate='{2})" + " from legacy application id='{3}' to '{4}'," + " application status='{5}' to '{6}'," + " vacancy status='{7}' to '{8}'," + " closing date='{9}' to '{10}'," + " unsuccessful reason='{11}' to '{12}'"; _logger.Info( format, apprenticeshipApplication.EntityId, // 0 apprenticeshipApplication.Vacancy.Id, // 1 apprenticeshipApplication.CandidateDetails.EmailAddress, // 2 originalLegacyApplicationId, // 3 applicationStatusSummary.LegacyApplicationId, // 4 originalStatus, // 5 applicationStatusSummary.ApplicationStatus, // 6 originalVacancyStatus, // 7 applicationStatusSummary.VacancyStatus, // 8 originalClosingDate, // 9 applicationStatusSummary.ClosingDate, // 10 originalUnsuccessfulReason, // 11 applicationStatusSummary.UnsuccessfulReason, //12 originalUnSuccessfulDateTime, //13 applicationStatusSummary.UnsuccessfulDateTime); // 14 _apprenticeshipApplicationWriteRepository.Save(apprenticeshipApplication); _applicationStatusAlertStrategy.Send(originalStatus, applicationStatusSummary); } }
public void ProcessApplicationStatuses(ApplicationStatusSummary applicationStatusSummary) { _logger.Debug("Processing application summary status update for application with legacy application ID '{0}'", applicationStatusSummary.LegacyApplicationId); if (!ProcessApprenticeshipApplication(applicationStatusSummary) && !ProcessTraineeshipApplication(applicationStatusSummary)) { var message = string.Format("Unable to find/update apprenticeship or traineeship application status for application with legacy application ID '{0}' and application ID '{1}'", applicationStatusSummary.LegacyApplicationId, applicationStatusSummary.ApplicationId); if (applicationStatusSummary.ApplicationId != Guid.Empty && applicationStatusSummary.LegacyApplicationId == 0) { _logger.Info(message + ". It was likely a draft that was deleted by the candidate."); } else { _logger.Warn(message); } } }
public void ShouldUpdateApplicationStatus( ApplicationStatuses oldStatus, ApplicationStatuses newStatus, ApplicationStatusSummary.Source source, bool expected) { // Arrange. var detail = new ApprenticeshipApplicationDetail { Status = oldStatus, IsArchived = true }; var summary = new ApplicationStatusSummary { ApplicationId = Guid.Empty, ApplicationStatus = newStatus }; var ignoreOwnershipCheck = summary.UpdateSource == ApplicationStatusSummary.Source.Raa; _mockReadRepository.Setup(mock => mock.Get(detail.EntityId)).Returns(new ApprenticeshipApplicationDetail { Status = newStatus }); _mockWriteRepository.Setup(mock => mock .UpdateApplicationStatus(detail, newStatus, ignoreOwnershipCheck)) .Returns(expected); // Act. var actual = detail.UpdateApprenticeshipApplicationDetail(summary, _mockReadRepository.Object, _mockWriteRepository.Object); // Assert. actual.Should().Be(expected); detail.IsArchived.Should().Be(!expected); detail.Status.Should().Be(summary.ApplicationStatus); _mockWriteRepository.Verify(mock => mock .UpdateApplicationStatus(detail, newStatus, ignoreOwnershipCheck), Times.Exactly(expected ? 1 : 0)); }
public void Update(TraineeshipApplicationDetail traineeeshipApplication, ApplicationStatusSummary applicationStatusSummary) { var originalLegacyApplicationId = traineeeshipApplication.LegacyApplicationId; var originalStatus = traineeeshipApplication.Status; var originalVacancyStatus = traineeeshipApplication.VacancyStatus; var originalClosingDate = traineeeshipApplication.Vacancy.ClosingDate; //todo: 1.6: remove this? we won't ever receive these updates while integrating with the legacy system for traineeships // invoked because the status of the apprenticeshipApplication / vacancy *may* have changed if (traineeeshipApplication.UpdateTraineeshipApplicationDetail(applicationStatusSummary)) { // note, this flow will be extended to include a call to outbound communication later (when we do notifications) // note, may subsequently consolidate status updates for a candidate (when we do notifications) but may be done in another component const string format = "Updating traineeship application (id='{0}', vacancy id='{1}', candidate='{2})" + " from legacy application id='{3}' to '{4}'," + " application status='{5}' to '{6}'," + " vacancy status='{7}' to '{8}'," + " closing date='{9}' to '{10}'"; _logger.Info( format, traineeeshipApplication.EntityId, // 0 traineeeshipApplication.Vacancy.Id, // 1 traineeeshipApplication.CandidateDetails.EmailAddress, // 2 originalLegacyApplicationId, // 3 applicationStatusSummary.LegacyApplicationId, // 4 originalStatus, // 5 applicationStatusSummary.ApplicationStatus, // 6 originalVacancyStatus, // 7 applicationStatusSummary.VacancyStatus, // 8 originalClosingDate, // 9 applicationStatusSummary.ClosingDate); // 10 _traineeshipApplicationWriteRepository.Save(traineeeshipApplication); } }
public void ShouldUpdateLegacyApplicationId(int oldId, int newId, bool expected) { // Arrange. var detail = new ApprenticeshipApplicationDetail { LegacyApplicationId = oldId }; var summary = new ApplicationStatusSummary { ApplicationId = Guid.Empty, LegacyApplicationId = newId }; // Act. var actual = detail.UpdateApprenticeshipApplicationDetail(summary, _mockReadRepository.Object, _mockWriteRepository.Object); // Assert. actual.Should().Be(expected); detail.LegacyApplicationId.Should().Be(summary.LegacyApplicationId); }
public void Send(ApplicationStatuses currentStatus, ApplicationStatusSummary applicationStatusSummary) { if (!applicationStatusSummary.IsLegacySystemUpdate()) { return; } if (currentStatus == applicationStatusSummary.ApplicationStatus) { return; } if (!(applicationStatusSummary.ApplicationStatus == ApplicationStatuses.Successful || applicationStatusSummary.ApplicationStatus == ApplicationStatuses.Unsuccessful)) { return; } var applicationStatusChanged = new ApplicationStatusChanged { LegacyApplicationId = applicationStatusSummary.LegacyApplicationId, ApplicationStatus = applicationStatusSummary.ApplicationStatus, UnsuccessfulReason = applicationStatusSummary.UnsuccessfulReason }; var message = $"Queuing application status changed for LegacyApplicationId: {applicationStatusChanged.LegacyApplicationId} with ApplicationStatus: {applicationStatusChanged.ApplicationStatus}, UnsuccessfulReason: {applicationStatusChanged.UnsuccessfulReason}"; try { _logService.Debug(message); _serviceBus.PublishMessage(applicationStatusChanged); } catch (Exception e) { _logService.Warn(message + " failed!", e); } }
public void ShouldUpdateVacancyStatus( VacancyStatuses oldStatus, VacancyStatuses newStatus, bool expected) { // Arrange. var detail = new ApprenticeshipApplicationDetail { VacancyStatus = oldStatus }; var summary = new ApplicationStatusSummary { VacancyStatus = newStatus }; // Act. var actual = detail.UpdateApprenticeshipApplicationDetail(summary, _mockReadRepository.Object, _mockWriteRepository.Object); // Assert. actual.Should().Be(expected); detail.VacancyStatus.Should().Be(summary.VacancyStatus); }
public void ShouldUpdateUnsuccessfulReason(string oldReason, string newReason, bool expected) { // Arrange. var detail = new ApprenticeshipApplicationDetail { Status = ApplicationStatuses.Unsuccessful, UnsuccessfulReason = oldReason }; var summary = new ApplicationStatusSummary { ApplicationId = Guid.Empty, ApplicationStatus = ApplicationStatuses.Unsuccessful, UnsuccessfulReason = newReason }; // Act. var actual = detail.UpdateApprenticeshipApplicationDetail(summary, _mockReadRepository.Object, _mockWriteRepository.Object); // Assert. actual.Should().Be(expected); detail.UnsuccessfulReason.Should().Be(summary.UnsuccessfulReason); }
public static bool IsLegacySystemUpdate(this ApplicationStatusSummary applicationStatusSummary) { return(applicationStatusSummary.ApplicationId == Guid.Empty); }
public static bool UpdateTraineeshipApplicationDetail(this TraineeshipApplicationDetail traineeshipApplication, ApplicationStatusSummary applicationStatusSummary) { var updated = false; if (applicationStatusSummary.IsLegacySystemUpdate()) { // Only update application status etc. if update originated from Legacy system. if (traineeshipApplication.Status != applicationStatusSummary.ApplicationStatus) { traineeshipApplication.Status = applicationStatusSummary.ApplicationStatus; // Application status has changed, ensure it appears on the candidate's dashboard. traineeshipApplication.IsArchived = false; updated = true; } if (traineeshipApplication.LegacyApplicationId != applicationStatusSummary.LegacyApplicationId) { // Ensure the application is linked to the legacy application. traineeshipApplication.LegacyApplicationId = applicationStatusSummary.LegacyApplicationId; updated = true; } } if (traineeshipApplication.VacancyStatus != applicationStatusSummary.VacancyStatus) { traineeshipApplication.VacancyStatus = applicationStatusSummary.VacancyStatus; updated = true; } if (traineeshipApplication.Vacancy.ClosingDate != applicationStatusSummary.ClosingDate) { traineeshipApplication.Vacancy.ClosingDate = applicationStatusSummary.ClosingDate; updated = true; } return(updated); }
public void Send(ApplicationStatusSummary applicationStatusSummary) { //todo: 1.7: publish communication message for later processing. details TBC - may be removed... }