예제 #1
0
        public async Task ShouldCallReservationValidationsAndReturnErrors()
        {
            var viewModel = new ApprenticeshipViewModel();

            viewModel.ReservationId = Guid.NewGuid();
            viewModel.StartDate     = new DateTimeViewModel(1, 1, 2001);

            var updateModel = new UpdateApprenticeshipViewModel();

            MockMediator.Setup(m => m.SendAsync(It.IsAny <GetReservationValidationRequest>()))
            .ReturnsAsync(new GetReservationValidationResponse
            {
                Data = new ReservationValidationResult(new List <ReservationValidationError>
                {
                    new ReservationValidationError("Reservation", "A reservation issue")
                })
            });

            var result = await Orchestrator.ValidateApprenticeship(viewModel, updateModel);

            Assert.IsTrue(result.ContainsKey("Reservation"));
            Assert.AreEqual("A reservation issue", result["Reservation"]);

            MockMediator.Verify(m => m.SendAsync(It.IsAny <GetReservationValidationRequest>()), Times.Once);
        }
 private bool NeedReapproval(UpdateApprenticeshipViewModel model)
 {
     return
         (!string.IsNullOrEmpty(model.FirstName) ||
          !string.IsNullOrEmpty(model.LastName) ||
          model.DateOfBirth?.DateTime != null ||
          !string.IsNullOrEmpty(model.TrainingCode) ||
          model.StartDate?.DateTime != null ||
          model.EndDate?.DateTime != null ||
          !string.IsNullOrEmpty(model.Cost));
 }
예제 #3
0
 public async Task CreateApprenticeshipUpdate(UpdateApprenticeshipViewModel apprenticeship, string hashedAccountId, string userId, string userName, string userEmail)
 {
     var employerId = _hashingService.DecodeValue(hashedAccountId);
     await _mediator.SendAsync(new CreateApprenticeshipUpdateCommand
     {
         EmployerId           = employerId,
         ApprenticeshipUpdate = _apprenticeshipMapper.MapFrom(apprenticeship),
         UserId           = userId,
         UserEmailAddress = userEmail,
         UserDisplayName  = userName
     });
 }
        public void ThenTheCookieIsDeletedBeforeBeingCreated()
        {
            //Arrange
            var model = new UpdateApprenticeshipViewModel();

            //Act
            _orchestrator.CreateApprenticeshipViewModelCookie(model);

            //Assert
            _cookieStorageService.Verify(x => x.Delete(CookieName));
            _cookieStorageService.Verify(x => x.Create(model, CookieName, 1));
        }
 private bool AnyChanges(UpdateApprenticeshipViewModel data)
 {
     return
         (!string.IsNullOrEmpty(data.FirstName) ||
          !string.IsNullOrEmpty(data.LastName) ||
          data.DateOfBirth != null ||
          !string.IsNullOrEmpty(data.TrainingName) ||
          data.StartDate != null ||
          data.EndDate != null ||
          data.Cost != null ||
          data.EmployerRef != null);
 }
예제 #6
0
        public Dictionary <string, string> ValidateAcademicYear(UpdateApprenticeshipViewModel model)
        {
            var dict = new Dictionary <string, string>();

            if (model.StartDate?.DateTime != null &&
                _academicYearValidator.Validate(model.StartDate.DateTime.Value) == AcademicYearValidationResult.NotWithinFundingPeriod)
            {
                dict.Add($"{nameof(model.StartDate)}", ValidationText.AcademicYearStartDate01.Text);
            }

            return(dict);
        }
예제 #7
0
        public async Task ShouldValidateOverlapAndDateChecks()
        {
            var viewModel   = new ApprenticeshipViewModel();
            var updateModel = new UpdateApprenticeshipViewModel();


            await Orchestrator.ValidateApprenticeship(viewModel, updateModel);

            MockMediator.Verify(m => m.SendAsync(It.IsAny <GetOverlappingApprenticeshipsQueryRequest>()), Times.Once, failMessage: "Should call");
            _mockValidator.Verify(m => m.MapOverlappingErrors(It.IsAny <GetOverlappingApprenticeshipsQueryResponse>()), Times.Once, failMessage: "Should verify overlapping apprenticeship");
            _mockValidator.Verify(m => m.ValidateToDictionary(It.IsAny <ApprenticeshipViewModel>()), Times.Once, failMessage: "Should validate apprenticeship");
            _mockValidator.Verify(m => m.ValidateAcademicYear(It.IsAny <UpdateApprenticeshipViewModel>()), Times.Once, failMessage: "Should validate academic year");
        }
        public async Task <UpdateApprenticeshipViewModel> CompareAndMapToApprenticeshipViewModel(
            Apprenticeship original, ApprenticeshipViewModel edited)
        {
            string ChangedOrNull(string a, string edit) => a?.Trim() == edit?.Trim() ? null : edit;

            var apprenticeshipDetailsViewModel = MapToApprenticeshipDetailsViewModel(original);
            var model = new UpdateApprenticeshipViewModel
            {
                FirstName   = ChangedOrNull(original.FirstName, edited.FirstName),
                LastName    = ChangedOrNull(original.LastName, edited.LastName),
                DateOfBirth = original.DateOfBirth == edited.DateOfBirth.DateTime
                    ? null
                    : edited.DateOfBirth,
                Cost      = original.Cost == edited.Cost.AsNullableDecimal() ? null : edited.Cost,
                StartDate = original.StartDate == edited.StartDate.DateTime
                  ? null
                  : edited.StartDate,
                EndDate = original.EndDate == edited.EndDate.DateTime
                    ? null
                    : edited.EndDate,
                EmployerRef = original.EmployerRef?.Trim() == edited.EmployerRef?.Trim() ||
                              (string.IsNullOrEmpty(original.EmployerRef) && string.IsNullOrEmpty(edited.EmployerRef))
                    ? null
                    : edited.EmployerRef ?? "",
                OriginalApprenticeship = apprenticeshipDetailsViewModel
            };

            if (!string.IsNullOrWhiteSpace(edited.TrainingCode) && original.TrainingCode != edited.TrainingCode)
            {
                var training = await GetTrainingProgramme(edited.TrainingCode);

                if (training != null)
                {
                    model.TrainingType = int.TryParse(training.CourseCode, out _) ? TrainingType.Standard : TrainingType.Framework;
                    model.TrainingCode = edited.TrainingCode;
                    model.TrainingName = training.Name;
                }
                else
                {
                    model.TrainingType = edited.TrainingType;
                    model.TrainingCode = edited.TrainingCode;
                    model.TrainingName = edited.TrainingName;

                    _logger.Warn($"Apprentice training course has expired. TrainingName: {edited.TrainingName}, TrainingCode: {edited.TrainingCode}, Employer Ref: {edited.EmployerRef}, Apprenticeship ULN: {edited.ULN}");
                }
            }

            model.HasHadDataLockSuccess = original.HasHadDataLockSuccess;

            return(model);
        }
예제 #9
0
        public async Task ShouldValidateDateButNotCallReservationValidationsBecauseStartDateIsBlank()
        {
            var viewModel = new ApprenticeshipViewModel();

            viewModel.ReservationId = Guid.NewGuid();
            var updateModel = new UpdateApprenticeshipViewModel();

            _mockValidator.Setup(m => m.ValidateAcademicYear(It.Is <UpdateApprenticeshipViewModel>(p => p.StartDate == null)))
            .Returns(new Dictionary <string, string> {
                { "StartDate", "Start Date cannot be empty" }
            });

            var result = await Orchestrator.ValidateApprenticeship(viewModel, updateModel);

            Assert.IsTrue(result.ContainsKey("StartDate"));
            Assert.AreEqual("Start Date cannot be empty", result["StartDate"]);

            MockMediator.Verify(m => m.SendAsync(It.IsAny <GetReservationValidationRequest>()), Times.Never);
        }
예제 #10
0
        public ApprenticeshipUpdate MapFrom(UpdateApprenticeshipViewModel viewModel)
        {
            var apprenticeshipId = _hashingService.DecodeValue(viewModel.HashedApprenticeshipId);

            return(new ApprenticeshipUpdate
            {
                ApprenticeshipId = apprenticeshipId,
                Cost = viewModel.Cost.AsNullableDecimal(),
                DateOfBirth = viewModel.DateOfBirth?.DateTime,
                FirstName = viewModel.FirstName,
                LastName = viewModel.LastName,
                StartDate = viewModel.StartDate?.DateTime,
                EndDate = viewModel.EndDate?.DateTime,
                Originator = Originator.Employer,
                Status = ApprenticeshipUpdateStatus.Pending,
                TrainingName = viewModel.TrainingName,
                TrainingCode = viewModel.TrainingCode,
                TrainingType = viewModel.TrainingType,
                EmployerRef = viewModel.EmployerRef
            });
        }
예제 #11
0
        public async Task <UpdateApprenticeshipViewModel> CompareAndMapToApprenticeshipViewModel(
            Apprenticeship original, ApprenticeshipViewModel edited)
        {
            Func <string, string, string> changedOrNull = (a, edit) =>
                                                          a?.Trim() == edit?.Trim() ? null : edit;

            var apprenticeshipDetailsViewModel = MapToApprenticeshipDetailsViewModel(original);
            var model = new UpdateApprenticeshipViewModel
            {
                FirstName   = changedOrNull(original.FirstName, edited.FirstName),
                LastName    = changedOrNull(original.LastName, edited.LastName),
                DateOfBirth = original.DateOfBirth == edited.DateOfBirth.DateTime
                    ? null
                    : edited.DateOfBirth,
                Cost      = original.Cost == edited.Cost.AsNullableDecimal() ? null : edited.Cost,
                StartDate = original.StartDate == edited.StartDate.DateTime
                  ? null
                  : edited.StartDate,
                EndDate = original.EndDate == edited.EndDate.DateTime
                    ? null
                    : edited.EndDate,
                EmployerRef = original.EmployerRef?.Trim() == edited.EmployerRef?.Trim() ||
                              (string.IsNullOrEmpty(original.EmployerRef) && string.IsNullOrEmpty(edited.EmployerRef))
                    ? null
                    : edited.EmployerRef ?? "",
                OriginalApprenticeship = apprenticeshipDetailsViewModel
            };

            if (!string.IsNullOrWhiteSpace(edited.TrainingCode) && original.TrainingCode != edited.TrainingCode)
            {
                var training = await GetTrainingProgramme(edited.TrainingCode);

                model.TrainingType = training is Standard ? TrainingType.Standard : TrainingType.Framework;
                model.TrainingCode = edited.TrainingCode;
                model.TrainingName = training.Title;
            }

            return(model);
        }
        public async Task <IDictionary <string, string> > ValidateApprenticeship(ApprenticeshipViewModel apprenticeship, UpdateApprenticeshipViewModel updatedModel)
        {
            ConcurrentDictionary <string, string> errors = new ConcurrentDictionary <string, string>();
            await Task.WhenAll(AddOverlapAndDateValidationErrors(errors, apprenticeship, updatedModel), AddReservationValidationErrors(errors, apprenticeship));

            return(errors);
        }
        public async Task <ActionResult> ViewChanges(string hashedAccountId, string hashedApprenticeshipId, UpdateApprenticeshipViewModel apprenticeship)
        {
            if (!ModelState.IsValid)
            {
                var viewmodel = await _orchestrator
                                .GetViewChangesViewModel(hashedAccountId, hashedApprenticeshipId, OwinWrapper.GetClaimValue(@"sub"));

                viewmodel.Data.AddErrorsFromModelState(ModelState);
                SetErrorMessage(viewmodel, viewmodel.Data.ErrorDictionary);
                return(View(viewmodel));
            }

            if (apprenticeship.ChangesConfirmed != null && apprenticeship.ChangesConfirmed.Value)
            {
                await _orchestrator.SubmitUndoApprenticeshipUpdate(hashedAccountId, hashedApprenticeshipId, OwinWrapper.GetClaimValue(@"sub"), OwinWrapper.GetClaimValue(DasClaimTypes.DisplayName),
                                                                   OwinWrapper.GetClaimValue(DasClaimTypes.Email));

                SetOkayMessage("Changes undone");
            }

            return(RedirectToAction("Details"));
        }
        public async Task <ActionResult> ReviewChanges(string hashedAccountId, string hashedApprenticeshipId, UpdateApprenticeshipViewModel viewModel)
        {
            if (!ModelState.IsValid)
            {
                var viewmodel = await _orchestrator
                                .GetViewChangesViewModel(hashedAccountId, hashedApprenticeshipId, OwinWrapper.GetClaimValue(@"sub"));

                viewmodel.Data.AddErrorsFromModelState(ModelState);
                viewModel.ApprenticeDetailsV2Link = _linkGenerator.CommitmentsV2Link($"{hashedAccountId}/apprentices/{hashedApprenticeshipId}/details");
                SetErrorMessage(viewmodel, viewmodel.Data.ErrorDictionary);
                return(View(viewmodel));
            }
            if (viewModel.ChangesConfirmed != null)
            {
                await _orchestrator.SubmitReviewApprenticeshipUpdate(hashedAccountId, hashedApprenticeshipId, OwinWrapper.GetClaimValue(@"sub"), viewModel.ChangesConfirmed.Value,
                                                                     OwinWrapper.GetClaimValue(DasClaimTypes.DisplayName), OwinWrapper.GetClaimValue(DasClaimTypes.Email));

                var message = viewModel.ChangesConfirmed.Value ? "Changes approved" : "Changes rejected";
                SetOkayMessage(message);
            }
            return(RedirectToAction("Details", new { hashedAccountId, hashedApprenticeshipId }));
        }
        public async Task <ActionResult> SubmitChanges(string hashedAccountId, string hashedApprenticeshipId, UpdateApprenticeshipViewModel apprenticeship)
        {
            if (!await IsUserRoleAuthorized(hashedAccountId, Role.Owner, Role.Transactor))
            {
                return(View("AccessDenied"));
            }

            var orginalApp = await _orchestrator.GetApprenticeship(hashedAccountId, hashedApprenticeshipId, OwinWrapper.GetClaimValue(@"sub"));

            apprenticeship.OriginalApprenticeship = orginalApp.Data;

            if (!ModelState.IsValid)
            {
                var viewmodel = await _orchestrator.GetOrchestratorResponseUpdateApprenticeshipViewModelFromCookie(hashedAccountId, hashedApprenticeshipId);

                viewmodel.Data.AddErrorsFromModelState(ModelState);
                SetErrorMessage(viewmodel, viewmodel.Data.ErrorDictionary);
                return(View("ConfirmChanges", viewmodel));
            }

            if (apprenticeship.ChangesConfirmed != null && !apprenticeship.ChangesConfirmed.Value)
            {
                return(RedirectToAction("Details", new { hashedAccountId, hashedApprenticeshipId }));
            }

            await _orchestrator.CreateApprenticeshipUpdate(apprenticeship, hashedAccountId, OwinWrapper.GetClaimValue(@"sub"), OwinWrapper.GetClaimValue(DasClaimTypes.DisplayName),
                                                           OwinWrapper.GetClaimValue(DasClaimTypes.Email));

            var message = NeedReapproval(apprenticeship)
                ? "Suggested changes sent to training provider for approval, where needed."
                : "Apprentice updated";

            var flashmessage = new FlashMessageViewModel
            {
                Message  = message,
                Severity = FlashMessageSeverityLevel.Okay
            };

            AddFlashMessageToCookie(flashmessage);


            return(RedirectToAction("Details", new { hashedAccountId, hashedApprenticeshipId }));
        }
        private async Task AddOverlapAndDateValidationErrors(ConcurrentDictionary <string, string> errors, ApprenticeshipViewModel apprenticeship, UpdateApprenticeshipViewModel updatedModel)
        {
            void AddToErrors(IDictionary <string, string> items)
            {
                foreach (var error in items)
                {
                    errors.TryAdd(error.Key, error.Value);
                }
            }

            var overlappingErrors = await Mediator.SendAsync(
                new GetOverlappingApprenticeshipsQueryRequest
            {
                Apprenticeship = new List <Apprenticeship> {
                    await _apprenticeshipMapper.MapFrom(apprenticeship)
                }
            });

            AddToErrors(_approvedApprenticeshipValidator.MapOverlappingErrors(overlappingErrors));
            AddToErrors(_approvedApprenticeshipValidator.ValidateToDictionary(apprenticeship));
            AddToErrors(_approvedApprenticeshipValidator.ValidateAcademicYear(updatedModel));
        }
예제 #17
0
 public void CreateApprenticeshipViewModelCookie(UpdateApprenticeshipViewModel model)
 {
     _apprenticshipsViewModelCookieStorageService.Delete(CookieName);
     model.OriginalApprenticeship = null;
     _apprenticshipsViewModelCookieStorageService.Create(model, CookieName);
 }