diff --git a/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs b/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs index 0840b4bb23..0dd7f31111 100644 --- a/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs +++ b/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs @@ -30,14 +30,14 @@ public VacancyPreviewController(VacancyPreviewOrchestrator orchestrator) } [HttpGet("preview", Name = RouteNames.Vacancy_Preview_Get)] - public async Task VacancyPreview(VacancyRouteModel vrm, string selection = null) + public async Task VacancyPreview(VacancyRouteModel vrm, bool? submitToEfsa = null) { var viewModel = await _orchestrator.GetVacancyPreviewViewModelAsync(vrm); AddSoftValidationErrorsToModelState(viewModel); SetSectionStates(viewModel); viewModel.CanHideValidationSummary = true; - ViewBag.Selection = selection; + viewModel.SubmitToEsfa = submitToEfsa; if (TempData.ContainsKey(TempDataKeys.VacancyClonedInfoMessage)) viewModel.VacancyClonedInfoMessage = TempData[TempDataKeys.VacancyClonedInfoMessage].ToString(); @@ -50,6 +50,15 @@ public async Task Review(SubmitReviewModel m) { if (ModelState.IsValid) { + if(m.SubmitToEsfa.Value) + { + await _orchestrator.ClearRejectedVacancyReason(m, User.ToVacancyUser()); + } + else + { + await _orchestrator.UpdateRejectedVacancyReason(m, User.ToVacancyUser()); + } + return RedirectToRoute(m.SubmitToEsfa.GetValueOrDefault() ? RouteNames.ApproveJobAdvert_Get : RouteNames.RejectJobAdvert_Get); @@ -57,6 +66,8 @@ public async Task Review(SubmitReviewModel m) var viewModel = await _orchestrator.GetVacancyPreviewViewModelAsync(m); viewModel.SoftValidationErrors = null; + viewModel.SubmitToEsfa = m.SubmitToEsfa; + viewModel.RejectedReason = m.RejectedReason; SetSectionStates(viewModel); return View(ViewNames.VacancyPreview, viewModel); @@ -125,7 +136,7 @@ public async Task ApproveJobAdvert(ApproveJobAdvertViewModel vm) } else { - return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, Selection = "Approve" }); + return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, SubmitToEfsa = true }); } var viewModel = await _orchestrator.GetVacancyPreviewViewModelAsync(vm); @@ -167,7 +178,7 @@ public async Task RejectJobAdvert(RejectJobAdvertViewModel vm) } } - return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, Selection = "Reject" }); + return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, SubmitToEfsa = false }); } [HttpGet("confirmation-advert", Name = RouteNames.JobAdvertConfirmation_Get)] diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs index c21c04985c..93d3caa47c 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs @@ -7,6 +7,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Domain.Extensions; @@ -15,7 +16,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class DatesOrchestrator : EntityValidatingOrchestrator + public class DatesOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ClosingDate | VacancyRuleSet.StartDate | VacancyRuleSet.StartDateEndDate | VacancyRuleSet.TrainingExpiryDate; private readonly IEmployerVacancyClient _client; @@ -99,11 +100,33 @@ public async Task PostDatesEditModelAsync(DatesEditModel m { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.Dates_Post); - vacancy.ClosingDate = m.ClosingDate.AsDateTimeUk()?.ToUniversalTime(); - vacancy.StartDate = m.StartDate.AsDateTimeUk()?.ToUniversalTime(); - - vacancy.DisabilityConfident = m.IsDisabilityConfident ? DisabilityConfident.Yes : DisabilityConfident.No; - + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ClosingDate, + FieldIdResolver.ToFieldId(v => v.ClosingDate), + vacancy, + (v) => + { + return v.ClosingDate = m.ClosingDate.AsDateTimeUk()?.ToUniversalTime(); + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.StartDate, + FieldIdResolver.ToFieldId(v => v.StartDate), + vacancy, + (v) => + { + return v.StartDate = m.StartDate.AsDateTimeUk()?.ToUniversalTime(); + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.DisabilityConfident, + FieldIdResolver.ToFieldId(v => v.DisabilityConfident), + vacancy, + (v) => + { + return v.DisabilityConfident = m.IsDisabilityConfident ? DisabilityConfident.Yes : DisabilityConfident.No; + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs index 9f0eb29a7d..123bfc6e3c 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs @@ -6,6 +6,7 @@ using Esfa.Recruit.Shared.Web.Extensions; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -13,7 +14,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class DurationOrchestrator : EntityValidatingOrchestrator + public class DurationOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Duration | VacancyRuleSet.WorkingWeekDescription | VacancyRuleSet.WeeklyHours; private readonly IEmployerVacancyClient _client; @@ -72,11 +73,42 @@ public async Task PostDurationEditModelAsync(DurationEditM if(vacancy.Wage == null) vacancy.Wage = new Wage(); - vacancy.Wage.Duration = int.TryParse(m.Duration, out int duration) ? duration : default(int?); - vacancy.Wage.DurationUnit = m.DurationUnit; - vacancy.Wage.WorkingWeekDescription = m.WorkingWeekDescription; - vacancy.Wage.WeeklyHours = m.WeeklyHours.AsDecimal(2); - + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.Duration, + FieldIdResolver.ToFieldId(v => v.Wage.Duration), + vacancy, + (v) => + { + return v.Wage.Duration = int.TryParse(m.Duration, out int duration) ? duration : default(int?); + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.DurationUnit, + FieldIdResolver.ToFieldId(v => v.Wage.DurationUnit), + vacancy, + (v) => + { + return v.Wage.DurationUnit = m.DurationUnit; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WorkingWeekDescription, + FieldIdResolver.ToFieldId(v => v.Wage.WorkingWeekDescription), + vacancy, + (v) => + { + return v.Wage.WorkingWeekDescription = m.WorkingWeekDescription; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WeeklyHours, + FieldIdResolver.ToFieldId(v => v.Wage.WeeklyHours), + vacancy, + (v) => + { + return v.Wage.WeeklyHours = m.WeeklyHours.AsDecimal(2); + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs index 312511c11f..a2cee6bd02 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs @@ -16,10 +16,11 @@ using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Employer.Web.Mappings; using Esfa.Recruit.Shared.Web.Models; +using Esfa.Recruit.Vacancies.Client.Application.Services; namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class LocationOrchestrator : EntityValidatingOrchestrator + public class LocationOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerAddress; private readonly IEmployerVacancyClient _employerVacancyClient; @@ -140,14 +141,91 @@ public async Task PostLocationEditModelAsync( var matchingAddress = GetMatchingAddress(newLocation, allLocations); - vacancy.EmployerLocation = matchingAddress != null ? matchingAddress : ConvertToDomainAddress(locationEditModel); + var employerLocation = matchingAddress != null ? matchingAddress : ConvertToDomainAddress(locationEditModel); - //if cookie is found then update legal entity and name option from cookie + // this has diverged from the usual pattern because the individual properties are review fields + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine1, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine1), + vacancy, + (v) => + { + return employerLocation.AddressLine1; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine2, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine2), + vacancy, + (v) => + { + return employerLocation.AddressLine2; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine3, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine3), + vacancy, + (v) => + { + return employerLocation.AddressLine3; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine4, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine4), + vacancy, + (v) => + { + return employerLocation.AddressLine4; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.Postcode, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.Postcode), + vacancy, + (v) => + { + return employerLocation.Postcode; + }); + + vacancy.EmployerLocation = employerLocation; + + // if cookie is found then update legal entity and name option from cookie if (employerInfoModel != null) { - vacancy.LegalEntityName = selectedOrganisation.Name; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.LegalEntityName, + FieldIdResolver.ToFieldId(v => v.EmployerName), + vacancy, + (v) => + { + return v.LegalEntityName = selectedOrganisation.Name; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerNameOption, + FieldIdResolver.ToFieldId(v => v.EmployerName), + vacancy, + (v) => + { + return v.EmployerNameOption = employerInfoModel.EmployerIdentityOption?.ConvertToDomainOption(); + }); + + if (employerInfoModel.EmployerIdentityOption == EmployerIdentityOption.NewTradingName) + { + SetVacancyWithEmployerReviewFieldIndicators( + employerProfile.TradingName, + FieldIdResolver.ToFieldId(v => v.EmployerName), + vacancy, + (e) => + { + // the indicator will be set for the vacancy when the employer profile will change to the new trading name + return employerInfoModel.NewTradingName; + }); + } + vacancy.AccountLegalEntityPublicHashedId = selectedOrganisation.AccountLegalEntityPublicHashedId; - vacancy.EmployerNameOption = employerInfoModel.EmployerIdentityOption?.ConvertToDomainOption(); vacancy.AnonymousReason = vacancy.IsAnonymous ? employerInfoModel.AnonymousReason : null; vacancy.EmployerName = vacancy.IsAnonymous ? employerInfoModel.AnonymousName : null; } @@ -161,6 +239,7 @@ public async Task PostLocationEditModelAsync( await UpdateEmployerProfile(employerInfoModel, employerProfile, matchingAddress == null ? vacancy.EmployerLocation : null, user); }); } + private Address GetMatchingAddress(string locationToMatch, IEnumerable
allLocations) { var matchingLocation = @@ -206,8 +285,6 @@ private async Task UpdateEmployerProfile(VacancyEmployerInfoModel employerInfoMo } } - - private async Task> GetAllAvailableLocationsAsync(EmployerProfile employerProfile) { var employerData = await _employerVacancyClient.GetEditVacancyInfoAsync(employerProfile.EmployerAccountId); diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs index a7caee7c55..51b6d131ae 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs @@ -6,6 +6,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part1.NumberOfPositions; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -13,7 +14,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class NumberOfPositionsOrchestrator : EntityValidatingOrchestrator + public class NumberOfPositionsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.NumberOfPositions; private readonly IEmployerVacancyClient _client; @@ -58,9 +59,17 @@ public async Task GetNumberOfPositionsViewModelAsync public async Task> PostNumberOfPositionsEditModelAsync(NumberOfPositionsEditModel m, VacancyUser user) { - var numberOfPositions = int.TryParse(m.NumberOfPositions, out var n)? n : default(int?); var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient,m, RouteNames.NumberOfPositions_Post); - vacancy.NumberOfPositions = numberOfPositions; + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.NumberOfPositions, + FieldIdResolver.ToFieldId(v => v.NumberOfPositions), + vacancy, + (v) => + { + return v.NumberOfPositions = int.TryParse(m.NumberOfPositions, out var n) ? n : default(int?); + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs index b9dba9443d..661d5306c2 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs @@ -8,6 +8,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Shared.Web.ViewModels; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -16,21 +17,19 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class TitleOrchestrator : EntityValidatingOrchestrator + public class TitleOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Title; private readonly IEmployerVacancyClient _client; private readonly IRecruitVacancyClient _vacancyClient; private readonly IReviewSummaryService _reviewSummaryService; - private readonly IEmployerVacancyClient _employerVacancyClient; private readonly ITrainingProviderService _trainingProviderService; - public TitleOrchestrator(IEmployerVacancyClient client, IRecruitVacancyClient vacancyClient, ILogger logger, IReviewSummaryService reviewSummaryService, IEmployerVacancyClient employerVacancyClient, ITrainingProviderService trainingProviderService) : base(logger) + public TitleOrchestrator(IEmployerVacancyClient client, IRecruitVacancyClient vacancyClient, ILogger logger, IReviewSummaryService reviewSummaryService, ITrainingProviderService trainingProviderService) : base(logger) { _client = client; _vacancyClient = vacancyClient; _reviewSummaryService = reviewSummaryService; - _employerVacancyClient = employerVacancyClient; _trainingProviderService = trainingProviderService; } @@ -45,7 +44,7 @@ public TitleViewModel GetTitleViewModel() public async Task GetTitleViewModelAsync(VacancyRouteModel vrm) { - var dashboard = await _employerVacancyClient.GetDashboardAsync(vrm.EmployerAccountId); + var dashboard = await _client.GetDashboardAsync(vrm.EmployerAccountId); var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, vrm, RouteNames.Title_Get); var vm = new TitleViewModel @@ -83,7 +82,6 @@ public async Task GetTitleViewModelAsync(TitleEditModel m) return vm; } - public async Task> PostTitleEditModelAsync(TitleEditModel m, VacancyUser user) { TrainingProvider provider = null; @@ -111,7 +109,14 @@ public async Task> PostTitleEditModelAsync(TitleEditM var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, new VacancyRouteModel{EmployerAccountId = m.EmployerAccountId, VacancyId = m.VacancyId.Value}, RouteNames.Title_Post); - vacancy.Title = m.Title; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Title, + FieldIdResolver.ToFieldId(v => v.Title), + vacancy, + (v) => + { + return v.Title = m.Title; + }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs index 1606d236df..ecbbfa3c92 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs @@ -8,6 +8,7 @@ using Esfa.Recruit.Shared.Web.Helpers; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Domain.Extensions; @@ -16,7 +17,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class TrainingOrchestrator : EntityValidatingOrchestrator + public class TrainingOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProgramme; private readonly IEmployerVacancyClient _client; @@ -104,8 +105,15 @@ public async Task GetConfirmTrainingViewModelAsync(Vac public async Task PostConfirmTrainingEditModelAsync(ConfirmTrainingEditModel m, VacancyUser user) { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.Training_Confirm_Post); - - vacancy.ProgrammeId = m.ProgrammeId; + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ProgrammeId, + FieldIdResolver.ToFieldId(v => v.ProgrammeId), + vacancy, + (v) => + { + return v.ProgrammeId = m.ProgrammeId; + }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs index 793269c0db..787b1589fc 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs @@ -11,6 +11,7 @@ using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Configuration; using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -19,7 +20,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class TrainingProviderOrchestrator : EntityValidatingOrchestrator + public class TrainingProviderOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProvider; private readonly IEmployerVacancyClient _client; @@ -148,6 +149,16 @@ public async Task PostConfirmEditModelAsync(ConfirmTrainin var vacancy = vacancyTask.Result; var provider = providerTask.Result; + // this has diverged from the usual pattern because only a single individual property is a review field + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.TrainingProvider?.Ukprn, + FieldIdResolver.ToFieldId(v => v.TrainingProvider.Ukprn), + vacancy, + (v) => + { + return provider.Ukprn; + }); + vacancy.TrainingProvider = provider; return await ValidateAndExecute( diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs index 648609a3d7..9570297dd9 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs @@ -8,6 +8,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Domain.Extensions; @@ -18,7 +19,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class WageOrchestrator : EntityValidatingOrchestrator + public class WageOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Wage | VacancyRuleSet.MinimumWage; private readonly IEmployerVacancyClient _client; @@ -82,10 +83,33 @@ public async Task PostWageEditModelAsync(WageEditModel m, if(vacancy.Wage == null) vacancy.Wage = new Wage(); - vacancy.Wage.WageType = m.WageType; - vacancy.Wage.FixedWageYearlyAmount = (m.WageType == WageType.FixedWage) ? m.FixedWageYearlyAmount?.AsMoney() : null; - vacancy.Wage.WageAdditionalInformation = m.WageAdditionalInformation; - + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WageType, + FieldIdResolver.ToFieldId(v => v.Wage.WageType), + vacancy, + (v) => + { + return v.Wage.WageType = m.WageType; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.FixedWageYearlyAmount, + FieldIdResolver.ToFieldId(v => v.Wage.FixedWageYearlyAmount), + vacancy, + (v) => + { + return v.Wage.FixedWageYearlyAmount = (m.WageType == WageType.FixedWage) ? m.FixedWageYearlyAmount?.AsMoney() : null; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WageAdditionalInformation, + FieldIdResolver.ToFieldId(v => v.Wage.WageAdditionalInformation), + vacancy, + (v) => + { + return v.Wage.WageAdditionalInformation = m.WageAdditionalInformation; + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs index 2d9aa7cdb3..dfd86bb683 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs @@ -7,6 +7,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.AboutEmployer; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -14,7 +15,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class AboutEmployerOrchestrator : EntityValidatingOrchestrator + public class AboutEmployerOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerDescription | VacancyRuleSet.EmployerWebsiteUrl; private readonly IEmployerVacancyClient _client; @@ -64,8 +65,17 @@ public async Task PostAboutEmployerEditModelAsync(AboutEmp { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.AboutEmployer_Post); - vacancy.EmployerDescription = m.EmployerDescription; - vacancy.EmployerWebsiteUrl = m.EmployerWebsiteUrl; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerDescription, + FieldIdResolver.ToFieldId(v => v.EmployerDescription), + vacancy, + (v) => { return v.EmployerDescription = m.EmployerDescription; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerWebsiteUrl, + FieldIdResolver.ToFieldId(v => v.EmployerWebsiteUrl), + vacancy, + (v) => { return v.EmployerWebsiteUrl = m.EmployerWebsiteUrl; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs index f3df55cf04..5077012da6 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs @@ -6,6 +6,7 @@ using Esfa.Recruit.Employer.Web.ViewModels; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -14,7 +15,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class ApplicationProcessOrchestrator : EntityValidatingOrchestrator + public class ApplicationProcessOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ApplicationMethod; private readonly IEmployerVacancyClient _client; @@ -70,11 +71,25 @@ public async Task PostApplicationProcessEditModelAsync(App { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.ApplicationProcess_Post); + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ApplicationMethod, + FieldIdResolver.ToFieldId(v => v.ApplicationMethod), + vacancy, + (v) => { return v.ApplicationMethod = m.ApplicationMethod; }); + var hasSelectedApplyThroughFaa = m.ApplicationMethod == ApplicationMethod.ThroughFindAnApprenticeship; - vacancy.ApplicationMethod = m.ApplicationMethod; - vacancy.ApplicationInstructions = hasSelectedApplyThroughFaa ? null : m.ApplicationInstructions; - vacancy.ApplicationUrl = hasSelectedApplyThroughFaa ? null : m.ApplicationUrl; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ApplicationInstructions, + FieldIdResolver.ToFieldId(v => v.ApplicationInstructions), + vacancy, + (v) => { return v.ApplicationInstructions = hasSelectedApplyThroughFaa ? null : m.ApplicationInstructions; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ApplicationUrl, + FieldIdResolver.ToFieldId(v => v.ApplicationUrl), + vacancy, + (v) => { return v.ApplicationUrl = hasSelectedApplyThroughFaa ? null : m.ApplicationUrl; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs index e4eeaa5a00..7ef06649a7 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class ConsiderationsOrchestrator : EntityValidatingOrchestrator + public class ConsiderationsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ThingsToConsider; private readonly IEmployerVacancyClient _client; @@ -57,8 +58,12 @@ public async Task GetConsiderationsViewModelAsync(Consi public async Task PostConsiderationsEditModelAsync(ConsiderationsEditModel m, VacancyUser user) { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.Considerations_Post); - - vacancy.ThingsToConsider = m.ThingsToConsider; + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ThingsToConsider, + FieldIdResolver.ToFieldId(v => v.ThingsToConsider), + vacancy, + (v) => { return v.ThingsToConsider = m.ThingsToConsider; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs index 57509cf30d..fd770f165f 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class EmployerContactDetailsOrchestrator : EntityValidatingOrchestrator + public class EmployerContactDetailsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerContactDetails; private readonly IEmployerVacancyClient _client; @@ -63,12 +64,26 @@ public async Task PostEmployerContactDetailsEditModelAsync { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.EmployerContactDetails_Post); - vacancy.EmployerContact = new ContactDetail - { - Name = m.EmployerContactName, - Email = m.EmployerContactEmail, - Phone = m.EmployerContactPhone - }; + if (vacancy.EmployerContact == null) + vacancy.EmployerContact = new ContactDetail(); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerContact.Name, + FieldIdResolver.ToFieldId(v => v.EmployerContact.Name), + vacancy, + (v) => { return v.EmployerContact.Name = m.EmployerContactName; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerContact.Email, + FieldIdResolver.ToFieldId(v => v.EmployerContact.Email), + vacancy, + (v) => { return v.EmployerContact.Email = m.EmployerContactEmail; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerContact.Phone, + FieldIdResolver.ToFieldId(v => v.EmployerContact.Phone), + vacancy, + (v) => { return v.EmployerContact.Phone = m.EmployerContactPhone; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs index 9737f1eaf3..e5dea21242 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs @@ -10,6 +10,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Shared.Web.ViewModels.Qualifications; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -17,7 +18,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class QualificationsOrchestrator : EntityValidatingOrchestrator + public class QualificationsOrchestrator : VacancyValidatingOrchestrator { private readonly IEmployerVacancyClient _client; private readonly IRecruitVacancyClient _vacancyClient; @@ -118,10 +119,10 @@ public async Task PostQualificationEditModelForAddAsync(Va if (vacancy.Qualifications == null) vacancy.Qualifications = new List(); - var qualification = new Qualification(); + var qualification = new Qualification(); vacancy.Qualifications.Add(qualification); - return await UpdateVacancyWithQualificationAsync(vacancy, qualification, m, user); + return await UpdateVacancyWithQualificationAsync(vacancy, null, qualification, m, user); } public async Task PostQualificationEditModelForEditAsync(VacancyRouteModel vrm, QualificationEditModel m, VacancyUser user, int index) @@ -129,8 +130,15 @@ public async Task PostQualificationEditModelForEditAsync(V var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, vrm, RouteNames.Qualification_Edit_Post); var qualification = vacancy.Qualifications[index]; + var currentQualification = new Qualification + { + QualificationType = qualification.QualificationType, + Grade = qualification.Grade, + Subject = qualification.Subject, + Weighting = qualification.Weighting, + }; - return await UpdateVacancyWithQualificationAsync(vacancy, qualification, m, user); + return await UpdateVacancyWithQualificationAsync(vacancy, currentQualification, qualification, m, user); } public async Task DeleteQualificationAsync(VacancyRouteModel vrm, int index, VacancyUser user) @@ -140,7 +148,15 @@ public async Task DeleteQualificationAsync(VacancyRouteModel vrm, int index, Vac if (vacancy.Qualifications == null) return; - vacancy.Qualifications.RemoveAt(index); + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Qualifications[index], + FieldIdResolver.ToFieldId(v => v.Qualifications), + vacancy, + (v) => + { + vacancy.Qualifications.RemoveAt(index); + return null; + }); await _vacancyClient.UpdateDraftVacancyAsync(vacancy, user); } @@ -199,15 +215,22 @@ private void SetQualificationViewModelFromEditModel(QualificationViewModel vm, Q vm.Weighting = m.Weighting; } - private async Task UpdateVacancyWithQualificationAsync(Vacancy vacancy, Qualification qualification, QualificationEditModel m, VacancyUser user) + private async Task UpdateVacancyWithQualificationAsync(Vacancy vacancy, Qualification currentQualification, Qualification qualification, QualificationEditModel m, VacancyUser user) { - qualification.QualificationType = m.QualificationType; - qualification.Grade = m.Grade; - qualification.Subject = m.Subject; - qualification.Weighting = m.Weighting; - - var allQualifications = await _vacancyClient.GetCandidateQualificationsAsync(); - vacancy.Qualifications = vacancy.Qualifications.SortQualifications(allQualifications).ToList(); + SetVacancyWithEmployerReviewFieldIndicators( + currentQualification, + FieldIdResolver.ToFieldId(v => v.Qualifications), + vacancy, + (v) => { + qualification.QualificationType = m.QualificationType; + qualification.Grade = m.Grade; + qualification.Subject = m.Subject; + qualification.Weighting = m.Weighting; + return qualification; + }); + + var qualificationTypes = await _vacancyClient.GetCandidateQualificationsAsync(); + vacancy.Qualifications = vacancy.Qualifications.SortQualifications(qualificationTypes).ToList(); return await ValidateAndExecute(vacancy, v => diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs index af42e2698a..002c203c3c 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part2.ShortDescription; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class ShortDescriptionOrchestrator : EntityValidatingOrchestrator + public class ShortDescriptionOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ShortDescription; private readonly IEmployerVacancyClient _client; @@ -59,7 +60,14 @@ public async Task PostShortDescriptionEditModelAsync(Short { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.ShortDescription_Post); - vacancy.ShortDescription = m.ShortDescription; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ShortDescription, + FieldIdResolver.ToFieldId(v => v.ShortDescription), + vacancy, + (v) => + { + return v.ShortDescription = m.ShortDescription; + }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs index ee53793ae3..c7e44a01ce 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs @@ -8,7 +8,7 @@ using Esfa.Recruit.Shared.Web.Extensions; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; -using Esfa.Recruit.Shared.Web.ViewModels.Skills; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -16,7 +16,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class SkillsOrchestrator : EntityValidatingOrchestrator + public class SkillsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Skills; private readonly IEmployerVacancyClient _client; @@ -79,9 +79,22 @@ public async Task PostSkillsEditModelAsync(VacancyRouteMod m.Skills = new List(); } - _skillsHelper.SetVacancyFromEditModel(vacancy, m); + var currentSkills = new List(); + if (vacancy.Skills != null) + currentSkills.AddRange(vacancy.Skills); - //if we are adding/removing a skill then just validate and don't persist + SetVacancyWithEmployerReviewFieldIndicators( + currentSkills, + FieldIdResolver.ToFieldId(v => v.Skills), + vacancy, + (v) => + { + _skillsHelper.SetVacancyFromEditModel(v, m); + return v.Skills; + }); + + // when adding a custom skill the vacancy is not saved immediately, the new custom skill is + // validated but all the updates are saved later in a single operation var validateOnly = m.IsAddingCustomSkill; return await ValidateAndExecute(vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs index cc485af2d4..74e62b4035 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part2.VacancyDescription; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,9 +13,9 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class VacancyDescriptionOrchestrator : EntityValidatingOrchestrator + public class VacancyDescriptionOrchestrator : VacancyValidatingOrchestrator { - private const VacancyRuleSet ValdationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; private readonly IEmployerVacancyClient _client; private readonly IRecruitVacancyClient _vacancyClient; private readonly IReviewSummaryService _reviewSummaryService; @@ -65,14 +66,28 @@ public async Task GetVacancyDescriptionViewModelAsy public async Task PostVacancyDescriptionEditModelAsync(VacancyDescriptionEditModel m, VacancyUser user) { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.VacancyDescription_Index_Post); - - vacancy.Description = m.VacancyDescription; - vacancy.TrainingDescription = m.TrainingDescription; - vacancy.OutcomeDescription = m.OutcomeDescription; - + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Description, + FieldIdResolver.ToFieldId(v => v.Description), + vacancy, + (v) => { return v.Description = m.VacancyDescription; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.TrainingDescription, + FieldIdResolver.ToFieldId(v => v.TrainingDescription), + vacancy, + (v) => { return v.TrainingDescription = m.TrainingDescription; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.OutcomeDescription, + FieldIdResolver.ToFieldId(v => v.OutcomeDescription), + vacancy, + (v) => { return v.OutcomeDescription = m.OutcomeDescription; }); + return await ValidateAndExecute( vacancy, - v => _vacancyClient.Validate(v, ValdationRules), + v => _vacancyClient.Validate(v, ValidationRules), v => _vacancyClient.UpdateDraftVacancyAsync(vacancy, user) ); } diff --git a/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs index 0be15ac525..70eb29ec40 100644 --- a/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs @@ -68,7 +68,8 @@ public async Task GetVacancyPreviewViewModelAsync(Vacan var vm = new VacancyPreviewViewModel(); await _vacancyDisplayMapper.MapFromVacancyAsync(vm, vacancy); - + + vm.RejectedReason = vacancy.EmployerRejectedReason; vm.HasProgramme = vacancy.ProgrammeId != null; vm.HasWage = vacancy.Wage != null; vm.CanShowReference = vacancy.Status != VacancyStatus.Draft; @@ -144,7 +145,25 @@ private async Task RejectActionAsync(Vacancy vacancy, Vac await _messaging.SendCommandAsync(command); - return new RejectVacancyResponse { IsRejected = true }; + return new RejectVacancyResponse { IsRejected = true }; + } + + public async Task ClearRejectedVacancyReason(SubmitReviewModel m, VacancyUser user) + { + var vacancy = await Utility.GetAuthorisedVacancyAsync(_vacancyClient, m, RouteNames.ApproveJobAdvert_Post); + + vacancy.EmployerRejectedReason = null; + + await _vacancyClient.UpdateDraftVacancyAsync(vacancy, user); + } + + public async Task UpdateRejectedVacancyReason(SubmitReviewModel m, VacancyUser user) + { + var vacancy = await Utility.GetAuthorisedVacancyAsync(_vacancyClient, m, RouteNames.ApproveJobAdvert_Post); + + vacancy.EmployerRejectedReason = m.RejectedReason; + + await _vacancyClient.UpdateDraftVacancyAsync(vacancy, user); } public async Task> ApproveJobAdvertAsync(ApproveJobAdvertViewModel m, VacancyUser user) @@ -205,7 +224,8 @@ public async Task GetVacancyRejectJobAdvertAsync(Vacan var vacancy = await _vacancyClient.GetVacancyAsync(vrm.VacancyId); var vm = new RejectJobAdvertViewModel - { + { + RejectionReason = vacancy.EmployerRejectedReason, TrainingProviderName = vacancy.TrainingProvider.Name }; diff --git a/src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs new file mode 100644 index 0000000000..2beca6b849 --- /dev/null +++ b/src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Esfa.Recruit.Employer.Web.Mappings; +using Esfa.Recruit.Shared.Web.Orchestrators; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace Esfa.Recruit.Employer.Web.Orchestrators +{ + public abstract class VacancyValidatingOrchestrator : EntityValidatingOrchestrator + { + protected VacancyValidatingOrchestrator(ILogger logger) + : base(logger) + { + } + + protected void SetVacancyWithEmployerReviewFieldIndicators(T currentValue, + string fieldId, + Vacancy vacancy, + Func setFunc + ) + { + PopulateEmployerReviewFieldIndicators(vacancy); + + var newValue = setFunc(vacancy); + if (!JsonConvert.SerializeObject(currentValue).Equals(JsonConvert.SerializeObject(newValue))) + { + foreach (var fieldIdentifier in ReviewFieldMappingLookups.GetPreviewReviewFieldIndicators().VacancyPropertyMappingsLookup[fieldId]) + { + var changedIndicator = vacancy.EmployerReviewFieldIndicators.Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault(); + if (changedIndicator != null) + { + changedIndicator.IsChangeRequested = true; + } + } + } + } + + private void PopulateEmployerReviewFieldIndicators(Vacancy vacancy) + { + var employerReviewFieldIndicators = vacancy.EmployerReviewFieldIndicators ?? new List(); + + // add field indicators which are missing + var missingIndicators = + ReviewFieldMappingLookups + .GetPreviewReviewFieldIndicators().FieldIdentifiersForPage + .Select(p => new EmployerReviewFieldIndicator { FieldIdentifier = p.ReviewFieldIdentifier, IsChangeRequested = false }) + .Where(p => !employerReviewFieldIndicators.Any(v => v.FieldIdentifier == p.FieldIdentifier)); + + if (missingIndicators.Any()) + { + employerReviewFieldIndicators + .AddRange(missingIndicators); + + vacancy.EmployerReviewFieldIndicators = employerReviewFieldIndicators + .OrderBy(p => p.FieldIdentifier).ToList(); + } + } + } +} diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs index c304694052..ce0600b970 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs @@ -7,6 +7,7 @@ public class RejectJobAdvertViewModel : VacancyRouteModel { [Required(ErrorMessage = "Select if you want to reject this job advert")] public bool? RejectJobAdvert { get; set; } + public string RejectionReason { get; set; } public string TrainingProviderName { get; set; } } diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs index 48fe7ed7d2..af127ad960 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs @@ -1,11 +1,33 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using Esfa.Recruit.Employer.Web.RouteModel; namespace Esfa.Recruit.Employer.Web.ViewModels.Preview { - public class SubmitReviewModel : VacancyRouteModel + public class SubmitReviewModel : VacancyRouteModel, IValidatableObject { - [Required(ErrorMessage = "You need to submit or reject the advert")] + private const int RejectedReasonMaxCharacters = 200; + + [Required(ErrorMessage = "Confirm if you want to submit or reject this advert ")] public bool? SubmitToEsfa { get; set; } + + public string RejectedReason { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + var property = new[] { nameof(RejectedReason) }; + + if(SubmitToEsfa.HasValue && SubmitToEsfa.Value == false) + { + if (string.IsNullOrEmpty(RejectedReason)) + { + yield return new ValidationResult("Enter details of why you are rejecting this advert", property); + } + else if (RejectedReason.Length > RejectedReasonMaxCharacters) + { + yield return new ValidationResult($"You have {RejectedReason.Length- RejectedReasonMaxCharacters} character too many", property); + } + } + } } } diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs index 1904afcd82..52a21e2dd8 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs @@ -66,6 +66,9 @@ public class VacancyPreviewViewModel : DisplayVacancyViewModel public bool HasSoftValidationErrors => SoftValidationErrors?.HasErrors == true; + public string RejectedReason { get; set; } + public bool? SubmitToEsfa { get; set; } + public bool ShowIncompleteSections => ((HasIncompleteMandatorySections || HasIncompleteOptionalSections) && !Review.HasBeenReviewed) || HasSoftValidationErrors; public ReviewSummaryViewModel Review { get; set; } = new ReviewSummaryViewModel(); public string SubmitButtonText => Review.HasBeenReviewed ? "Resubmit advert" : "Submit advert"; diff --git a/src/Employer/Employer.Web/Views/Submitted/Confirmation.cshtml b/src/Employer/Employer.Web/Views/Submitted/Confirmation.cshtml index 528f84fbc9..f3f1b9d61a 100644 --- a/src/Employer/Employer.Web/Views/Submitted/Confirmation.cshtml +++ b/src/Employer/Employer.Web/Views/Submitted/Confirmation.cshtml @@ -6,42 +6,37 @@ ViewBag.Title = "Advert submitted for approval"; } -

@Model.Title

-
-
-

- Advert submitted for approval +
+

+ Advert submitted to ESFA +

+

+ Advert resubmitted to ESFA

- The advert reference number is
+ Your reference number is
VAC@(Model.VacancyReference)

-
-

- Advert resubmitted for approval -

-
+

What happens next

-

We’ll check the advert within one working day and let you know by email if you need to make any edits. Manage your emails.

-

When we approve your advert, it will appear on the ​Find an apprenticeship service (opens in a new tab or window).

+

The ESFA will check the advert and let you know by email, within one working day, if you need to make any edits.

-

We’ll check the advert within one working day and tell you on the dashboard if you need to make any edits. You can manage your emails if you’d also like to get an email.

-

When we approve your advert, it will appear on the ​Find an apprenticeship service (opens in a new tab or window).

-
-
- +

The ESFA will check the advert and will tell you within one working day, on the Recruitment dashboard within rejected adverts, if you need to make any edits.

+

Manage the frequency of your recruitment emails.

+

When the advert is approved, it will appear on ​Find an apprenticeship (opens in a new tab).

+

+ Return to dashboard +

+

+ Create another advert +

\ No newline at end of file diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml index b9ad6cb4a6..0b71b57030 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml @@ -29,7 +29,7 @@

When we approve your advert, it will appear on the Find an apprenticeship service (opens in a new tab or window).

-

This job advert has gone back to @Model.TrainingProviderName. You may want to tell them why you've rejected it.

+

This job advert has gone back to @Model.TrainingProviderName.

diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml index b7ff56176d..e4289d2125 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml @@ -3,18 +3,22 @@ @{ ViewBag.Vpv = "/recruitment/employer/reject-job-advert"; ViewBag.Title = "Are you sure you want to reject this job advert?"; } -Back +Back

- Are you sure you want to reject this job advert? -

-
-

This job advert will go back to @Model.TrainingProviderName. You may want to tell them why you're rejecting it.

-
+ Are you sure you want to reject this job advert? + +
+

This job advert will go back to @Model.TrainingProviderName.

+
+

Rejection reason

+

@Model.RejectionReason

+
+
@@ -33,6 +37,6 @@ ViewBag.Title = "Are you sure you want to reject this job advert?"; }
- +
\ No newline at end of file diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml index 3b781599c7..fcee3a2063 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml @@ -507,19 +507,29 @@ Error: @Html.ValidationMessage("SubmitToEsfa") -
+
- +
- +
+
+ +
+ + + You have + 200 + characters remaining +
+
diff --git a/src/Employer/Employer.Web/wwwroot/css/application.css b/src/Employer/Employer.Web/wwwroot/css/application.css index 87ad83fa0e..a205e1b138 100644 --- a/src/Employer/Employer.Web/wwwroot/css/application.css +++ b/src/Employer/Employer.Web/wwwroot/css/application.css @@ -1417,4 +1417,144 @@ a[rel="external"]:hover:after { /*** govuk confirmation panel ***/ .govuk-panel--confirmation { background: #00703c; +} + +/* govuk notification banner */ + +.govuk-notification-banner { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + line-height: 1.25; + margin-bottom: 30px; + border: 5px solid #1d70b8; + background-color: #1d70b8; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner { + margin-bottom: 50px; + } +} + +.govuk-notification-banner__header { + padding: 2px 15px 5px; + border-bottom: 1px solid transparent; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__header { + padding: 2px 20px 5px; + } +} + +.govuk-notification-banner__title { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + line-height: 1.25; + margin: 0; + padding: 0; + color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__title { + font-size: 19px; + line-height: 1.35; + } +} + +.govuk-notification-banner__content { + color: #0b0c0c; + padding: 15px; + background-color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__content { + padding: 20px; + } +} + +.govuk-notification-banner__content > * { + max-width: 605px; +} + +.govuk-notification-banner__content>:last-child { + margin-bottom: 0; +} + +.govuk-notification-banner__heading { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + line-height: 1.1; + margin: 0 0 15px 0; + padding: 0; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__heading { + font-size: 24px; + line-height: 1.25; + } +} + +.govuk-notification-banner__link { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + color: #1d70b8; +} + +.govuk-notification-banner__link:link { + color: #1d70b8; +} + +.govuk-notification-banner__link:hover { + color: #003078; +} + +.govuk-notification-banner__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #fd0; + -webkit-box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + text-decoration: none; +} + +/* Additional govuk tag colours */ + +.govuk-tag--purple { + color: #3d2375; + background: #dbd5e9; +} + +.govuk-tag--red { + color: #942514; + background: #f6d7d2; +} + +.govuk-tag--blue { + color: #144e81; + background: #d2e2f1; +} + +.govuk-tag--green { + color: #005a30; + background: #cce2d8; +} + +.govuk-tag--orange { + color: #6e3619; + background: #fcd6c3; } \ No newline at end of file diff --git a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs index 227ad7ac94..0f41e6c359 100644 --- a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs +++ b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs @@ -1,15 +1,22 @@ -using Esfa.Recruit.Vacancies.Client.Domain.Entities; -using System; +using System; +using System.Collections.Generic; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo; +using Address = Esfa.Recruit.Vacancies.Client.Domain.Entities.Address; namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks { internal class VacancyOrchestratorTestData { + public const string AccountLegalEntityPublicHashedId123 = "ABC123"; + public const string AccountLegalEntityPublicHashedId456 = "ABC456"; + internal static Vacancy GetPart1CompleteVacancy() { return new Vacancy { EmployerAccountId = "EMPLOYER ACCOUNT ID", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId123, Id = Guid.Parse("84af954e-5baf-4942-897d-d00180a0839e"), Title = "has a value", NumberOfPositions = 1, @@ -17,7 +24,7 @@ internal static Vacancy GetPart1CompleteVacancy() ShortDescription = "has a value", ProgrammeId = "has a value", Wage = new Wage {Duration = 1, WageType = WageType.FixedWage }, - LegalEntityName = "legal name", + LegalEntityName = "LEGAL ENTITY NAME 123", EmployerNameOption = EmployerNameOption.RegisteredName, StartDate = DateTime.Now }; @@ -32,5 +39,50 @@ internal static VacancyUser GetVacancyUser() UserId = "scott" }; } + + internal static EmployerProfile GetEmployerProfile(string accountLegalEntityPublicHashedId123) + { + return new EmployerProfile + { + EmployerAccountId = "EMPLOYER ACCOUNT ID", + AccountLegalEntityPublicHashedId = accountLegalEntityPublicHashedId123 + }; + } + + internal static EmployerEditVacancyInfo GetEmployerEditVacancyInfo() + { + return new EmployerEditVacancyInfo + { + LegalEntities = new List + { + new LegalEntity + { + Name = "LEGAL ENTITY NAME 123", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId123, + Address = new Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo.Address + { + AddressLine1 = "this is a value", + AddressLine2 = "this is a value", + AddressLine3 = "this is a value", + AddressLine4 = "this is a value", + Postcode = "this is a value" + } + }, + new LegalEntity + { + Name = "LEGAL ENTITY NAME 456", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId456, + Address = new Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo.Address + { + AddressLine1 = "this is a value", + AddressLine2 = "this is a value", + AddressLine3 = "this is a value", + AddressLine4 = "this is a value", + Postcode = "this is a value" + } + } + } + }; + } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs new file mode 100644 index 0000000000..39e9f7398a --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs @@ -0,0 +1,141 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Dates; +using Esfa.Recruit.Shared.Web.Extensions; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class DatesOrchestratorTests + { + private DatesOrchestratorTestsFixture _fixture; + + public DatesOrchestratorTests() + { + _fixture = new DatesOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("31/12/2021", "01/01/2001", false, new string[] { FieldIdentifiers.ClosingDate }, new string[] { FieldIdentifiers.PossibleStartDate, FieldIdentifiers.DisabilityConfident})] + [InlineData("01/01/2001", "31/12/2021", false, new string[] { FieldIdentifiers.PossibleStartDate }, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.DisabilityConfident })] + [InlineData("01/01/2001", "01/01/2001", true, new string[] { FieldIdentifiers.DisabilityConfident }, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.PossibleStartDate })] + [InlineData("01/01/2001", "01/01/2001", false, new string[] { }, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.PossibleStartDate, FieldIdentifiers.DisabilityConfident })] + [InlineData("31/12/2021", "31/12/2021", true, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.PossibleStartDate, FieldIdentifiers.DisabilityConfident }, new string[] { })] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string closingDate, string startDate, bool isDisablityConfident, string[] setFieldIdentifers, string [] unsetFieldIdentifiers) + { + _fixture + .WithClosingDate("01/01/2001") + .WithStartDate("01/01/2001") + .WithDisabilityConfident(false) + .Setup(); + + var closingDateTime = DateTime.ParseExact(closingDate, "dd/MM/yyyy", CultureInfo.InvariantCulture); + var startDateTime = DateTime.ParseExact(startDate, "dd/MM/yyyy", CultureInfo.InvariantCulture); + + var datesEditModel = new DatesEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ClosingDay = closingDateTime.Day.ToString(), + ClosingMonth = closingDateTime.Month.ToString(), + ClosingYear = closingDateTime.Year.ToString(), + StartDay = startDateTime.Day.ToString(), + StartMonth = startDateTime.Month.ToString(), + StartYear = startDateTime.Year.ToString(), + IsDisabilityConfident = isDisablityConfident + }; + + await _fixture.PostDatesEditModelAsync(datesEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIdentifers, unsetFieldIdentifiers); + } + + public class DatesOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ClosingDate | VacancyRuleSet.StartDate | VacancyRuleSet.StartDateEndDate | VacancyRuleSet.TrainingExpiryDate; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public DatesOrchestrator Sut {get; private set;} + + public DatesOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public DatesOrchestratorTestsFixture WithClosingDate(string closingDate) + { + Vacancy.ClosingDate = closingDate.AsDateTimeUk()?.ToUniversalTime(); + return this; + } + + public DatesOrchestratorTestsFixture WithStartDate(string startDate) + { + Vacancy.StartDate = startDate.AsDateTimeUk()?.ToUniversalTime(); + return this; + } + + public DatesOrchestratorTestsFixture WithDisabilityConfident(bool isDisablityConfident) + { + Vacancy.DisabilityConfident = isDisablityConfident ? DisabilityConfident.Yes : DisabilityConfident.No; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new DatesOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(),Mock.Of(), Mock.Of()); + } + + public async Task PostDatesEditModelAsync(DatesEditModel model) + { + await Sut.PostDatesEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs new file mode 100644 index 0000000000..75bb42e784 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs @@ -0,0 +1,143 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Dates; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Duration; +using Esfa.Recruit.Shared.Web.Extensions; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class DurationOrchestratorTests + { + private DurationOrchestratorTestsFixture _fixture; + + public DurationOrchestratorTests() + { + _fixture = new DurationOrchestratorTestsFixture(); + } + + [Theory] + [InlineData(24, DurationUnit.Month, 37.0, "this is a value", new string[] { }, new string[] { FieldIdentifiers.ExpectedDuration, FieldIdentifiers.WorkingWeek })] + [InlineData(12, DurationUnit.Month, 37.0, "this is a value", new string[] { FieldIdentifiers.ExpectedDuration }, new string[] { FieldIdentifiers.WorkingWeek })] + [InlineData(24, DurationUnit.Year, 37.0, "this is a value", new string[] { FieldIdentifiers.ExpectedDuration }, new string[] { FieldIdentifiers.WorkingWeek })] + [InlineData(24, DurationUnit.Month, 35.0, "this is a value", new string[] { FieldIdentifiers.WorkingWeek }, new string[] { FieldIdentifiers.ExpectedDuration })] + [InlineData(24, DurationUnit.Month, 37.0, "this is a new value", new string[] { FieldIdentifiers.WorkingWeek }, new string[] { FieldIdentifiers.ExpectedDuration })] + [InlineData(1, DurationUnit.Year, 35.0, "this is a new value", new string[] { FieldIdentifiers.ExpectedDuration, FieldIdentifiers.WorkingWeek }, new string[] { })] + public async Task WhenUpdated_ShouldFlagFieldIndicators(int duration, DurationUnit durationUnit, decimal weeklyHours, string workingWeekDescription, string[] setFieldIdentifers, string [] unsetFieldIdentifiers) + { + _fixture + .WithDuration(24) + .WithDurationUnit(DurationUnit.Month) + .WithWeeklyHours(37) + .WithWorkingWeekDescription("this is a value") + .Setup(); + + var durationEditModel = new DurationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + Duration = duration.ToString(), + DurationUnit = durationUnit, + WeeklyHours = weeklyHours.ToString(), + WorkingWeekDescription = workingWeekDescription + }; + + await _fixture.PostDurationEditModelAsync(durationEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIdentifers, unsetFieldIdentifiers); + } + + public class DurationOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Duration | VacancyRuleSet.WorkingWeekDescription | VacancyRuleSet.WeeklyHours; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public DurationOrchestrator Sut {get; private set;} + + public DurationOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public DurationOrchestratorTestsFixture WithDuration(int duration) + { + Vacancy.Wage.Duration = duration; + return this; + } + + public DurationOrchestratorTestsFixture WithDurationUnit(DurationUnit durationUnit) + { + Vacancy.Wage.DurationUnit = durationUnit; + return this; + } + + public DurationOrchestratorTestsFixture WithWeeklyHours(decimal weeklyHours) + { + Vacancy.Wage.WeeklyHours = weeklyHours; + return this; + } + + public DurationOrchestratorTestsFixture WithWorkingWeekDescription(string workingWeekDescription) + { + Vacancy.Wage.WorkingWeekDescription = workingWeekDescription; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new DurationOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostDurationEditModelAsync(DurationEditModel model) + { + await Sut.PostDurationEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs new file mode 100644 index 0000000000..97ee8b8d5d --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs @@ -0,0 +1,241 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Models; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Duration; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Location; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Wage; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Models; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using Esfa.Recruit.Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; +using Address = Esfa.Recruit.Vacancies.Client.Domain.Entities.Address; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class LocationOrchestratorTests + { + private LocationOrchestratorTestsFixture _fixture; + + public LocationOrchestratorTests() + { + _fixture = new LocationOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("this is a value", "this is a value", "this is a value", "this is a value", "this is a value", false)] + [InlineData("this is a new value", "this is a value", "this is a value", "this is a value", "this is a value", true)] + [InlineData("this is a value", "this is a new value", "this is a value", "this is a value", "this is a value", true)] + [InlineData("this is a value", "this is a value", "this is a new value", "this is a value", "this is a value", true)] + [InlineData("this is a value", "this is a value", "this is a value", "this is a new value", "this is a value", true)] + [InlineData("this is a value", "this is a value", "this is a value", "this is a value", "this is a new value", true)] + [InlineData("this is a new value", "this is a new value", "this is a new value", "this is a new value", "this is a new value", true)] + public async Task WhenAddressUpdated_ShouldFlagFieldIndicators(string addressLine1, string addressLine2, string addressLine3, string addressLine4, string postcode, bool fieldIndicatorSet) + { + _fixture + .WithAddressLine1("this is a value") + .WithAddressLine2("this is a value") + .WithAddresLine3("this is a value") + .WithAddresLine4("this is a value") + .WithPostcode("this is a value") + .Setup(); + + var locationEditModel = new LocationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + AddressLine1 = addressLine1, + AddressLine2 = addressLine2, + AddressLine3 = addressLine3, + AddressLine4 = addressLine4, + Postcode = postcode, + SelectedLocation = LocationViewModel.UseOtherLocationConst + }; + + await _fixture.PostLocationEditModelAsync(locationEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerAddress, fieldIndicatorSet); + } + + [Fact] + public async Task WhenEmployerLegalEntityUpdated_ShouldFlagEmployerNameFieldIndicator() + { + _fixture + .WithEmployerNameOption(EmployerNameOption.RegisteredName) + .Setup(); + + var locationEditModel = new LocationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + SelectedLocation = LocationViewModel.UseOtherLocationConst + }; + + await _fixture.PostLocationEditModelAsync(locationEditModel, new VacancyEmployerInfoModel + { + EmployerIdentityOption = EmployerIdentityOption.RegisteredName, + AccountLegalEntityPublicHashedId = VacancyOrchestratorTestData.AccountLegalEntityPublicHashedId456 + }); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerName, true); + } + + [Theory] + [InlineData(EmployerNameOption.RegisteredName, EmployerIdentityOption.ExistingTradingName, null, true)] + [InlineData(EmployerNameOption.RegisteredName, EmployerIdentityOption.NewTradingName, "this is a new value", true)] + [InlineData(EmployerNameOption.TradingName, EmployerIdentityOption.NewTradingName, "this is a new value", true)] + [InlineData(EmployerNameOption.TradingName, EmployerIdentityOption.ExistingTradingName, null, false)] + [InlineData(EmployerNameOption.RegisteredName, EmployerIdentityOption.RegisteredName, null, false)] + public async Task WhenEmployerNameOptionUpdated_ShouldFlagEmployerNameFieldIndicator(EmployerNameOption employerNameOption, EmployerIdentityOption employerIdentityOption, string newTradingName, bool shouldFlagIndicator) + { + _fixture + .WithEmployerNameOption(employerNameOption) + .WithTradingName(employerNameOption == EmployerNameOption.TradingName + ? "this is a value" + : null) + .Setup(); + + var locationEditModel = new LocationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + SelectedLocation = LocationViewModel.UseOtherLocationConst + }; + + await _fixture.PostLocationEditModelAsync(locationEditModel, new VacancyEmployerInfoModel + { + EmployerIdentityOption = employerIdentityOption, + NewTradingName = newTradingName, + AccountLegalEntityPublicHashedId = _fixture.Vacancy.AccountLegalEntityPublicHashedId + }); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerName, shouldFlagIndicator); + } + + public class LocationOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerAddress; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public EmployerEditVacancyInfo EmployerEditVacancyInfo { get; } + public EmployerProfile VacancyEmployerProfile { get; } + public EmployerProfile AlternateEmployerProfile { get; } + public LocationOrchestrator Sut {get; private set;} + + public LocationOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + VacancyEmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(Vacancy.AccountLegalEntityPublicHashedId); + AlternateEmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(VacancyOrchestratorTestData.AccountLegalEntityPublicHashedId456); + EmployerEditVacancyInfo = VacancyOrchestratorTestData.GetEmployerEditVacancyInfo(); + } + + public LocationOrchestratorTestsFixture WithAddressLine1(string addressLine1) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine1 = addressLine1; + return this; + } + + public LocationOrchestratorTestsFixture WithAddressLine2(string addressLine2) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine2 = addressLine2; + return this; + } + + public LocationOrchestratorTestsFixture WithAddresLine3(string addressLine3) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine3 = addressLine3; + return this; + } + + public LocationOrchestratorTestsFixture WithAddresLine4(string addressLine4) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine4 = addressLine4; + return this; + } + + public LocationOrchestratorTestsFixture WithPostcode(string postcode) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.Postcode = postcode; + return this; + } + + public LocationOrchestratorTestsFixture WithEmployerNameOption(EmployerNameOption employerNameOption) + { + Vacancy.EmployerNameOption = employerNameOption; + return this; + } + + public LocationOrchestratorTestsFixture WithTradingName(string tradingName) + { + VacancyEmployerProfile.TradingName = tradingName; + return this; + } + + public void Setup() + { + MockClient.Setup(x => x.GetEditVacancyInfoAsync(Vacancy.EmployerAccountId)).ReturnsAsync(EmployerEditVacancyInfo); + + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, Vacancy.AccountLegalEntityPublicHashedId)).ReturnsAsync(VacancyEmployerProfile); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, AlternateEmployerProfile.AccountLegalEntityPublicHashedId)).ReturnsAsync(AlternateEmployerProfile); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new LocationOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostLocationEditModelAsync(LocationEditModel model, VacancyEmployerInfoModel vacancyEmployerInfoModel = null) + { + await Sut.PostLocationEditModelAsync(model, + vacancyEmployerInfoModel ?? new VacancyEmployerInfoModel + { + VacancyId = Vacancy.Id + }, + User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs new file mode 100644 index 0000000000..038f7f6b06 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs @@ -0,0 +1,97 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.NumberOfPositions; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class NumberofPositionsOrchestratorTests + { + private NumberofPositionsOrchestratorTestsFixture _fixture; + + public NumberofPositionsOrchestratorTests() + { + _fixture = new NumberofPositionsOrchestratorTestsFixture(); + } + + [Theory] + [InlineData(1, false)] + [InlineData(2, true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(int numberOfPositions, bool fieldIndicatorSet) + { + _fixture + .WithNumberOfPositions(1) + .Setup(); + + var numberOfPositionsEditModel = new NumberOfPositionsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + NumberOfPositions = numberOfPositions.ToString() + }; + + await _fixture.PostNumberOfPositionsEditModelAsync(numberOfPositionsEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.NumberOfPositions, fieldIndicatorSet); + } + + public class NumberofPositionsOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.NumberOfPositions; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public NumberOfPositionsOrchestrator Sut {get; private set;} + + public NumberofPositionsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public NumberofPositionsOrchestratorTestsFixture WithNumberOfPositions(int numberOfPositions) + { + Vacancy.NumberOfPositions = numberOfPositions; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new NumberOfPositionsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostNumberOfPositionsEditModelAsync(NumberOfPositionsEditModel model) + { + await Sut.PostNumberOfPositionsEditModelAsync(model, User); + } + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs new file mode 100644 index 0000000000..0c2a3d1cdd --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs @@ -0,0 +1,99 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Title; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Services.TrainingProvider; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class TitleOrchestratorTests + { + private TitleOrchestratorTestsFixture _fixture; + + public TitleOrchestratorTests() + { + _fixture = new TitleOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("this is a value", false)] + [InlineData("this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string title, bool fieldIndicatorSet) + { + _fixture + .WithTitle("this is a value") + .Setup(); + + var titleEditModel = new TitleEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + Title = title + }; + + await _fixture.PostTitleEditModelAsync(titleEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Title, fieldIndicatorSet); + } + + public class TitleOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Title; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public TitleOrchestrator Sut {get; private set;} + + public TitleOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public TitleOrchestratorTestsFixture WithTitle(string title) + { + Vacancy.Title = title; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new TitleOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(), Mock.Of()); + } + + public async Task PostTitleEditModelAsync(TitleEditModel model) + { + await Sut.PostTitleEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs new file mode 100644 index 0000000000..6c60e54a78 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs @@ -0,0 +1,101 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Title; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Training; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Services.TrainingProvider; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class TrainingOrchestratorTests + { + private TrainingOrchestratorTestsFixture _fixture; + + public TrainingOrchestratorTests() + { + _fixture = new TrainingOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("this is a value", false)] + [InlineData("this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string programmeId, bool fieldIndicatorSet) + { + _fixture + .WithProgrammeId("this is a value") + .Setup(); + + var confirmTrainingEditModel = new ConfirmTrainingEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ProgrammeId = programmeId + }; + + await _fixture.PostConfirmTrainingEditModelAsync(confirmTrainingEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.TrainingLevel, fieldIndicatorSet); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Training, fieldIndicatorSet); + } + + public class TrainingOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProgramme; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public TrainingOrchestrator Sut {get; private set;} + + public TrainingOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public TrainingOrchestratorTestsFixture WithProgrammeId(string programmeId) + { + Vacancy.ProgrammeId = programmeId; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new TrainingOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostConfirmTrainingEditModelAsync(ConfirmTrainingEditModel model) + { + await Sut.PostConfirmTrainingEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs index ff888ff7c5..03db0c04cd 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs @@ -1,8 +1,13 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Models; using Esfa.Recruit.Employer.Web.Orchestrators.Part1; using Esfa.Recruit.Employer.Web.ViewModels.Part1.TrainingProvider; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; using Esfa.Recruit.Vacancies.Client.Application.Validation; @@ -17,158 +22,264 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 { public class TrainingProviderOrchestratorTests - { - private const string EmployerAccountId = "EMPLOYERACCOUNTID"; - private readonly Guid VacancyId = Guid.Parse("0a8e54c9-e284-4023-b688-14b9d841fcd7"); - + { [Fact] public async Task PostSelectTrainingProviderAsync_WhenNotChoosingThenRemoveExistingTrainingProvider() { - var vacancy = new Vacancy - { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" - }; - - var orch = GetTrainingProviderOrchestrator(vacancy); + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var m = new SelectTrainingProviderEditModel + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { - IsTrainingProviderSelected = false, - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, + IsTrainingProviderSelected = false }; - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); - vacancy.TrainingProvider.Should().BeNull(); - result.Data.FoundTrainingProviderUkprn.Should().BeNull(); + fixture.VerifyTrainingProviderNotSet(); + fixture.VerifyNotFoundTrainingProviderUkprn(result); } [Theory] [InlineData("This search won't match a single provider")] - [InlineData("88888")] //will match multiple providers + [InlineData("88888")] // will match multiple providers public async Task PostSelectTrainingProviderAsync_TrainingProviderSearch_WhenNoSingleProviderFoundShouldNotReturnFoundProvider(string trainingProviderSearch) { - var vacancy = new Vacancy - { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" - }; + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var orch = GetTrainingProviderOrchestrator(vacancy); - - var m = new SelectTrainingProviderEditModel + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, IsTrainingProviderSelected = true, SelectionType = TrainingProviderSelectionType.TrainingProviderSearch, - TrainingProviderSearch = trainingProviderSearch, - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + TrainingProviderSearch = trainingProviderSearch }; - - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); - result.Data.FoundTrainingProviderUkprn.Should().BeNull(); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); + + fixture.VerifyNotFoundTrainingProviderUkprn(result); } [Fact] public async Task PostSelectTrainingProviderAsync_TrainingProviderSearch_WhenSingleProviderFoundShouldReturnFoundProvider() { - var vacancy = new Vacancy - { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" - }; + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var orch = GetTrainingProviderOrchestrator(vacancy); - - var m = new SelectTrainingProviderEditModel + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, IsTrainingProviderSelected = true, SelectionType = TrainingProviderSelectionType.TrainingProviderSearch, - TrainingProviderSearch = "MR EGG 88888888", - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + TrainingProviderSearch = "FIRST TRAINING PROVIDER 88888888", }; - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); - result.Data.FoundTrainingProviderUkprn.Should().Be(88888888); + fixture.VerifyFoundTrainingProviderUkprn(result, fixture.TrainingProviderOne.Ukprn.Value); } [Fact] public async Task PostSelectTrainingProviderAsync_UKPRN_WhenSingleProviderFoundShouldReturnFoundProvider() { - var vacancy = new Vacancy + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); + + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, + IsTrainingProviderSelected = true, + SelectionType = TrainingProviderSelectionType.Ukprn, + Ukprn = fixture.TrainingProviderOne.Ukprn.ToString() }; - var orch = GetTrainingProviderOrchestrator(vacancy); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); + + fixture.VerifyFoundTrainingProviderUkprn(result, fixture.TrainingProviderOne.Ukprn.Value); + } + + [Theory] + [InlineData(88888888)] + [InlineData(88888889)] + public async Task PostConfirmEditModelAsync_ShouldFlagProviderFieldIndicator(long ukprn) + { + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var m = new SelectTrainingProviderEditModel + var confirmTrainingProviderEditModel = new ConfirmTrainingProviderEditModel { - IsTrainingProviderSelected = true, - SelectionType = TrainingProviderSelectionType.Ukprn, - Ukprn = "88888888", - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, + Ukprn = ukprn.ToString() }; - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); + await fixture.PostConfirmEditModelAsync(confirmTrainingProviderEditModel); - result.Data.FoundTrainingProviderUkprn.Should().Be(88888888); + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Provider, true); } - private TrainingProviderOrchestrator GetTrainingProviderOrchestrator(Vacancy vacancy) + public class TrainingProviderOrchestratorTestsFixture { - var mockClient = new Mock(); + private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProvider; + public TrainingProvider TrainingProviderOne { get; set; } + public TrainingProvider TrainingProviderTwo { get; set; } + public TrainingProviderSummary TrainingProviderSummaryOne { get; set; } + public TrainingProviderSummary TrainingProviderSummaryTwo { get; set; } + public VacancyUser User { get; } + public Vacancy Vacancy { get; private set; } + public TrainingProviderOrchestrator Sut { get; private set; } + + public const string EmployerAccountId = "EmployerAccountId"; + public readonly Guid VacancyId = Guid.NewGuid(); + + public TrainingProviderOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + MockTrainingProviderSummaryProvider = new Mock(); + MockTrainingProviderService = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + + TrainingProviderOne = new TrainingProvider { Ukprn = 88888888 }; + TrainingProviderTwo = new TrainingProvider { Ukprn = 88888889 }; + TrainingProviderSummaryOne = new TrainingProviderSummary { ProviderName = "First Training Provider", Ukprn = TrainingProviderOne.Ukprn.Value }; + TrainingProviderSummaryTwo = new TrainingProviderSummary { ProviderName = "Second Training Provider", Ukprn = TrainingProviderTwo.Ukprn.Value }; + } + + public TrainingProviderOrchestratorTestsFixture WithVacacny(Vacancy vacancy) + { + Vacancy = vacancy; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + MockTrainingProviderSummaryProvider.Setup(p => p.FindAllAsync()).ReturnsAsync(new List + { + TrainingProviderSummaryOne, + TrainingProviderSummaryTwo + }); - var mockTrainingProviderService = new Mock(); - mockTrainingProviderService.Setup(t => t.GetProviderAsync(88888888)) - .ReturnsAsync(new TrainingProvider {Ukprn = 88888888}); + MockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(TrainingProviderSummaryOne.Ukprn)) + .ReturnsAsync(TrainingProviderSummaryOne); - var mockRecruitClient = new Mock(); - mockRecruitClient.Setup(c => c.GetVacancyAsync(VacancyId)).ReturnsAsync(vacancy); + MockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(TrainingProviderSummaryTwo.Ukprn)) + .ReturnsAsync(TrainingProviderSummaryTwo); - var mockTrainingProviderSummaryProvider = new Mock(); + MockTrainingProviderService.Setup(t => t.GetProviderAsync(TrainingProviderOne.Ukprn.Value)) + .ReturnsAsync(TrainingProviderOne); - var mrEggTrainingProvider = new TrainingProviderSummary { ProviderName = "MR EGG", Ukprn = 88888888 }; - var mrsEggTrainingProvider = new TrainingProviderSummary { ProviderName = "MRS EGG", Ukprn = 88888889 }; + MockTrainingProviderService.Setup(t => t.GetProviderAsync(TrainingProviderTwo.Ukprn.Value)) + .ReturnsAsync(TrainingProviderTwo); - mockTrainingProviderSummaryProvider.Setup(p => p.FindAllAsync()).ReturnsAsync(new List + Sut = new TrainingProviderOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(), MockTrainingProviderSummaryProvider.Object, MockTrainingProviderService.Object); + } + + public async Task> PostSelectTrainingProviderAsync(SelectTrainingProviderEditModel model) { - mrEggTrainingProvider, - mrsEggTrainingProvider - }); + return await Sut.PostSelectTrainingProviderAsync(model, User); + } - mockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(88888888)) - .ReturnsAsync(mrEggTrainingProvider); + public async Task PostConfirmEditModelAsync(ConfirmTrainingProviderEditModel model) + { + return await Sut.PostConfirmEditModelAsync(model, User); + } - mockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(88888889)) - .ReturnsAsync(mrsEggTrainingProvider); + public void VerifyFoundTrainingProviderUkprn(OrchestratorResponse result, long value) + { + result.Data.FoundTrainingProviderUkprn.Should().Be(value); + } - mockRecruitClient.Setup(c => c.Validate(It.IsAny(), VacancyRuleSet.TrainingProvider)) - .Returns(new EntityValidationResult()); + public void VerifyNotFoundTrainingProviderUkprn(OrchestratorResponse result) + { + result.Data.FoundTrainingProviderUkprn.Should().BeNull(); + } - var mockLog = new Mock>(); - var mockReview = new Mock(); + public void VerifyTrainingProviderNotSet() + { + Vacancy.TrainingProvider.Should().BeNull(); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } - return new TrainingProviderOrchestrator(mockClient.Object, mockRecruitClient.Object, mockLog.Object, mockReview.Object, mockTrainingProviderSummaryProvider.Object, mockTrainingProviderService.Object); + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + public Mock MockTrainingProviderSummaryProvider { get; set; } + public Mock MockTrainingProviderService { get; set; } } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs new file mode 100644 index 0000000000..e9e12c553f --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs @@ -0,0 +1,131 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Duration; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Wage; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class WageOrchestratorTests + { + private WageOrchestratorTestsFixture _fixture; + + public WageOrchestratorTests() + { + _fixture = new WageOrchestratorTestsFixture(); + } + + [Theory] + [InlineData(WageType.FixedWage, 10000, "this is a value", false)] + [InlineData(WageType.NationalMinimumWage, 10000, "this is a value", true)] + [InlineData(WageType.FixedWage, 11000, "this is a value", true)] + [InlineData(WageType.FixedWage, 10000, "this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(WageType wageType, decimal fixedWageYearlyAmmount, string wageAddtionalInformation, bool fieldIndicatorSet) + { + _fixture + .WithWageType(WageType.FixedWage) + .WithFixedWageYearlyAmount(10000) + .WithWageAdditionalInformation("this is a value") + .Setup(); + + var wageEditModel = new WageEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + WageType = wageType, + FixedWageYearlyAmount = fixedWageYearlyAmmount.ToString(), + WageAdditionalInformation = wageAddtionalInformation + }; + + await _fixture.PostWageEditModelAsync(wageEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Wage, fieldIndicatorSet); + } + + public class WageOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Wage | VacancyRuleSet.MinimumWage; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public WageOrchestrator Sut {get; private set;} + + public WageOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public WageOrchestratorTestsFixture WithWageType(WageType wageType) + { + Vacancy.Wage.WageType = wageType; + return this; + } + + public WageOrchestratorTestsFixture WithFixedWageYearlyAmount(decimal fixedWageYearlyAmmount) + { + Vacancy.Wage.FixedWageYearlyAmount = fixedWageYearlyAmmount; + return this; + } + + public WageOrchestratorTestsFixture WithWageAdditionalInformation(string wageAdditionalInformation) + { + Vacancy.Wage.WageAdditionalInformation = wageAdditionalInformation; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new WageOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(), Mock.Of()); + } + + public async Task PostWageEditModelAsync(WageEditModel model) + { + await Sut.PostWageEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs new file mode 100644 index 0000000000..80a79ea1a7 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs @@ -0,0 +1,122 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class AboutEmployerOrchestratorTests + { + private AboutEmployerOrchestratorTestsFixture _fixture; + + public AboutEmployerOrchestratorTests() + { + _fixture = new AboutEmployerOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("has a new value", "has a value", new string[] { FieldIdentifiers.EmployerDescription }, new string[] { FieldIdentifiers.EmployerWebsiteUrl})] + [InlineData("has a value", "has a new value", new string[] { FieldIdentifiers.EmployerWebsiteUrl }, new string[] { FieldIdentifiers.EmployerDescription })] + [InlineData("has a new value", "has a new value", new string[] { FieldIdentifiers.EmployerDescription, FieldIdentifiers.EmployerWebsiteUrl }, new string[] { })] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string employerDescription, string employerWebSiteUrl, string[] setFieldIdentifers, string [] unsetFieldIdentifiers) + { + _fixture + .WithEmployerDescription("has a value") + .WithEmployerWebsiteUrl("has a value") + .Setup(); + + var aboutEmployerEditModel = new AboutEmployerEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerDescription = employerDescription, + EmployerWebsiteUrl = employerWebSiteUrl + }; + + await _fixture.PostAboutEmployerEditModelAsync(aboutEmployerEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIdentifers, unsetFieldIdentifiers); + } + + public class AboutEmployerOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerDescription | VacancyRuleSet.EmployerWebsiteUrl; + public VacancyUser User { get; } + public EmployerProfile EmployerProfile { get; } + public Vacancy Vacancy { get; } + public AboutEmployerOrchestrator Sut {get; private set;} + + public AboutEmployerOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + EmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(Vacancy.AccountLegalEntityPublicHashedId); + } + + public AboutEmployerOrchestratorTestsFixture WithEmployerDescription(string employerDescription) + { + Vacancy.EmployerDescription = employerDescription; + return this; + } + + public AboutEmployerOrchestratorTestsFixture WithEmployerWebsiteUrl(string employerWebsiteUrl) + { + Vacancy.EmployerWebsiteUrl = employerWebsiteUrl; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, Vacancy.AccountLegalEntityPublicHashedId)).ReturnsAsync(EmployerProfile); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new AboutEmployerOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostAboutEmployerEditModelAsync(AboutEmployerEditModel model) + { + await Sut.PostAboutEmployerEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs index f56934f819..6a9f661e1c 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs @@ -1,7 +1,11 @@ -using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; using Esfa.Recruit.Employer.Web.Configuration; using Esfa.Recruit.Employer.Web.Orchestrators.Part2; using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; @@ -16,73 +20,235 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 { public class ApplicationProcessOrchestratorTests { - private readonly Mock _mockClient; - private readonly Mock _mockVacancyClient; + private ApplicationProcessOrchestratorTestsFixture _fixture; public ApplicationProcessOrchestratorTests() { - _mockClient = new Mock(); - _mockVacancyClient = new Mock(); + _fixture = new ApplicationProcessOrchestratorTestsFixture(); } [Fact] - public void WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationUrlAsNull() + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldCallUpdateDraftVacancy() { - var user = VacancyOrchestratorTestData.GetVacancyUser(); - var vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(vacancy.Id)) - .ReturnsAsync(vacancy); - _mockVacancyClient.Setup(x => x.Validate(vacancy, VacancyRuleSet.ApplicationMethod)) - .Returns(new EntityValidationResult()); - _mockVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), user)); + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, + ApplicationInstructions = "has a value", + }; + + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); - var sut = new ApplicationProcessOrchestrator(_mockClient.Object, _mockVacancyClient.Object, Options.Create(new ExternalLinksConfiguration()), Mock.Of>(), Mock.Of()); + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationUrlAsNull() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); var applicationProcessEditModel = new ApplicationProcessEditModel { - EmployerAccountId = vacancy.EmployerAccountId, - VacancyId = vacancy.Id, + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, - ApplicationUrl = "www.google.com" + ApplicationUrl = "has a value" }; - var result = sut.PostApplicationProcessEditModelAsync(applicationProcessEditModel, user); + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); - vacancy.ApplicationMethod.HasValue.Should().BeTrue(); - vacancy.ApplicationMethod.Value.Should().Be(ApplicationMethod.ThroughFindAnApprenticeship); - vacancy.ApplicationUrl.Should().BeNull(); - _mockVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(vacancy, user), Times.Once); + _fixture.VerifyApplicationMethod(ApplicationMethod.ThroughFindAnApprenticeship); + _fixture.VerifyOverwriteApplicationUrlAsNull(); } [Fact] - public void WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationInstructionsAsNull() + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationInstructionsAsNull() { - var user = VacancyOrchestratorTestData.GetVacancyUser(); - var vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(vacancy.Id)) - .ReturnsAsync(vacancy); - _mockVacancyClient.Setup(x => x.Validate(vacancy, VacancyRuleSet.ApplicationMethod)) - .Returns(new EntityValidationResult()); - _mockVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), user)); + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, + ApplicationInstructions = "has a value", + }; - var sut = new ApplicationProcessOrchestrator(_mockClient.Object, _mockVacancyClient.Object, Options.Create(new ExternalLinksConfiguration()), Mock.Of>(), Mock.Of()); + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyApplicationMethod(ApplicationMethod.ThroughFindAnApprenticeship); + _fixture.VerifyOverwriteApplicationInstructionsAsNull(); + } + + [Fact] + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldFlagAllApplicationFieldIndicators() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); var applicationProcessEditModel = new ApplicationProcessEditModel { - EmployerAccountId = vacancy.EmployerAccountId, - VacancyId = vacancy.Id, + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, - ApplicationInstructions = "just do it" + ApplicationInstructions = "has a value", + ApplicationUrl = "has a value" + }; + + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationMethod, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationInstructions, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationUrl, true); + } + + [Fact] + public async Task WhenApplicationInstructionsIsUpdated_ShouldFlagApplicationInstructionsFieldIndicator() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); + + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughExternalApplicationSite, + ApplicationInstructions = "has a new value", + ApplicationUrl = "has a value" }; - var result = sut.PostApplicationProcessEditModelAsync(applicationProcessEditModel, user); + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationMethod, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationInstructions, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationUrl, false); + } + + [Fact] + public async Task WhenApplicationUrlIsUpdated_ShouldFlagApplicationInstructionsFieldIndicator() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); + + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughExternalApplicationSite, + ApplicationInstructions = "has a value", + ApplicationUrl = "has a new value" + }; + + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationMethod, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationInstructions, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationUrl, true); + } + + public class ApplicationProcessOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ApplicationMethod; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public ApplicationProcessOrchestrator Sut { get; private set; } + + public ApplicationProcessOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public ApplicationProcessOrchestratorTestsFixture WithApplicationMethod(ApplicationMethod applicationMethod) + { + Vacancy.ApplicationMethod = applicationMethod; + return this; + } + + public ApplicationProcessOrchestratorTestsFixture WithApplicationInstructions(string applicationInstructions) + { + Vacancy.ApplicationInstructions = applicationInstructions; + return this; + } + + public ApplicationProcessOrchestratorTestsFixture WithApplicationUrl(string applicationUrl) + { + Vacancy.ApplicationUrl = applicationUrl; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new ApplicationProcessOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Options.Create(new ExternalLinksConfiguration()), Mock.Of>(), Mock.Of()); + } + + public async Task PostApplicationProcessEditModelAsync(ApplicationProcessEditModel model) + { + await Sut.PostApplicationProcessEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyApplicationMethod(ApplicationMethod applicationMethod) + { + Vacancy.ApplicationMethod.HasValue.Should().BeTrue(); + Vacancy.ApplicationMethod.Value.Should().Be(applicationMethod); + } + + public void VerifyOverwriteApplicationInstructionsAsNull() + { + Vacancy.ApplicationInstructions.Should().BeNull(); + } + + public void VerifyOverwriteApplicationUrlAsNull() + { + Vacancy.ApplicationUrl.Should().BeNull(); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } - vacancy.ApplicationMethod.HasValue.Should().BeTrue(); - vacancy.ApplicationMethod.Value.Should().Be(ApplicationMethod.ThroughFindAnApprenticeship); - vacancy.ApplicationInstructions.Should().BeNull(); - _mockVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(vacancy, user), Times.Once); + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs new file mode 100644 index 0000000000..ca8b3d89f0 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs @@ -0,0 +1,119 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class ConsiderationsOrchestratorTests + { + private ConsiderationsOrchestratorTestsFixture _fixture; + + public ConsiderationsOrchestratorTests() + { + _fixture = new ConsiderationsOrchestratorTestsFixture(); + } + + [Fact] + public async Task WhenUpdated__ShouldCallUpdateDraftVacancy() + { + _fixture + .WithThingsToConsider("has a value") + .Setup(); + + var thingsToConsiderEditModel = new ConsiderationsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ThingsToConsider = "has a new value" + }; + + await _fixture.PostConsiderationsEditModelAsync(thingsToConsiderEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenThingsToConsiderIsUpdated_ShouldFlagThingsToConsiderFieldIndicator() + { + _fixture + .WithThingsToConsider("has a value") + .Setup(); + + var thingsToConsiderEditModel = new ConsiderationsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ThingsToConsider = "has a new value" + }; + + await _fixture.PostConsiderationsEditModelAsync(thingsToConsiderEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ThingsToConsider, true); + } + + public class ConsiderationsOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ThingsToConsider; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public ConsiderationsOrchestrator Sut {get; private set;} + + public ConsiderationsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public ConsiderationsOrchestratorTestsFixture WithThingsToConsider(string thingsToConsider) + { + Vacancy.ThingsToConsider = thingsToConsider; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new ConsiderationsOrchestrator(Mock.Of>(), MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of()); + } + + public async Task PostConsiderationsEditModelAsync(ConsiderationsEditModel model) + { + await Sut.PostConsiderationsEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs new file mode 100644 index 0000000000..4a0e38c96f --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs @@ -0,0 +1,156 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class EmployerContactDetailsOrchestratorTests + { + private EmployerContactDetailsOrchestratorTestsFixture _fixture; + + public EmployerContactDetailsOrchestratorTests() + { + _fixture = new EmployerContactDetailsOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value")] + [InlineData("has a value", "has a new value", "has a value")] + [InlineData("has a value", "has a value", "has a new value")] + [InlineData("has a new value", "has a new value", "has a new value")] + public async Task WhenEmployerContactNameIsUpdated__ShouldCallUpdateDraftVacancy(string employerContactName, string employerContactEmail, string employerContactPhone) + { + _fixture + .WithEmployerContactName("has a value") + .WithEmployerContactEmail("has a value") + .WithEmployerContactPhone("has a value") + .Setup(); + + var employerContactDetailsEditModel = new EmployerContactDetailsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerContactName = employerContactName, + EmployerContactEmail = employerContactEmail, + EmployerContactPhone = employerContactPhone + }; + + await _fixture.PostEmployerContactDetailsEditModelAsync(employerContactDetailsEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value")] + [InlineData("has a value", "has a new value", "has a value")] + [InlineData("has a value", "has a value", "has a new value")] + [InlineData("has a new value", "has a new value", "has a new value")] + public async Task WhenEmployerContactNameIsUpdated_ShouldFlagEmployerContactFieldIndicator(string employerContactName, string employerContactEmail, string employerContactPhone) + { + _fixture + .WithEmployerContactName("has a value") + .WithEmployerContactEmail("has a value") + .WithEmployerContactPhone("has a value") + .Setup(); + + var employerContactDetailsEditModel = new EmployerContactDetailsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerContactName = employerContactName, + EmployerContactEmail = employerContactEmail, + EmployerContactPhone = employerContactPhone + }; + + await _fixture.PostEmployerContactDetailsEditModelAsync(employerContactDetailsEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerContact, true); + } + + public class EmployerContactDetailsOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerContactDetails; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public EmployerContactDetailsOrchestrator Sut {get; private set;} + + public EmployerContactDetailsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public EmployerContactDetailsOrchestratorTestsFixture WithEmployerContactName(string employerContactName) + { + if (Vacancy.EmployerContact == null) + Vacancy.EmployerContact = new ContactDetail(); + + Vacancy.EmployerContact.Name = employerContactName; + return this; + } + + public EmployerContactDetailsOrchestratorTestsFixture WithEmployerContactEmail(string employerContactEmail) + { + if (Vacancy.EmployerContact == null) + Vacancy.EmployerContact = new ContactDetail(); + + Vacancy.EmployerContact.Email = employerContactEmail; + return this; + } + + public EmployerContactDetailsOrchestratorTestsFixture WithEmployerContactPhone(string employerContactPhone) + { + if (Vacancy.EmployerContact == null) + Vacancy.EmployerContact = new ContactDetail(); + + Vacancy.EmployerContact.Phone = employerContactPhone; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new EmployerContactDetailsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostEmployerContactDetailsEditModelAsync(EmployerContactDetailsEditModel model) + { + await Sut.PostEmployerContactDetailsEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs new file mode 100644 index 0000000000..67da323bc5 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs @@ -0,0 +1,381 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.RouteModel; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Shared.Web.ViewModels.Qualifications; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Newtonsoft.Json; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class QualificationsOrchestratorTests + { + public QualificationsOrchestratorTests() + { + } + + [Fact] + public async Task WhenQualificationIsAdded_ShouldAddQualificationToDraftVacancy() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "A", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Essential + }; + + await fixture.PostQualificationEditModelForAddAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification)); + + fixture.VerifyAddQualificationToDraftVacancy(2, qualification); + } + + [Fact] + public async Task WhenQualificationIsAdded_ShouldCallUpdateDraftVacancyAsync() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "A", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Essential + }; + + await fixture.PostQualificationEditModelForAddAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification)); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenQualificationIsAdded_ShouldFlagQualificationsFieldIndicator() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "A", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Essential + }; + + await fixture.PostQualificationEditModelForAddAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification)); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Qualifications, true); + } + + [Fact] + public async Task WhenQualificationIsUpdated_ShouldUpdateQualificationForDraftVacancy() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.PostQualificationEditModelForEditAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification), + index: 1); + + fixture.VerifyUpdateQualificationForDraftVacancy(qualification); + } + + [Fact] + public async Task WhenQualificationIsUpdated_ShouldCallUpdateDraftVacancyAsync() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.PostQualificationEditModelForEditAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification), + index: 1); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenQualificationIsUpdated_ShouldFlagQualificationsFieldIndicator() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.PostQualificationEditModelForEditAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification), + index: 1); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Qualifications, true); + } + + [Fact] + public async Task WhenQualificationIsDeleted_ShouldRemoveQualificationFromDraftVacancy() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.DeleteQualificationAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + index: 1); + + fixture.VerifyRemoveQualificationFromDraftVacancy(qualification); + } + + [Fact] + public async Task WhenQualificationIsDeleted_ShouldCallUpdateDraftVacancyAsync() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + await fixture.DeleteQualificationAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + index: 1); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenQualificationIsDeleted_ShouldFlagQualificationsFieldIndicator() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + await fixture.DeleteQualificationAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + index: 1); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Qualifications, true); + } + + private QualificationEditModel FromQualification(Qualification qualification) + { + return new QualificationEditModel + { + Subject = qualification.Subject, + Grade = qualification.Grade, + QualificationType = qualification.QualificationType, + Weighting = qualification.Weighting + }; + } + + public class QualificationsOrchestratorTestsFixture + { + public VacancyUser User { get; } + public Vacancy Vacancy { get; private set; } + public QualificationsOrchestrator Sut {get; private set;} + + public QualificationsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public QualificationsOrchestratorTestsFixture WithQualfication(string subject, string grade, string qualificationType, QualificationWeighting weighting) + { + if ((Vacancy.Qualifications == null)) + Vacancy.Qualifications = new List(); + + Vacancy.Qualifications.Add(new Qualification + { + Subject = subject, + Grade = grade, + QualificationType = qualificationType, + Weighting = weighting + }); + + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetCandidateQualificationsAsync()).ReturnsAsync(new List() { "GCSE", "A-LEVEL" }); + MockRecruitVacancyClient.Setup(x => x.ValidateQualification(It.IsAny())).Returns(new EntityValidationResult()); + + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)) + .Callback((vacancy, user) => { Vacancy = vacancy; }) + .Returns(Task.FromResult(0)); + + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new QualificationsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostQualificationEditModelForAddAsync(VacancyRouteModel vacancyRouteModel, QualificationEditModel model) + { + await Sut.PostQualificationEditModelForAddAsync(vacancyRouteModel, model, User); + } + + public async Task PostQualificationEditModelForEditAsync(VacancyRouteModel vacancyRouteModel, QualificationEditModel model, int index) + { + await Sut.PostQualificationEditModelForEditAsync(vacancyRouteModel, model, User, index); + } + + public async Task DeleteQualificationAsync(VacancyRouteModel vacancyRouteModel, int index) + { + await Sut.DeleteQualificationAsync(vacancyRouteModel, index, User); + } + + public void VerifyAddQualificationToDraftVacancy(int count, Qualification qualification) + { + Vacancy.Qualifications.Should().HaveCount(count); + ContainEquivalentOf(Vacancy.Qualifications, qualification).Should().BeTrue(); + } + + public void VerifyUpdateQualificationForDraftVacancy(Qualification qualification) + { + ContainEquivalentOf(Vacancy.Qualifications, qualification).Should().BeTrue(); + } + + public void VerifyRemoveQualificationFromDraftVacancy(Qualification qualification) + { + ContainEquivalentOf(Vacancy.Qualifications, qualification).Should().BeFalse(); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + private bool ContainEquivalentOf(List collection, T expected) + { + // the FluentAssertions ContainEquivalentOf does not have a negated equivalent + return collection.Any(p => JsonConvert.SerializeObject(p).Equals(JsonConvert.SerializeObject(expected))); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs new file mode 100644 index 0000000000..06a6cd99ed --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs @@ -0,0 +1,120 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.ShortDescription; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class ShortDescriptionOrchestratorTests + { + private ShortDescriptionOrchestratorTestsFixture _fixture; + + public ShortDescriptionOrchestratorTests() + { + _fixture = new ShortDescriptionOrchestratorTestsFixture(); + } + + [Fact] + public async Task WhenUpdated__ShouldCallUpdateDraftVacancy() + { + _fixture + .WithShortDescription("has a value") + .Setup(); + + var shortDescriptionEditModel = new ShortDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ShortDescription = "has a new value" + }; + + await _fixture.PostShortDescriptionEditModelAsync(shortDescriptionEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenShortDescriptionIsUpdated_ShouldFlagThingsToConsiderFieldIndicator() + { + _fixture + .WithShortDescription("has a value") + .Setup(); + + var shortDescriptionEditModel = new ShortDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ShortDescription = "has a new value" + }; + + await _fixture.PostShortDescriptionEditModelAsync(shortDescriptionEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ShortDescription, true); + } + + public class ShortDescriptionOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ShortDescription; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public ShortDescriptionOrchestrator Sut {get; private set;} + + public ShortDescriptionOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public ShortDescriptionOrchestratorTestsFixture WithShortDescription(string shortDescription) + { + Vacancy.ShortDescription = shortDescription; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new ShortDescriptionOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostShortDescriptionEditModelAsync(ShortDescriptionEditModel model) + { + await Sut.PostShortDescriptionEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs index 217eaeeaac..c2c4df1e87 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs @@ -1,14 +1,15 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; using Esfa.Recruit.Employer.Web.Orchestrators.Part2; using Esfa.Recruit.Employer.Web.RouteModel; -using Esfa.Recruit.Employer.Web.Services; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.Skills; +using Esfa.Recruit.Shared.Web.Mappers; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; -using Esfa.Recruit.Vacancies.Client.Infrastructure.ReferenceData.Skills; using FluentAssertions; using Microsoft.Extensions.Logging; using Moq; @@ -18,216 +19,360 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 { public class SkillOrchestratorTests { - private const string TestEmployerAccountId = "ABC"; - private readonly Mock _mockClient; - private readonly Mock _mockVacancyClient; - - private readonly SkillsOrchestrator _orchestrator; - private readonly Vacancy _testVacancy; - private readonly VacancyRouteModel _testRouteModel = new VacancyRouteModel { EmployerAccountId = TestEmployerAccountId, VacancyId = Guid.NewGuid() }; - - public SkillOrchestratorTests() - { - var mockLogger = new Mock>(); - var candidateSkills = GetBaseSkills(); - _mockClient = new Mock(); - _mockVacancyClient = new Mock(); - _orchestrator = new SkillsOrchestrator(_mockClient.Object, _mockVacancyClient.Object, mockLogger.Object, Mock.Of()); - _testVacancy = GetTestVacancy(); - - _mockVacancyClient.Setup(x => x.GetCandidateSkillsAsync()).ReturnsAsync(candidateSkills); - } - [Fact] public async Task WhenNoSkillsSaved_ShouldReturnListOfAllBasicSkillsUnchecked() { - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); - - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); - - // Count that all 18 base skills are there - result.Column1Checkboxes.Count(x => x.Selected == false).Should().Be(9); - result.Column2Checkboxes.Count(x => x.Selected == false).Should().Be(8); - } - - [Fact] - public async Task WhenSingleBaseSkillSaved_ShouldReturnListOfAllBasicSkillsWithSkillSelected() - { - _testVacancy.Skills = new List { "Logical" }; // Set the saved skill + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - var allCheckboxes = result.Column1Checkboxes.Union(result.Column2Checkboxes); - allCheckboxes.Where(x => x.Selected).Should().HaveCount(1); + fixture.VerifyAllBasicSkillsAreUnchecked(skillsViewModel); } - [Fact] - public async Task WhenMultipleBaseSkillsSaved_ShouldReturnListOfAllBasicSkillsWithSkillsSelected() + [Theory] + [InlineData(new string[] { "Logical" }, 1)] + [InlineData(new string[] { "Logical", "Patience" }, 2)] + public async Task WhenBaseSkillSaved_ShouldReturnListOfAllBasicSkillsWithSkillsSelected(string[] selectedSkills, int selectedCount) { - _testVacancy.Skills = new List { "Logical", "Patience" }; // Set the saved skill + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .WithSelectedSkills(selectedSkills) + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - var allCheckboxes = result.Column1Checkboxes.Union(result.Column2Checkboxes); - allCheckboxes.Where(x => x.Selected).Should().HaveCount(2); + fixture.VerifySelectedSkillsCount(skillsViewModel, selectedCount); } [Fact] public async Task WhenCustomSkillHasBeenSaved_ShouldReturnCustomSkillsSelectedInLastItemInSecondColumn() { - _testVacancy.Skills = new List { "Custom1" }; // Set the saved skill - - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var fixture = new SkillsOrchestratorTestsFixture(); + + var customSkill = "Custom1"; + fixture + .WithSelectedSkills(new string[] { customSkill }) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - var lastCol2Item = result.Column2Checkboxes.Last(); - lastCol2Item.Name.Should().Be("Custom1"); - lastCol2Item.Selected.Should().BeTrue(); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, customSkill, 8); } [Fact] public async Task WhenMultipleCustomSkillsSaved_ShouldReturnTheCustomSkillsInAlternateColumnsStaringWithColumn2() { - _testVacancy.Skills = new List { "Custom1", "Custom2", "Custom3" }; // Set the saved skill + var fixture = new SkillsOrchestratorTestsFixture(); + + var customSkill1 = "Custom1"; + var customSkill2 = "Custom2"; + var customSkill3 = "Custom3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { customSkill1, customSkill2, customSkill3 }) + .Setup(); - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - result.Column2Checkboxes.FindIndex(x => x.Name == "Custom1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Custom2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Custom3").Should().Be(9); // 10th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, customSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, customSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, customSkill3, 9); } [Fact] public async Task WhenCustomDraftSkillHasBeenAdded_ShouldBeAddedToColumn2() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "1-Draft1" }; + var draftSkill = "Draft1"; + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, new string[] { "1-" + draftSkill}); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill, 8); } [Fact] public async Task WhenCustomeDraftSkillsAdded_ShouldBeAddedToAlternateColumnsStartingWithColumn2() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "1-Draft1", "2-Draft2", "3-Draft3" }; + var draftSkill1 = "Draft1"; + var draftSkill2 = "Draft2"; + var draftSkill3 = "Draft3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, + new string[] { "1-" + draftSkill1, "2-" + draftSkill2, "3-" + draftSkill3 }); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Draft2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft3").Should().Be(9); // 10th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, draftSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } [Fact] public async Task WhenCustomDraftSkillsAddedAndBaseSkillSelected_ShouldBeAddedToAlternateColumnsStartingWithColumn2() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "1-Draft1", "Patience", "2-Draft2", "3-Draft3" }; + var draftSkill1 = "Draft1"; + var draftSkill2 = "Draft2"; + var draftSkill3 = "Draft3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, + new string[] { "1-" + draftSkill1, "Patience", "2-" + draftSkill2, "3-" + draftSkill3 }); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Draft2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft3").Should().Be(9); // 10th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, draftSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } - + [Fact] - public async Task WhenCustomDraftSkillsAdded_ShouldIncludeIndicatorOfItsOrder() + public async Task WhenCustomDraftSkillsHaveBeenAdded_ShouldBeOrderedByTheirPrefix() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); + + var draftSkill1 = "Draft1"; + var draftSkill2 = "Draft2"; + var draftSkill3 = "Draft3"; - var draftSkills = new [] { "2-Draft2", "3-Draft3", "1-Draft1" }; + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, + new string[] { "2-" + draftSkill2, "3-" + draftSkill3, "1-" + draftSkill1 }); - result.Column2Checkboxes.Single(x => x.Name == "Draft1").Value.Should().Be("1-Draft1"); - result.Column1Checkboxes.Single(x => x.Name == "Draft2").Value.Should().Be("2-Draft2"); - result.Column2Checkboxes.Single(x => x.Name == "Draft3").Value.Should().Be("3-Draft3"); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, draftSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } - - [Fact] - public async Task WhenCustomDraftSkillsHaveBeenAdded_ShouldBeOrderedByTheirPrefix() + + [Theory] + [InlineData(new string[] { }, new string[] { }, false)] + [InlineData(new string[] { }, new string[] { "Organisation skills" }, true)] + [InlineData(new string[] { "Organisation skills" }, new string[] { "Organisation skills" }, false)] + [InlineData(new string[] { "Organisation skills" }, new string[] { }, true)] + public async Task WhenSkillsAreUpdated_ShouldFlagSkillsFieldIndicator(string[] currentlySelectedSkills, string[] newSelectedSkills, bool fieldIndicatorSet) { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .WithSelectedSkills(currentlySelectedSkills) + .Setup(); - var draftSkills = new [] { "2-Draft2", "3-Draft3", "1-Draft1" }; + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var skillsEditModel = new SkillsEditModel + { + Skills = newSelectedSkills.ToList(), + AddCustomSkillAction = null, + AddCustomSkillName = null + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + await fixture.PostSkillsEditModelAsync(vacancyRouteModel, skillsEditModel); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Draft2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft3").Should().Be(9); // 10th item in list + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Skills, fieldIndicatorSet); } - private static Vacancy GetTestVacancy() + [Theory] + [InlineData(new string[] { }, new string[] { })] + [InlineData(new string[] { }, new string[] { "Organisation skills" })] + [InlineData(new string[] { "Organisation skills" }, new string[] { "Organisation skills" })] + [InlineData(new string[] { "Organisation skills" }, new string[] { })] + public async Task WhenSkillsAreUpdated_ShouldCallUpdateDraftVacancyAsync(string[] currentlySelectedSkills, string[] newSelectedSkills) { - return new Vacancy + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .WithSelectedSkills(currentlySelectedSkills) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel { - EmployerAccountId = TestEmployerAccountId, - Title = "Test Title", - NumberOfPositions = 1, - ShortDescription = "Test Short Description", - EmployerLocation = new Address - { - Postcode = "AB1 2XZ" - }, - ProgrammeId = "2", - Wage = new Wage - { - Duration = 1, - WageType = WageType.NationalMinimumWage - }, - LegalEntityName = "legal name", - EmployerNameOption = EmployerNameOption.RegisteredName, - StartDate = DateTime.Now + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsEditModel = new SkillsEditModel + { + Skills = newSelectedSkills.ToList(), + AddCustomSkillAction = null, + AddCustomSkillName = null }; + + await fixture.PostSkillsEditModelAsync(vacancyRouteModel, skillsEditModel); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); } - private static List GetBaseSkills() + public class SkillsOrchestratorTestsFixture { - return new List - { - "Communication skills", - "IT skills", - "Attention to detail", - "Organisation skills", - "Customer care skills", - "Problem solving skills", - "Presentation skills", - "Administrative skills", - "Number skills", - "Analytical skills", - "Logical", - "Team working", - "Creative", - "Initiative", - "Non judgemental", - "Patience", - "Physical fitness" - }; + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Skills; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public SkillsOrchestrator Sut { get; private set; } + + public SkillsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public SkillsOrchestratorTestsFixture WithSelectedSkills(string[] selectedSkills) + { + Vacancy.Skills = selectedSkills.ToList(); + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetCandidateSkillsAsync()).ReturnsAsync(GetBasicSkills()); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new SkillsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task GetSkillsViewModelAsync(VacancyRouteModel vacancyRouteModel, string[] draftSkills = null) + { + return await Sut.GetSkillsViewModelAsync(vacancyRouteModel, draftSkills); + } + + public async Task PostSkillsEditModelAsync(VacancyRouteModel vacancyRouteModel, SkillsEditModel model) + { + await Sut.PostSkillsEditModelAsync(vacancyRouteModel, model, User); + } + + public void VerifyAllBasicSkillsAreUnchecked(SkillsViewModel skillsViewModel) + { + var allCheckboxes = skillsViewModel.Column1Checkboxes.Union(skillsViewModel.Column2Checkboxes); + allCheckboxes.Where(x => x.Selected == false).Should().HaveCount(GetBasicSkills().Count); + } + + internal void VerifySelectedSkillsCount(SkillsViewModel skillsViewModel, int count) + { + var allCheckboxes = skillsViewModel.Column1Checkboxes.Union(skillsViewModel.Column2Checkboxes); + allCheckboxes.Where(x => x.Selected).Should().HaveCount(count); + } + + public SkillsOrchestratorTestsFixture VerifyColumn2CheckboxesItemSelected(SkillsViewModel skillsViewModel, string customSkill, int index) + { + skillsViewModel.Column2Checkboxes.FindIndex(x => x.Name == customSkill && x.Selected).Should().Be(index); + return this; + } + + public SkillsOrchestratorTestsFixture VerifyColumn1CheckboxesItemSelected(SkillsViewModel skillsViewModel, string customSkill, int index) + { + skillsViewModel.Column1Checkboxes.FindIndex(x => x.Name == customSkill && x.Selected).Should().Be(index); + return this; + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + private static List GetBasicSkills() + { + return new List + { + "Communication skills", + "IT skills", + "Attention to detail", + "Organisation skills", + "Customer care skills", + "Problem solving skills", + "Presentation skills", + "Administrative skills", + "Number skills", + "Analytical skills", + "Logical", + "Team working", + "Creative", + "Initiative", + "Non judgemental", + "Patience", + "Physical fitness" + }; + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs new file mode 100644 index 0000000000..dea2af123e --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs @@ -0,0 +1,163 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.ShortDescription; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.VacancyDescription; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class VacancyDescriptionOrchestratorTests + { + private VacancyDescriptionOrchestratorTestsFixture _fixture; + + public VacancyDescriptionOrchestratorTests() + { + _fixture = new VacancyDescriptionOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value")] + [InlineData("has a value", "has a new value", "has a value")] + [InlineData("has a value", "has a value", "has a new value")] + [InlineData("has a new value", "has a new value", "has a new value")] + public async Task WhenUpdated__ShouldCallUpdateDraftVacancy(string description, string trainingDescription, string outcomeDescription) + { + _fixture + .WithDescription("has a value") + .WithTrainingDescription("has a value") + .WithOutcomeDescription("has a value") + .Setup(); + + var vacancyDescriptionEditModel = new VacancyDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + VacancyDescription = description, + TrainingDescription = trainingDescription, + OutcomeDescription = outcomeDescription + }; + + await _fixture.PostVacancyDescriptionEditModelAsync(vacancyDescriptionEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value", new string[] { FieldIdentifiers.VacancyDescription }, new string[] { FieldIdentifiers.TrainingDescription, FieldIdentifiers.OutcomeDescription })] + [InlineData("has a value", "has a new value", "has a value", new string[] { FieldIdentifiers.TrainingDescription }, new string[] { FieldIdentifiers.VacancyDescription, FieldIdentifiers.OutcomeDescription })] + [InlineData("has a value", "has a value", "has a new value", new string[] { FieldIdentifiers.OutcomeDescription }, new string[] { FieldIdentifiers.VacancyDescription, FieldIdentifiers.Training})] + [InlineData("has a new value", "has a new value", "has a new value", new string[] { FieldIdentifiers.VacancyDescription, FieldIdentifiers.TrainingDescription , FieldIdentifiers.OutcomeDescription }, new string[] { })] + public async Task WhenShortDescriptionIsUpdated_ShouldFlagFieldIndicators(string description, string trainingDescription, string outcomeDescription, string[] setFieldIndicators, string[] unsetFieldIndicators) + { + _fixture + .WithDescription("has a value") + .WithTrainingDescription("has a value") + .WithOutcomeDescription("has a value") + .Setup(); + + var vacancyDescriptionEditModel = new VacancyDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + VacancyDescription = description, + TrainingDescription = trainingDescription, + OutcomeDescription = outcomeDescription + }; + + await _fixture.PostVacancyDescriptionEditModelAsync(vacancyDescriptionEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIndicators, unsetFieldIndicators); + } + + public class VacancyDescriptionOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public VacancyDescriptionOrchestrator Sut {get; private set;} + + public VacancyDescriptionOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public VacancyDescriptionOrchestratorTestsFixture WithDescription(string description) + { + Vacancy.Description = description; + return this; + } + + public VacancyDescriptionOrchestratorTestsFixture WithTrainingDescription(string trainingDescription) + { + Vacancy.TrainingDescription = trainingDescription; + return this; + } + + public VacancyDescriptionOrchestratorTestsFixture WithOutcomeDescription(string outcomeDescription) + { + Vacancy.OutcomeDescription = outcomeDescription; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new VacancyDescriptionOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostVacancyDescriptionEditModelAsync(VacancyDescriptionEditModel model) + { + await Sut.PostVacancyDescriptionEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs b/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs index a915f0cf68..eddeb54bc3 100644 --- a/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs +++ b/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs @@ -25,6 +25,7 @@ public async Task GetVacancyReviewedOrches { var vacancy = await Utility.GetAuthorisedVacancyAsync(_client, _vacancyClient, vrm, RouteNames.Reviewed_Index_Get); var employer = await _client.GetProviderEmployerVacancyDataAsync(vrm.Ukprn, vacancy.EmployerAccountId); + var preferences = await _vacancyClient.GetUserNotificationPreferencesAsync(vacancyUser.UserId); if (vacancy.Status != VacancyStatus.Review) throw new InvalidStateException(string.Format(ErrorMessages.VacancyNotReviewedSuccessfully, vacancy.Title)); @@ -34,7 +35,8 @@ public async Task GetVacancyReviewedOrches Title = vacancy.Title, VacancyReference = vacancy.VacancyReference?.ToString(), EmployerName = employer.Name, - IsResubmit = vacancy.ReviewDate.HasValue + IsResubmit = vacancy.ReviewCount > 1, + IsVacancyRejectedByEmployerNotificationSelected = preferences.NotificationTypes.HasFlag(NotificationTypes.VacancyRejectedByEmployer) }; return vm; diff --git a/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs b/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs index 6d924037a1..cddf434b65 100644 --- a/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs +++ b/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs @@ -43,7 +43,8 @@ public async Task GetVacancySubmittedConf Title = vacancy.Title, VacancyReference = vacancy.VacancyReference?.ToString(), IsResubmit = isResubmit, - HasNotificationsSet = preferences != null && preferences.NotificationTypes > NotificationTypes.None + HasNotificationsSet = preferences != null && preferences.NotificationTypes > NotificationTypes.None, + IsVacancyRejectedByESFANotificationSelected = preferences.NotificationTypes.HasFlag(NotificationTypes.VacancyRejected) }; return vm; diff --git a/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs b/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs index 6b08c26d47..589ac1b293 100644 --- a/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs +++ b/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs @@ -8,5 +8,6 @@ public class VacancyReviewedConfirmationViewModel public bool HasVacancyReference => !string.IsNullOrEmpty(VacancyReference); public string EmployerName { get; set; } public bool IsResubmit { get; set; } + public bool IsVacancyRejectedByEmployerNotificationSelected { get; set; } } } diff --git a/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs b/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs index e96d2577bd..559d3c59c6 100644 --- a/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs +++ b/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs @@ -8,5 +8,6 @@ public class VacancySubmittedConfirmationViewModel public bool HasVacancyReference => !string.IsNullOrEmpty(VacancyReference); public bool HasNotificationsSet { get; set; } + public bool IsVacancyRejectedByESFANotificationSelected { get; set; } } } diff --git a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml index 8e79d6ef14..3b9d6009f6 100644 --- a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml @@ -20,25 +20,38 @@

- +

What happens next

@Model.EmployerName needs to approve the vacancy.

- +

- If they approve the vacancy, we’ll do a final review and then post it on ‘Find an apprenticeship’. + If @Model.EmployerName approves the vacancy, the ESFA will do a final review and then post it on 'Find an apprenticeship'.

- + + @if (Model.IsVacancyRejectedByEmployerNotificationSelected) + { +

+ If @Model.EmployerName reject the vacancy, it will come back to you to edit and resubmit. We will let you know by email if you need to make any edits. +

+ } + else + { +

+ If the vacancy is rejected by either @Model.EmployerName or the ESFA and you need to make edits, they will tell you in the rejected vacancies of your Recruitment dashboard. +

+ } +

- If they reject the vacancy, it will come back to you to edit and resubmit. + Manage the frequency of your recruitment emails

- +

- Return to recruitment dashboard + Return to recruitment

- +

Create another vacancy

diff --git a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml index 0636b8c569..bd9b152f3e 100644 --- a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml @@ -4,42 +4,52 @@ ViewBag.GaData.Vpv = "/recruitment/provider/page-vacancy-submitted-for-approval"; } -

@Model.Title

-
-
-

- Vacancy submitted for approval +
+

+ Vacancy submitted to ESFA +

+

+ Vacancy resubmitted to ESFA

- The vacancy reference number is
+ Your reference number
VAC@(Model.VacancyReference)

-
-

- Vacancy resubmitted for approval -

-
-

Next steps

-
-

We’ll check the vacancy and let you know by email within one working day if you need to make any edits. Manage your recruitment emails.

-

When the vacancy is approved, it will appear on the Find an apprenticeship service.

-
-
-

We’ll check the vacancy and tell you within one working day on the dashboard if you need to make any edits. Visit Manage your recruitment emails if you’d also like to get an email.

-

When the vacancy is approved, it will appear on the Find an apprenticeship service.

-
+

What happens next

- + @if (Model.IsVacancyRejectedByESFANotificationSelected) + { +

+ The ESFA will check the vacancy and let you know by email, within one working day, if you need to make any edits. +

+ } + else + { +

+ The ESFA will check the vacancy and will tell you within one working day, on the Recruitment dashboard within rejected vacancies, if you need to make any edits. +

+ } + +

+ Manage the frequency of your recruitment emails +

+ +

+ When the vacancy is approved, it will appear on Find an apprenticeship. +

+ +

+ Return to recruitment +

+ +

+ Create another vacancy +

\ No newline at end of file diff --git a/src/Provider/Provider.Web/wwwroot/css/application.css b/src/Provider/Provider.Web/wwwroot/css/application.css index 99595cf653..ab6fb494c9 100644 --- a/src/Provider/Provider.Web/wwwroot/css/application.css +++ b/src/Provider/Provider.Web/wwwroot/css/application.css @@ -1227,4 +1227,145 @@ a[rel="external"]:hover:after { display: none; } -/*** End of cookie banner ***/ \ No newline at end of file +/*** End of cookie banner ***/ + + +/* govuk notification banner */ + +.govuk-notification-banner { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + line-height: 1.25; + margin-bottom: 30px; + border: 5px solid #1d70b8; + background-color: #1d70b8; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner { + margin-bottom: 50px; + } +} + +.govuk-notification-banner__header { + padding: 2px 15px 5px; + border-bottom: 1px solid transparent; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__header { + padding: 2px 20px 5px; + } +} + +.govuk-notification-banner__title { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + line-height: 1.25; + margin: 0; + padding: 0; + color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__title { + font-size: 19px; + line-height: 1.35; + } +} + +.govuk-notification-banner__content { + color: #0b0c0c; + padding: 15px; + background-color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__content { + padding: 20px; + } +} + +.govuk-notification-banner__content > * { + max-width: 605px; +} + +.govuk-notification-banner__content>:last-child { + margin-bottom: 0; +} + +.govuk-notification-banner__heading { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + line-height: 1.1; + margin: 0 0 15px 0; + padding: 0; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__heading { + font-size: 24px; + line-height: 1.25; + } +} + +.govuk-notification-banner__link { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + color: #1d70b8; +} + +.govuk-notification-banner__link:link { + color: #1d70b8; +} + +.govuk-notification-banner__link:hover { + color: #003078; +} + +.govuk-notification-banner__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #fd0; + -webkit-box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + text-decoration: none; +} + +/* Additional govuk tag colours */ + +.govuk-tag--purple { + color: #3d2375; + background: #dbd5e9; +} + +.govuk-tag--red { + color: #942514; + background: #f6d7d2; +} + +.govuk-tag--blue { + color: #144e81; + background: #d2e2f1; +} + +.govuk-tag--green { + color: #005a30; + background: #cce2d8; +} + +.govuk-tag--orange { + color: #6e3619; + background: #fcd6c3; +} \ No newline at end of file diff --git a/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css b/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css index 97f12fb2c3..c4d29e3955 100755 --- a/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css +++ b/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css @@ -1,3 +1,3 @@ -@charset "UTF-8";.govuk-link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} +@charset "UTF-8";.govuk-link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} -/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-f38ad40456-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-458f8ea81c-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-a2452cb66f-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-f38c792ac2-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-851b10ccdd-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-62cc6f0a28-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-b89238d840-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-784c21afb8-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@media print{.govuk-link{font-family:sans-serif}}.govuk-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-link:link{color:#005ea5}.govuk-link:visited{color:#4c2c92}.govuk-link:active,.govuk-link:hover{color:#2b8cc4}.govuk-link:focus{color:#0b0c0c}@media print{.govuk-link[href^="/"]:after,.govuk-link[href^="http://"]:after,.govuk-link[href^="https://"]:after{content:" (" attr(href) ")";font-size:90%;word-wrap:break-word}}.govuk-link--muted:active,.govuk-link--muted:hover,.govuk-link--muted:link,.govuk-link--muted:visited{color:#6f777b}.govuk-link--muted:focus,.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#0b0c0c}@media print{.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#000}}.govuk-link--no-visited-state:link,.govuk-link--no-visited-state:visited{color:#005ea5}.govuk-link--no-visited-state:active,.govuk-link--no-visited-state:hover{color:#2b8cc4}.govuk-link--no-visited-state:focus,.govuk-list{color:#0b0c0c}.govuk-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px;padding-left:0;list-style-type:none}@media print{.govuk-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-list{margin-bottom:20px}}.govuk-list .govuk-list{margin-top:10px}.govuk-list>li{margin-bottom:5px}.govuk-list--bullet{padding-left:20px;list-style-type:disc}.govuk-list--number{padding-left:20px;list-style-type:decimal}.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:0}@media (min-width:40.0625em){.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:5px}}.govuk-template{background-color:#dee0e2}.govuk-template__body{margin:0;background-color:#fff}.govuk-heading-xl{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;display:block;margin-top:0;margin-bottom:30px}@media print{.govuk-heading-xl{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-heading-xl{font-size:32pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-xl{margin-bottom:50px}}.govuk-heading-l{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;display:block;margin-top:0;margin-bottom:20px}@media print{.govuk-heading-l{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-heading-l{font-size:24pt;line-height:1.05}}@media (min-width:40.0625em){.govuk-heading-l{margin-bottom:30px}}.govuk-heading-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-heading-m{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-m{margin-bottom:20px}}.govuk-heading-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-heading-s{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-s{margin-bottom:20px}}.govuk-caption-xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-xl{font-size:27px;font-size:1.6875rem;line-height:1.11111}}@media print{.govuk-caption-xl{font-size:18pt;line-height:1.15}}.govuk-caption-l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-l{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-caption-l{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-caption-l{margin-bottom:0}}.govuk-caption-m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;color:#6f777b}@media print{.govuk-caption-m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-caption-m{font-size:14pt;line-height:1.15}}.govuk-body-l,.govuk-body-lead{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:20px}@media print{.govuk-body-l,.govuk-body-lead{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-body-l,.govuk-body-lead{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{margin-bottom:30px}}.govuk-body,.govuk-body-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body,.govuk-body-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-body,.govuk-body-m{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{margin-bottom:20px}}.govuk-body-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;margin-top:0;margin-bottom:15px}@media print{.govuk-body-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-s{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-body-s{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-s{margin-bottom:20px}}.govuk-body-xs{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:12px;font-size:.75rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body-xs{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-xs{font-size:14px;font-size:.875rem;line-height:1.42857}}@media print{.govuk-body-xs{font-size:12pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-xs{margin-bottom:20px}}.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:5px}@media (min-width:40.0625em){.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:10px}}.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:15px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:20px}}.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:5px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:10px}}.govuk-section-break{margin:0;border:0}.govuk-section-break--xl{margin-top:30px;margin-bottom:30px}@media (min-width:40.0625em){.govuk-section-break--xl{margin-top:50px;margin-bottom:50px}}.govuk-section-break--l{margin-top:20px;margin-bottom:20px}@media (min-width:40.0625em){.govuk-section-break--l{margin-top:30px;margin-bottom:30px}}.govuk-section-break--m{margin-top:15px;margin-bottom:15px}@media (min-width:40.0625em){.govuk-section-break--m{margin-top:20px;margin-bottom:20px}}.govuk-section-break--visible{border-bottom:1px solid #bfc1c3}.govuk-form-group{margin-bottom:20px}@media (min-width:40.0625em){.govuk-form-group{margin-bottom:30px}}.govuk-form-group .govuk-form-group:last-of-type{margin-bottom:0}.govuk-form-group--error{padding-left:15px;border-left:5px solid #b10e1e}.govuk-form-group--error .govuk-form-group{padding:0;border:0}.govuk-grid-row{margin-right:-15px;margin-left:-15px}.govuk-grid-row:after{content:"";display:block;clear:both}.govuk-grid-column-one-quarter{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-quarter{width:25%;float:left}}.govuk-grid-column-one-third{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-third{width:33.3333%;float:left}}.govuk-grid-column-one-half{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-half{width:50%;float:left}}.govuk-grid-column-two-thirds{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-two-thirds{width:66.6666%;float:left}}.govuk-grid-column-three-quarters{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-three-quarters{width:75%;float:left}}.govuk-grid-column-full{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-full{width:100%;float:left}}.govuk-grid-column-one-quarter-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-quarter-from-desktop{width:25%;float:left}}.govuk-grid-column-one-third-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-third-from-desktop{width:33.3333%;float:left}}.govuk-grid-column-one-half-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-half-from-desktop{width:50%;float:left}}.govuk-grid-column-two-thirds-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-two-thirds-from-desktop{width:66.6666%;float:left}}.govuk-grid-column-three-quarters-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-three-quarters-from-desktop{width:75%;float:left}}.govuk-grid-column-full-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-full-from-desktop{width:100%;float:left}}.govuk-main-wrapper{padding-top:20px;padding-bottom:20px;display:block}@media (min-width:40.0625em){.govuk-main-wrapper{padding-top:30px;padding-bottom:30px}}.govuk-main-wrapper--l{padding-top:30px}@media (min-width:40.0625em){.govuk-main-wrapper--l{padding-top:50px}}.govuk-width-container{max-width:960px;margin:0 15px}@media (min-width:40.0625em){.govuk-width-container{margin:0 30px}}@media (min-width:1020px){.govuk-width-container{margin:0 auto}}.govuk-accordion{margin-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-accordion{margin-bottom:30px}}.govuk-accordion__section{border-top:1px solid #bfc1c3}.govuk-accordion__section-header{padding-bottom:15px}.govuk-accordion__section-heading{margin-top:0;margin-bottom:0}.govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:0;padding-top:15px}@media print{.govuk-accordion__section-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-accordion__section-button{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-accordion__section-button{font-size:18pt;line-height:1.15}}.govuk-accordion__section-summary{margin-top:10px;margin-bottom:0}.js-enabled .govuk-accordion__section-content{display:none;padding-top:15px;padding-bottom:15px}@media (min-width:40.0625em){.js-enabled .govuk-accordion__section-content{padding-top:15px;padding-bottom:15px}}.js-enabled .govuk-accordion__section-content>:last-child{margin-bottom:0}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-content{display:block}.js-enabled .govuk-accordion__open-all{font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline;border-width:0;color:#005ea5;background:none;cursor:pointer}@media (min-width:40.0625em){.js-enabled .govuk-accordion__open-all{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.js-enabled .govuk-accordion__open-all{font-size:14pt;line-height:1.2;font-family:sans-serif}}.js-enabled .govuk-accordion__open-all:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;background:none}.js-enabled .govuk-accordion__section-header{position:relative;padding-right:40px;cursor:pointer}.js-enabled .govuk-accordion__section-header:hover{background-color:#f8f8f8}.js-enabled .govuk-accordion__section-header--focused{outline:3px solid #ffbf47;outline-offset:0}.js-enabled .govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100%;margin-top:0;margin-bottom:0;margin-left:0;padding-top:15px;padding-bottom:0;padding-left:0;border-width:0;color:#005ea5;background:none;text-align:left;cursor:pointer}@media print{.js-enabled .govuk-accordion__section-button{font-family:sans-serif}}.js-enabled .govuk-accordion__section-button:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;outline:none;background:none}.js-enabled .govuk-accordion__section-button:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.js-enabled .govuk-accordion__controls{text-align:right}.js-enabled .govuk-accordion__icon{position:absolute;top:50%;right:15px;width:16px;height:16px;margin-top:-8px}.js-enabled .govuk-accordion__icon:after,.js-enabled .govuk-accordion__icon:before{content:"";box-sizing:border-box;position:absolute;top:0;right:0;bottom:0;left:0;width:25%;height:25%;margin:auto;border:2px solid rgba(0,0,0,0);background-color:#0b0c0c}.js-enabled .govuk-accordion__icon:before{width:100%}.js-enabled .govuk-accordion__icon:after{height:100%}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__icon:after{content:" ";display:none}.govuk-back-link{font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;position:relative;margin-top:15px;margin-bottom:15px;padding-left:14px;border-bottom:1px solid #0b0c0c;text-decoration:none}@media (min-width:40.0625em){.govuk-back-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-back-link{font-size:14pt;line-height:1.2;font-family:sans-serif}}.govuk-back-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#0b0c0c}@media print{.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#000}}.govuk-back-link:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 50%,100% 100%,100% 0);clip-path:polygon(0 50%,100% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:5px 6px 5px 0;border-right-color:inherit;content:"";position:absolute;left:0;margin:auto}.govuk-back-link:before{top:-1px;bottom:1px}.govuk-breadcrumbs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;margin-top:15px;margin-bottom:10px}@media print{.govuk-breadcrumbs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-breadcrumbs{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-breadcrumbs{font-size:14pt;line-height:1.2;color:#000}}.govuk-breadcrumbs__list{margin:0;padding:0;list-style-type:none}.govuk-breadcrumbs__list:after{content:"";display:block;clear:both}.govuk-breadcrumbs__list-item{display:inline-block;position:relative;margin-bottom:5px;margin-left:10px;padding-left:15.655px;float:left}.govuk-breadcrumbs__list-item:before{content:"";display:block;position:absolute;top:-1px;bottom:1px;left:-3.31px;width:7px;height:7px;margin:auto 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);border:solid;border-width:1px 1px 0 0;border-color:#6f777b}.govuk-breadcrumbs__list-item:first-child{margin-left:0;padding-left:0}.govuk-breadcrumbs__list-item:first-child:before{content:none;display:none}.govuk-breadcrumbs__link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media print{.govuk-breadcrumbs__link{font-family:sans-serif}}.govuk-breadcrumbs__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#0b0c0c}@media print{.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#000}}.govuk-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.1875;box-sizing:border-box;display:inline-block;position:relative;width:100%;margin-top:0;margin-bottom:22px;padding:7px 10px;border:2px solid rgba(0,0,0,0);border-radius:0;color:#fff;background-color:#00823b;box-shadow:0 2px 0 #003618;text-align:center;vertical-align:top;cursor:pointer;-webkit-appearance:none}@media print{.govuk-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-button{font-size:19px;font-size:1.1875rem;line-height:1}}@media print{.govuk-button{font-size:14pt;line-height:19px}}.govuk-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-button{margin-bottom:32px;width:auto}}.govuk-button:active,.govuk-button:hover,.govuk-button:link,.govuk-button:visited{color:#fff;text-decoration:none}.govuk-button::-moz-focus-inner{padding:0;border:0}.govuk-button:focus,.govuk-button:hover{background-color:#00692f}.govuk-button:active{top:2px;box-shadow:none}.govuk-button:before{content:"";display:block;position:absolute;top:-2px;right:-2px;bottom:-4px;left:-2px;background:rgba(0,0,0,0)}.govuk-button:active:before{top:-4px}.govuk-button--disabled,.govuk-button[disabled=disabled],.govuk-button[disabled]{opacity:.5;background:#00823b}.govuk-button--disabled:hover,.govuk-button[disabled=disabled]:hover,.govuk-button[disabled]:hover{background-color:#00823b;cursor:default}.govuk-button--disabled:focus,.govuk-button[disabled=disabled]:focus,.govuk-button[disabled]:focus{outline:none}.govuk-button--disabled:active,.govuk-button[disabled=disabled]:active,.govuk-button[disabled]:active{top:0;box-shadow:0 2px 0 #003618}.govuk-button--start{font-weight:700;font-size:18px;font-size:1.125rem;line-height:1;min-height:auto;padding:8px 40px 8px 15px;background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer.png);background-repeat:no-repeat;background-position:100% 50%}@media (min-width:40.0625em){.govuk-button--start{font-size:24px;font-size:1.5rem;line-height:1}}@media print{.govuk-button--start{font-size:18pt;line-height:1}}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-button--start{background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer-2x.png);background-size:30px 19px}}.govuk-button,.govuk-button--start{padding-top:9px;padding-bottom:6px}.govuk-error-message{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;clear:both;color:#b10e1e}@media print{.govuk-error-message{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-message{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-message{font-size:14pt;line-height:1.15}}.govuk-fieldset{margin:0;padding:0;border:0}.govuk-fieldset:after{content:"";display:block;clear:both}.govuk-fieldset__legend{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;box-sizing:border-box;display:table;max-width:100%;margin-bottom:10px;padding:0;overflow:hidden;white-space:normal}@media print{.govuk-fieldset__legend{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend{font-size:14pt;line-height:1.15;color:#000}}.govuk-fieldset__legend--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-fieldset__legend--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-fieldset__legend--xl{font-size:32pt;line-height:1.15}}.govuk-fieldset__legend--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-fieldset__legend--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-fieldset__legend--l{font-size:24pt;line-height:1.05}}.govuk-fieldset__legend--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:15px}@media print{.govuk-fieldset__legend--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-fieldset__legend--m{font-size:18pt;line-height:1.15}}.govuk-fieldset__legend--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-fieldset__legend--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend--s{font-size:14pt;line-height:1.15}}.govuk-fieldset__heading{margin:0;font-size:inherit;font-weight:inherit}.govuk-hint{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;color:#6f777b}@media print{.govuk-hint{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-hint{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-hint{font-size:14pt;line-height:1.15}}.govuk-label:not(.govuk-label--m):not(.govuk-label--l):not(.govuk-label--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend:not(.govuk-fieldset__legend--m):not(.govuk-fieldset__legend--l):not(.govuk-fieldset__legend--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend+.govuk-hint{margin-top:-5px}.govuk-label{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;display:block;margin-bottom:5px}@media print{.govuk-label{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label{font-size:14pt;line-height:1.15;color:#000}}.govuk-label--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-label--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-label--xl{font-size:32pt;line-height:1.15}}.govuk-label--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-label--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-label--l{font-size:24pt;line-height:1.05}}.govuk-label--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:10px}@media print{.govuk-label--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-label--m{font-size:18pt;line-height:1.15}}.govuk-label--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-label--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label--s{font-size:14pt;line-height:1.15}}.govuk-label-wrapper{margin:0}.govuk-checkboxes__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-checkboxes__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-checkboxes__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-checkboxes__item{font-size:14pt;line-height:1.15}}.govuk-checkboxes__item:last-child,.govuk-checkboxes__item:last-of-type{margin-bottom:0}.govuk-checkboxes__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-checkboxes__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-checkboxes__hint{display:block;padding-right:15px;padding-left:15px}.govuk-checkboxes__input+.govuk-checkboxes__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;background:rgba(0,0,0,0)}.govuk-checkboxes__input+.govuk-checkboxes__label:after{content:"";position:absolute;top:11px;left:9px;width:18px;height:7px;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);border:solid;border-width:0 0 5px 5px;border-top-color:rgba(0,0,0,0);opacity:0;background:rgba(0,0,0,0)}.govuk-checkboxes__input:focus+.govuk-checkboxes__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 3px #ffbf47}.govuk-checkboxes__input:checked+.govuk-checkboxes__label:after{opacity:1}.govuk-checkboxes__input:disabled,.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{cursor:default}.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{opacity:.5}.govuk-checkboxes__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-checkboxes__conditional{margin-bottom:20px}}.js-enabled .govuk-checkboxes__conditional--hidden{display:none}.govuk-checkboxes__conditional>:last-child{margin-bottom:0}.govuk-character-count{margin-bottom:20px}@media (min-width:40.0625em){.govuk-character-count{margin-bottom:30px}}.govuk-character-count .govuk-form-group,.govuk-character-count .govuk-textarea{margin-bottom:5px}.govuk-character-count .govuk-textarea--error{padding:3px}.govuk-character-count__message{margin-top:0;margin-bottom:0}.govuk-character-count__message--disabled{visibility:hidden}.govuk-summary-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin:0 0 20px}@media print{.govuk-summary-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-summary-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-summary-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-summary-list{display:table;width:100%;margin-bottom:30px}}@media (max-width:40.0525em){.govuk-summary-list__row{margin-bottom:15px;border-bottom:1px solid #bfc1c3}}@media (min-width:40.0625em){.govuk-summary-list__row{display:table-row}}.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{margin:0}@media (min-width:40.0625em){.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{display:table-cell;padding-right:20px;padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}}.govuk-summary-list__actions{margin-bottom:15px}@media (min-width:40.0625em){.govuk-summary-list__actions{padding-right:0}}.govuk-summary-list__key{margin-bottom:5px;font-weight:700;word-break:break-word}@media (min-width:40.0625em){.govuk-summary-list__key{width:30%}}@media (max-width:40.0525em){.govuk-summary-list__value{margin-bottom:15px}}.govuk-summary-list__value>p{margin-bottom:10px}.govuk-summary-list__value>:last-child{margin-bottom:0}.govuk-summary-list__actions-list{width:100%;margin:0;padding:0}@media (min-width:40.0625em){.govuk-summary-list__actions-list{text-align:right}}.govuk-summary-list__actions-list-item{display:inline;margin-right:10px;padding-right:10px}.govuk-summary-list__actions-list-item:not(:last-child){border-right:1px solid #bfc1c3}.govuk-summary-list__actions-list-item:last-child{margin-right:0;padding-right:0;border:0}.govuk-summary-list--no-border .govuk-summary-list__actions,.govuk-summary-list--no-border .govuk-summary-list__key,.govuk-summary-list--no-border .govuk-summary-list__row,.govuk-summary-list--no-border .govuk-summary-list__value{border:0}.govuk-input{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;width:100%;height:40px;margin-top:0;padding:5px;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media print{.govuk-input{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-input{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-input{font-size:14pt;line-height:1.15}}.govuk-input:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-input::-webkit-inner-spin-button,.govuk-input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.govuk-input[type=number]{-moz-appearance:textfield}.govuk-input--error{border:4px solid #b10e1e}.govuk-input--width-30{max-width:59ex}.govuk-input--width-20{max-width:41ex}.govuk-input--width-10{max-width:23ex}.govuk-input--width-5{max-width:10.8ex}.govuk-input--width-4{max-width:9ex}.govuk-input--width-3{max-width:7.2ex}.govuk-input--width-2{max-width:5.4ex}.govuk-date-input{font-size:0}.govuk-date-input:after{content:"";display:block;clear:both}.govuk-date-input__item{display:inline-block;margin-right:20px;margin-bottom:0}.govuk-date-input__label{display:block}.govuk-date-input__input{margin-bottom:0}.govuk-details{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-bottom:20px;display:block}@media print{.govuk-details{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-details{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-details{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-details{margin-bottom:30px}}.govuk-details__summary{display:inline-block;position:relative;margin-bottom:5px;padding-left:25px;color:#005ea5;cursor:pointer}.govuk-details__summary-text{text-decoration:underline}.govuk-details__summary:hover{color:#2b8cc4}.govuk-details__summary:focus{outline:4px solid #ffbf47;outline-offset:-1px;color:#0b0c0c;background:#ffbf47}.govuk-details__summary::-webkit-details-marker{display:none}.govuk-details__summary:before{content:"";position:absolute;top:0;bottom:0;left:0;margin:auto;display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,100% 50%,0 100%);clip-path:polygon(0 0,100% 50%,0 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:7px 0 7px 12.124px;border-left-color:inherit}.govuk-details[open]>.govuk-details__summary:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:12.124px 7px 0;border-top-color:inherit}.govuk-details__text{padding:15px 15px 15px 20px;border-left:5px solid #bfc1c3}.govuk-details__text p{margin-top:0;margin-bottom:20px}.govuk-details__text>:last-child{margin-bottom:0}.govuk-error-summary{color:#0b0c0c;padding:15px;margin-bottom:30px;border:4px solid #b10e1e}@media print{.govuk-error-summary{color:#000}}@media (min-width:40.0625em){.govuk-error-summary{padding:20px;margin-bottom:50px}}.govuk-error-summary:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-error-summary{border:5px solid #b10e1e}}.govuk-error-summary__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:15px}@media print{.govuk-error-summary__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__title{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-error-summary__title{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-error-summary__title{margin-bottom:20px}}.govuk-error-summary__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-error-summary__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__body{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-summary__body{font-size:14pt;line-height:1.15}}.govuk-error-summary__body p{margin-top:0;margin-bottom:15px}@media (min-width:40.0625em){.govuk-error-summary__body p{margin-bottom:20px}}.govuk-error-summary__list{margin-top:0;margin-bottom:0}.govuk-error-summary__list a{font-weight:700}.govuk-error-summary__list a:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-error-summary__list a:active,.govuk-error-summary__list a:hover,.govuk-error-summary__list a:link,.govuk-error-summary__list a:visited{color:#b10e1e}.govuk-error-summary__list a:focus{color:#0b0c0c}.govuk-file-upload{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c}@media print{.govuk-file-upload{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-file-upload{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-file-upload{font-size:14pt;line-height:1.15;color:#000}}.govuk-file-upload:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-file-upload--error{border:4px solid #b10e1e}.govuk-footer{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;padding-top:25px;padding-bottom:15px;border-top:1px solid #a1acb2;color:#454a4c;background:#dee0e2}@media print{.govuk-footer{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-footer{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-footer{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-footer{padding-top:40px;padding-bottom:25px}}.govuk-footer__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-footer__link:link,.govuk-footer__link:visited{color:#454a4c}.govuk-footer__link:active,.govuk-footer__link:hover{color:#171819}.govuk-footer__link:focus{color:#0b0c0c}.govuk-footer__section-break{margin:0 0 30px;border:0;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__section-break{margin-bottom:50px}}.govuk-footer__meta{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:end;-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.govuk-footer__meta-item{margin-right:15px;margin-bottom:25px;margin-left:15px}.govuk-footer__meta-item--grow{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}@media (max-width:40.0525em){.govuk-footer__meta-item--grow{-webkit-flex-basis:320px;-ms-flex-preferred-size:320px;flex-basis:320px}}.govuk-footer__licence-logo{display:inline-block;margin-right:10px;vertical-align:top}@media (max-width:48.0525em){.govuk-footer__licence-logo{margin-bottom:15px}}.govuk-footer__licence-description{display:inline-block}.govuk-footer__copyright-logo{display:inline-block;min-width:125px;padding-top:112px;background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest.png);background-repeat:no-repeat;background-position:50% 0;background-size:125px 102px;text-align:center;text-decoration:none;white-space:nowrap}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-footer__copyright-logo{background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest-2x.png)}}.govuk-footer__inline-list{margin-top:0;margin-bottom:15px;padding:0}.govuk-footer__meta-custom{margin-bottom:20px}.govuk-footer__inline-list-item{display:inline-block;margin-right:15px;margin-bottom:5px}.govuk-footer__heading{margin-bottom:25px;padding-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__heading{margin-bottom:40px}}@media (max-width:40.0525em){.govuk-footer__heading{padding-bottom:10px}}.govuk-footer__navigation{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.govuk-footer__section{display:inline-block;margin-right:15px;margin-bottom:30px;margin-left:15px;vertical-align:top;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}@media (max-width:48.0525em){.govuk-footer__section{-webkit-flex-basis:200px;-ms-flex-preferred-size:200px;flex-basis:200px}}@media (min-width:48.0625em){.govuk-footer__section:first-child{-webkit-box-flex:2;-webkit-flex-grow:2;-ms-flex-positive:2;flex-grow:2}}.govuk-footer__list{margin:0;padding:0;list-style:none;-webkit-column-gap:30px;column-gap:30px}@media (min-width:48.0625em){.govuk-footer__list--columns-2{-webkit-column-count:2;column-count:2}.govuk-footer__list--columns-3{-webkit-column-count:3;column-count:3}}.govuk-footer__list-item{margin-bottom:15px}@media (min-width:40.0625em){.govuk-footer__list-item{margin-bottom:20px}}.govuk-footer__list-item:last-child{margin-bottom:0}.govuk-header{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;border-bottom:10px solid #fff;color:#fff;background:#0b0c0c}@media print{.govuk-header{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header{font-size:14pt;line-height:1.2}}.govuk-header__container--full-width{padding:0 15px;border-color:#005ea5}.govuk-header__container--full-width .govuk-header__menu-button{right:15px}.govuk-header__container{position:relative;margin-bottom:-10px;padding-top:10px;border-bottom:10px solid #005ea5}.govuk-header__container:after{content:"";display:block;clear:both}.govuk-header__logotype{margin-right:5px}.govuk-header__logotype-crown{margin-right:1px;fill:currentColor;vertical-align:middle}.govuk-header__logotype-crown-fallback-image{width:36px;height:32px;border:0;vertical-align:middle}.govuk-header__product-name{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:inline-table;padding-right:10px}@media print{.govuk-header__product-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__product-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__product-name{font-size:18pt;line-height:1.15}}.govuk-header__link{text-decoration:none}.govuk-header__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-header__link:link,.govuk-header__link:visited{color:#fff}.govuk-header__link:hover{text-decoration:underline}.govuk-header__link:focus{color:#0b0c0c}.govuk-header__link--homepage{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;font-size:30px;line-height:30px}@media print{.govuk-header__link--homepage{font-family:sans-serif}}.govuk-header__link--homepage:link,.govuk-header__link--homepage:visited{text-decoration:none}.govuk-header__link--homepage:active,.govuk-header__link--homepage:hover{margin-bottom:-1px;border-bottom:1px solid}.govuk-header__link--service-name{display:inline-block;margin-bottom:10px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111}@media print{.govuk-header__link--service-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__link--service-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__link--service-name{font-size:18pt;line-height:1.15}}.govuk-header__logo{margin-bottom:10px;padding-right:50px}@media (min-width:40.0625em){.govuk-header__logo{margin-bottom:10px}}@media (min-width:48.0625em){.govuk-header__logo{width:33.33%;padding-right:0;float:left;vertical-align:top}}@media (min-width:48.0625em){.govuk-header__content{width:66.66%;float:left}}.govuk-header__menu-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;display:none;position:absolute;top:20px;right:0;margin:0;padding:0;border:0;color:#fff;background:none}@media print{.govuk-header__menu-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__menu-button{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__menu-button{font-size:14pt;line-height:1.2}}.govuk-header__menu-button:hover{text-decoration:underline}.govuk-header__menu-button:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:8.66px 5px 0;border-top-color:inherit;content:"";margin-left:5px}.govuk-header__menu-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-header__menu-button{top:15px}}.govuk-header__menu-button--open:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(50% 0,0 100%,100% 100%);clip-path:polygon(50% 0,0 100%,100% 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:0 5px 8.66px;border-bottom-color:inherit}.govuk-header__navigation{display:block;margin:0;padding:0;list-style:none}@media (min-width:40.0625em){.govuk-header__navigation{margin-bottom:10px}}.js-enabled .govuk-header__menu-button{display:block}@media (min-width:48.0625em){.js-enabled .govuk-header__menu-button{display:none}}.js-enabled .govuk-header__navigation{display:none}@media (min-width:48.0625em){.js-enabled .govuk-header__navigation{display:block}}.js-enabled .govuk-header__navigation--open{display:block}@media (min-width:48.0625em){.govuk-header__navigation--end{margin:0;padding:5px 0;text-align:right}}.govuk-header__navigation--no-service-name{padding-top:40px}.govuk-header__navigation-item{padding:10px 0;border-bottom:1px solid #2e3133}@media (min-width:48.0625em){.govuk-header__navigation-item{display:inline-block;margin-right:15px;padding:5px 0;border:0}}.govuk-header__navigation-item a{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.14286;white-space:nowrap}@media print{.govuk-header__navigation-item a{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__navigation-item a{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__navigation-item a{font-size:14pt;line-height:1.2}}.govuk-header__navigation-item--active a:hover,.govuk-header__navigation-item--active a:link,.govuk-header__navigation-item--active a:visited{color:#1d8feb}.govuk-header__navigation-item--active a:focus{color:#0b0c0c}.govuk-header__navigation-item:last-child{margin-right:0}@media print{.govuk-header{border-bottom-width:0;color:#0b0c0c;background:rgba(0,0,0,0)}.govuk-header__logotype-crown-fallback-image{display:none}.govuk-header__link:link,.govuk-header__link:visited{color:#0b0c0c}.govuk-header__link:after{display:none}}.govuk-header__logotype-crown,.govuk-header__logotype-crown-fallback-image{position:relative;top:-4px}.govuk-header{padding-top:3px}.govuk-inset-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;padding:15px;margin-top:20px;margin-bottom:20px;clear:both;border-left:10px solid #bfc1c3}@media print{.govuk-inset-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-inset-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-inset-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-inset-text{margin-top:30px;margin-bottom:30px}}.govuk-inset-text :first-child{margin-top:0}.govuk-inset-text :last-child,.govuk-inset-text :only-child{margin-bottom:0}.govuk-panel{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;margin-bottom:15px;padding:35px;border:5px solid rgba(0,0,0,0);text-align:center}@media print{.govuk-panel{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-panel{font-size:14pt;line-height:1.15}}@media (max-width:40.0525em){.govuk-panel{padding:25px}}.govuk-panel--confirmation{color:#fff;background:#28a197}.govuk-panel__title{margin-top:0;margin-bottom:30px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375}@media print{.govuk-panel__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__title{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-panel__title{font-size:32pt;line-height:1.15}}.govuk-panel__title:last-child{margin-bottom:0}.govuk-panel__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:24px;font-size:1.5rem;line-height:1.04167}@media print{.govuk-panel__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__body{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-panel__body{font-size:24pt;line-height:1.05}}.govuk-tag{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.25;display:inline-block;padding:4px 8px 1px;outline:2px solid rgba(0,0,0,0);outline-offset:-2px;color:#fff;background-color:#005ea5;letter-spacing:1px;text-decoration:none;text-transform:uppercase}@media print{.govuk-tag{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tag{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-tag{font-size:14pt;line-height:1.25}}.govuk-tag--inactive{background-color:#6f777b}.govuk-phase-banner{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}.govuk-phase-banner__content{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;display:table;margin:0}@media print{.govuk-phase-banner__content{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-phase-banner__content{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-phase-banner__content{font-size:14pt;line-height:1.2;color:#000}}.govuk-phase-banner__content__tag{margin-right:10px}.govuk-phase-banner__text{display:table-cell;vertical-align:baseline}.govuk-tabs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-top:5px;margin-bottom:20px}@media print{.govuk-tabs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-tabs{margin-top:5px;margin-bottom:30px}}.govuk-tabs__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-bottom:5px}@media print{.govuk-tabs__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__title{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__title{font-size:14pt;line-height:1.15}}.govuk-tabs__list{margin:0;padding:0;list-style:none}@media (max-width:40.0525em){.govuk-tabs__list{margin-bottom:20px}}@media (max-width:40.0525em) and (min-width:40.0625em){.govuk-tabs__list{margin-bottom:30px}}.govuk-tabs__list-item{margin-left:25px}.govuk-tabs__list-item:before{content:"— ";margin-left:-25px;padding-right:5px}.govuk-tabs__tab{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:inline-block;padding-top:10px;padding-bottom:10px}.govuk-tabs__tab:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-tabs__tab:link{color:#005ea5}.govuk-tabs__tab:visited{color:#4c2c92}.govuk-tabs__tab:active,.govuk-tabs__tab:hover{color:#2b8cc4}.govuk-tabs__tab:focus{color:#0b0c0c}@media print{.govuk-tabs__tab{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__tab{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__tab{font-size:14pt;line-height:1.15}}.govuk-tabs__tab[aria-current=true]{color:#0b0c0c;text-decoration:none}.govuk-tabs__panel{margin-bottom:30px}@media (min-width:40.0625em){.govuk-tabs__panel{margin-bottom:50px}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__list{border-bottom:1px solid #bfc1c3}.js-enabled .govuk-tabs__list:after{content:"";display:block;clear:both}.js-enabled .govuk-tabs__list-item{margin-left:0}.js-enabled .govuk-tabs__list-item:before{content:none}.js-enabled .govuk-tabs__title{display:none}.js-enabled .govuk-tabs__tab{margin-right:5px;padding-right:20px;padding-left:20px;float:left;color:#0b0c0c;background-color:#f8f8f8;text-align:center;text-decoration:none}.js-enabled .govuk-tabs__tab--selected{margin-top:-5px;margin-bottom:-1px;padding:14px 19px 16px;border:1px solid #bfc1c3;border-bottom:0;color:#0b0c0c;background-color:#fff}.js-enabled .govuk-tabs__tab--selected:focus{background-color:rgba(0,0,0,0)}.js-enabled .govuk-tabs__panel{margin-bottom:0;padding:30px 20px;border:1px solid #bfc1c3;border-top:0}}@media (min-width:40.0625em) and (min-width:40.0625em){.js-enabled .govuk-tabs__panel{margin-bottom:0}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__panel--hidden{display:none}.js-enabled .govuk-tabs__panel>:last-child{margin-bottom:0}}.govuk-radios__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-radios__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__item{font-size:14pt;line-height:1.15}}.govuk-radios__item:last-child,.govuk-radios__item:last-of-type{margin-bottom:0}.govuk-radios__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-radios__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-radios__hint{display:block;padding-right:15px;padding-left:15px}.govuk-radios__input+.govuk-radios__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;border-radius:50%;background:rgba(0,0,0,0)}.govuk-radios__input+.govuk-radios__label:after{content:"";position:absolute;top:10px;left:10px;width:0;height:0;border:10px solid;border-radius:50%;opacity:0;background:currentColor}.govuk-radios__input:focus+.govuk-radios__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 4px #ffbf47}.govuk-radios__input:checked+.govuk-radios__label:after{opacity:1}.govuk-radios__input:disabled,.govuk-radios__input:disabled+.govuk-radios__label{cursor:default}.govuk-radios__input:disabled+.govuk-radios__label{opacity:.5}@media (min-width:40.0625em){.govuk-radios--inline:after{content:"";display:block;clear:both}.govuk-radios--inline .govuk-radios__item{margin-right:20px;float:left;clear:none}}.govuk-radios--inline.govuk-radios--conditional .govuk-radios__item{margin-right:0;float:none}.govuk-radios__divider{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:40px;margin-bottom:10px;text-align:center}@media print{.govuk-radios__divider{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__divider{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__divider{font-size:14pt;line-height:1.15;color:#000}}.govuk-radios__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-radios__conditional{margin-bottom:20px}}.js-enabled .govuk-radios__conditional--hidden{display:none}.govuk-radios__conditional>:last-child{margin-bottom:0}.govuk-select{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;max-width:100%;height:40px;padding:5px;border:2px solid #0b0c0c}@media print{.govuk-select{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-select{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-select{font-size:14pt;line-height:1.25}}.govuk-select:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-select:focus::-ms-value,.govuk-select option:active,.govuk-select option:checked{color:#fff;background-color:#005ea5}.govuk-select--error{border:4px solid #b10e1e}.govuk-skip-link{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:14px;font-size:.875rem;line-height:1.14286;display:block;padding:10px 15px}.govuk-skip-link:active,.govuk-skip-link:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}@media print{.govuk-skip-link{font-family:sans-serif}}.govuk-skip-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#0b0c0c}@media print{.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#000}}@media (min-width:40.0625em){.govuk-skip-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-skip-link{font-size:14pt;line-height:1.2}}.govuk-table{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:100%;margin-bottom:20px;border-spacing:0;border-collapse:collapse}@media print{.govuk-table{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-table{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-table{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-table{margin-bottom:30px}}.govuk-table__header{font-weight:700}.govuk-table__cell,.govuk-table__header{padding:10px 20px 10px 0;border-bottom:1px solid #bfc1c3;text-align:left}.govuk-table__cell--numeric{font-family:ntatabularnumbers,nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400}@media print{.govuk-table__cell--numeric{font-family:sans-serif}}.govuk-table__cell--numeric,.govuk-table__header--numeric{text-align:right}.govuk-table__cell:last-child,.govuk-table__header:last-child{padding-right:0}.govuk-table__caption{font-weight:700;display:table-caption;text-align:left}.govuk-textarea{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;display:block;width:100%;min-height:40px;margin-bottom:20px;padding:5px;resize:vertical;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none}@media print{.govuk-textarea{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-textarea{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-textarea{font-size:14pt;line-height:1.25}}.govuk-textarea:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-textarea{margin-bottom:30px}}.govuk-textarea--error{border:4px solid #b10e1e}.govuk-warning-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;position:relative;margin-bottom:20px;padding:10px 0}@media print{.govuk-warning-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-warning-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-warning-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-warning-text{margin-bottom:30px}}.govuk-warning-text__assistive{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;padding:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;border:0!important;white-space:nowrap!important}.govuk-warning-text__icon{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;position:absolute;top:50%;left:0;min-width:32px;min-height:29px;margin-top:-20px;padding-top:3px;border:3px solid #0b0c0c;border-radius:50%;color:#fff;background:#0b0c0c;font-size:1.6em;line-height:29px;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media print{.govuk-warning-text__icon{font-family:sans-serif}}.govuk-warning-text__text{display:block;padding-left:50px}.govuk-clearfix:after{content:"";display:block;clear:both}.govuk-visually-hidden{padding:0!important;border:0!important}.govuk-visually-hidden,.govuk-visually-hidden-focusable{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important}.govuk-visually-hidden-focusable:active,.govuk-visually-hidden-focusable:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}.govuk-\!-display-inline{display:inline!important}.govuk-\!-display-inline-block{display:inline-block!important}.govuk-\!-display-block{display:block!important}.govuk-\!-margin-0{margin:0!important}@media (min-width:40.0625em){.govuk-\!-margin-0{margin:0!important}}.govuk-\!-margin-top-0{margin-top:0!important}@media (min-width:40.0625em){.govuk-\!-margin-top-0{margin-top:0!important}}.govuk-\!-margin-right-0{margin-right:0!important}@media (min-width:40.0625em){.govuk-\!-margin-right-0{margin-right:0!important}}.govuk-\!-margin-bottom-0{margin-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-0{margin-bottom:0!important}}.govuk-\!-margin-left-0{margin-left:0!important}@media (min-width:40.0625em){.govuk-\!-margin-left-0{margin-left:0!important}}.govuk-\!-margin-1{margin:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-1{margin:5px!important}}.govuk-\!-margin-top-1{margin-top:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-1{margin-top:5px!important}}.govuk-\!-margin-right-1{margin-right:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-1{margin-right:5px!important}}.govuk-\!-margin-bottom-1{margin-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-1{margin-bottom:5px!important}}.govuk-\!-margin-left-1{margin-left:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-1{margin-left:5px!important}}.govuk-\!-margin-2{margin:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-2{margin:10px!important}}.govuk-\!-margin-top-2{margin-top:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-2{margin-top:10px!important}}.govuk-\!-margin-right-2{margin-right:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-2{margin-right:10px!important}}.govuk-\!-margin-bottom-2{margin-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-2{margin-bottom:10px!important}}.govuk-\!-margin-left-2{margin-left:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-2{margin-left:10px!important}}.govuk-\!-margin-3{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-3{margin:15px!important}}.govuk-\!-margin-top-3{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-3{margin-top:15px!important}}.govuk-\!-margin-right-3{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-3{margin-right:15px!important}}.govuk-\!-margin-bottom-3{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-3{margin-bottom:15px!important}}.govuk-\!-margin-left-3{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-3{margin-left:15px!important}}.govuk-\!-margin-4{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-4{margin:20px!important}}.govuk-\!-margin-top-4{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-4{margin-top:20px!important}}.govuk-\!-margin-right-4{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-4{margin-right:20px!important}}.govuk-\!-margin-bottom-4{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-4{margin-bottom:20px!important}}.govuk-\!-margin-left-4{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-4{margin-left:20px!important}}.govuk-\!-margin-5{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-5{margin:25px!important}}.govuk-\!-margin-top-5{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-5{margin-top:25px!important}}.govuk-\!-margin-right-5{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-5{margin-right:25px!important}}.govuk-\!-margin-bottom-5{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-5{margin-bottom:25px!important}}.govuk-\!-margin-left-5{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-5{margin-left:25px!important}}.govuk-\!-margin-6{margin:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-6{margin:30px!important}}.govuk-\!-margin-top-6{margin-top:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-6{margin-top:30px!important}}.govuk-\!-margin-right-6{margin-right:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-6{margin-right:30px!important}}.govuk-\!-margin-bottom-6{margin-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-6{margin-bottom:30px!important}}.govuk-\!-margin-left-6{margin-left:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-6{margin-left:30px!important}}.govuk-\!-margin-7{margin:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-7{margin:40px!important}}.govuk-\!-margin-top-7{margin-top:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-7{margin-top:40px!important}}.govuk-\!-margin-right-7{margin-right:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-7{margin-right:40px!important}}.govuk-\!-margin-bottom-7{margin-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-7{margin-bottom:40px!important}}.govuk-\!-margin-left-7{margin-left:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-7{margin-left:40px!important}}.govuk-\!-margin-8{margin:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-8{margin:50px!important}}.govuk-\!-margin-top-8{margin-top:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-8{margin-top:50px!important}}.govuk-\!-margin-right-8{margin-right:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-8{margin-right:50px!important}}.govuk-\!-margin-bottom-8{margin-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-8{margin-bottom:50px!important}}.govuk-\!-margin-left-8{margin-left:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-8{margin-left:50px!important}}.govuk-\!-margin-9{margin:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-9{margin:60px!important}}.govuk-\!-margin-top-9{margin-top:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-9{margin-top:60px!important}}.govuk-\!-margin-right-9{margin-right:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-9{margin-right:60px!important}}.govuk-\!-margin-bottom-9{margin-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-9{margin-bottom:60px!important}}.govuk-\!-margin-left-9{margin-left:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-9{margin-left:60px!important}}.govuk-\!-padding-0{padding:0!important}@media (min-width:40.0625em){.govuk-\!-padding-0{padding:0!important}}.govuk-\!-padding-top-0{padding-top:0!important}@media (min-width:40.0625em){.govuk-\!-padding-top-0{padding-top:0!important}}.govuk-\!-padding-right-0{padding-right:0!important}@media (min-width:40.0625em){.govuk-\!-padding-right-0{padding-right:0!important}}.govuk-\!-padding-bottom-0{padding-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-0{padding-bottom:0!important}}.govuk-\!-padding-left-0{padding-left:0!important}@media (min-width:40.0625em){.govuk-\!-padding-left-0{padding-left:0!important}}.govuk-\!-padding-1{padding:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-1{padding:5px!important}}.govuk-\!-padding-top-1{padding-top:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-1{padding-top:5px!important}}.govuk-\!-padding-right-1{padding-right:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-1{padding-right:5px!important}}.govuk-\!-padding-bottom-1{padding-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-1{padding-bottom:5px!important}}.govuk-\!-padding-left-1{padding-left:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-1{padding-left:5px!important}}.govuk-\!-padding-2{padding:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-2{padding:10px!important}}.govuk-\!-padding-top-2{padding-top:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-2{padding-top:10px!important}}.govuk-\!-padding-right-2{padding-right:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-2{padding-right:10px!important}}.govuk-\!-padding-bottom-2{padding-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-2{padding-bottom:10px!important}}.govuk-\!-padding-left-2{padding-left:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-2{padding-left:10px!important}}.govuk-\!-padding-3{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-3{padding:15px!important}}.govuk-\!-padding-top-3{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-3{padding-top:15px!important}}.govuk-\!-padding-right-3{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-3{padding-right:15px!important}}.govuk-\!-padding-bottom-3{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-3{padding-bottom:15px!important}}.govuk-\!-padding-left-3{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-3{padding-left:15px!important}}.govuk-\!-padding-4{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-4{padding:20px!important}}.govuk-\!-padding-top-4{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-4{padding-top:20px!important}}.govuk-\!-padding-right-4{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-4{padding-right:20px!important}}.govuk-\!-padding-bottom-4{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-4{padding-bottom:20px!important}}.govuk-\!-padding-left-4{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-4{padding-left:20px!important}}.govuk-\!-padding-5{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-5{padding:25px!important}}.govuk-\!-padding-top-5{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-5{padding-top:25px!important}}.govuk-\!-padding-right-5{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-5{padding-right:25px!important}}.govuk-\!-padding-bottom-5{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-5{padding-bottom:25px!important}}.govuk-\!-padding-left-5{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-5{padding-left:25px!important}}.govuk-\!-padding-6{padding:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-6{padding:30px!important}}.govuk-\!-padding-top-6{padding-top:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-6{padding-top:30px!important}}.govuk-\!-padding-right-6{padding-right:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-6{padding-right:30px!important}}.govuk-\!-padding-bottom-6{padding-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-6{padding-bottom:30px!important}}.govuk-\!-padding-left-6{padding-left:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-6{padding-left:30px!important}}.govuk-\!-padding-7{padding:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-7{padding:40px!important}}.govuk-\!-padding-top-7{padding-top:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-7{padding-top:40px!important}}.govuk-\!-padding-right-7{padding-right:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-7{padding-right:40px!important}}.govuk-\!-padding-bottom-7{padding-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-7{padding-bottom:40px!important}}.govuk-\!-padding-left-7{padding-left:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-7{padding-left:40px!important}}.govuk-\!-padding-8{padding:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-8{padding:50px!important}}.govuk-\!-padding-top-8{padding-top:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-8{padding-top:50px!important}}.govuk-\!-padding-right-8{padding-right:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-8{padding-right:50px!important}}.govuk-\!-padding-bottom-8{padding-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-8{padding-bottom:50px!important}}.govuk-\!-padding-left-8{padding-left:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-8{padding-left:50px!important}}.govuk-\!-padding-9{padding:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-9{padding:60px!important}}.govuk-\!-padding-top-9{padding-top:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-9{padding-top:60px!important}}.govuk-\!-padding-right-9{padding-right:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-9{padding-right:60px!important}}.govuk-\!-padding-bottom-9{padding-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-9{padding-bottom:60px!important}}.govuk-\!-padding-left-9{padding-left:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-9{padding-left:60px!important}}.govuk-\!-font-size-80{font-size:53px!important;font-size:3.3125rem!important;line-height:1.03774!important}@media (min-width:40.0625em){.govuk-\!-font-size-80{font-size:80px!important;font-size:5rem!important;line-height:1!important}}@media print{.govuk-\!-font-size-80{font-size:53pt!important;line-height:1.1!important}}.govuk-\!-font-size-48{font-size:32px!important;font-size:2rem!important;line-height:1.09375!important}@media (min-width:40.0625em){.govuk-\!-font-size-48{font-size:48px!important;font-size:3rem!important;line-height:1.04167!important}}@media print{.govuk-\!-font-size-48{font-size:32pt!important;line-height:1.15!important}}.govuk-\!-font-size-36{font-size:24px!important;font-size:1.5rem!important;line-height:1.04167!important}@media (min-width:40.0625em){.govuk-\!-font-size-36{font-size:36px!important;font-size:2.25rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-36{font-size:24pt!important;line-height:1.05!important}}.govuk-\!-font-size-27{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-27{font-size:27px!important;font-size:1.6875rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-27{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-24{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-24{font-size:24px!important;font-size:1.5rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-24{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-19{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-19{font-size:19px!important;font-size:1.1875rem!important;line-height:1.31579!important}}@media print{.govuk-\!-font-size-19{font-size:14pt!important;line-height:1.15!important}}.govuk-\!-font-size-16{font-size:14px!important;font-size:.875rem!important;line-height:1.14286!important}@media (min-width:40.0625em){.govuk-\!-font-size-16{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-16{font-size:14pt!important;line-height:1.2!important}}.govuk-\!-font-size-14{font-size:12px!important;font-size:.75rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-14{font-size:14px!important;font-size:.875rem!important;line-height:1.42857!important}}@media print{.govuk-\!-font-size-14{font-size:12pt!important;line-height:1.2!important}}.govuk-\!-font-weight-regular{font-weight:400!important}.govuk-\!-font-weight-bold{font-weight:700!important}.govuk-\!-width-full,.govuk-\!-width-three-quarters{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-three-quarters{width:75%!important}}.govuk-\!-width-two-thirds{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-two-thirds{width:66.66%!important}}.govuk-\!-width-one-half{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-half{width:50%!important}}.govuk-\!-width-one-third{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-third{width:33.33%!important}}.govuk-\!-width-one-quarter{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-quarter{width:25%!important}} \ No newline at end of file +/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-f38ad40456-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-458f8ea81c-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-a2452cb66f-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-f38c792ac2-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-851b10ccdd-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-62cc6f0a28-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-b89238d840-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-784c21afb8-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@media print{.govuk-link{font-family:sans-serif}}.govuk-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-link:link{color:#005ea5}.govuk-link:visited{color:#4c2c92}.govuk-link:active,.govuk-link:hover{color:#2b8cc4}.govuk-link:focus{color:#0b0c0c}@media print{.govuk-link[href^="/"]:after,.govuk-link[href^="http://"]:after,.govuk-link[href^="https://"]:after{content:" (" attr(href) ")";font-size:90%;word-wrap:break-word}}.govuk-link--muted:active,.govuk-link--muted:hover,.govuk-link--muted:link,.govuk-link--muted:visited{color:#6f777b}.govuk-link--muted:focus,.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#0b0c0c}@media print{.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#000}}.govuk-link--no-visited-state:link,.govuk-link--no-visited-state:visited{color:#005ea5}.govuk-link--no-visited-state:active,.govuk-link--no-visited-state:hover{color:#2b8cc4}.govuk-link--no-visited-state:focus,.govuk-list{color:#0b0c0c}.govuk-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px;padding-left:0;list-style-type:none}@media print{.govuk-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-list{margin-bottom:20px}}.govuk-list .govuk-list{margin-top:10px}.govuk-list>li{margin-bottom:5px}.govuk-list--bullet{padding-left:20px;list-style-type:disc}.govuk-list--number{padding-left:20px;list-style-type:decimal}.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:0}@media (min-width:40.0625em){.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:5px}}.govuk-template{background-color:#dee0e2}.govuk-template__body{margin:0;background-color:#fff}.govuk-heading-xl{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;display:block;margin-top:0;margin-bottom:30px}@media print{.govuk-heading-xl{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-heading-xl{font-size:32pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-xl{margin-bottom:50px}}.govuk-heading-l{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;display:block;margin-top:0;margin-bottom:20px}@media print{.govuk-heading-l{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-heading-l{font-size:24pt;line-height:1.05}}@media (min-width:40.0625em){.govuk-heading-l{margin-bottom:30px}}.govuk-heading-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-heading-m{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-m{margin-bottom:20px}}.govuk-heading-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-heading-s{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-s{margin-bottom:20px}}.govuk-caption-xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-xl{font-size:27px;font-size:1.6875rem;line-height:1.11111}}@media print{.govuk-caption-xl{font-size:18pt;line-height:1.15}}.govuk-caption-l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-l{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-caption-l{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-caption-l{margin-bottom:0}}.govuk-caption-m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;color:#6f777b}@media print{.govuk-caption-m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-caption-m{font-size:14pt;line-height:1.15}}.govuk-body-l,.govuk-body-lead{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:20px}@media print{.govuk-body-l,.govuk-body-lead{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-body-l,.govuk-body-lead{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{margin-bottom:30px}}.govuk-body,.govuk-body-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body,.govuk-body-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-body,.govuk-body-m{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{margin-bottom:20px}}.govuk-body-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;margin-top:0;margin-bottom:15px}@media print{.govuk-body-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-s{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-body-s{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-s{margin-bottom:20px}}.govuk-body-xs{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:12px;font-size:.75rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body-xs{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-xs{font-size:14px;font-size:.875rem;line-height:1.42857}}@media print{.govuk-body-xs{font-size:12pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-xs{margin-bottom:20px}}.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:5px}@media (min-width:40.0625em){.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:10px}}.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:15px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:20px}}.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:5px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:10px}}.govuk-section-break{margin:0;border:0}.govuk-section-break--xl{margin-top:30px;margin-bottom:30px}@media (min-width:40.0625em){.govuk-section-break--xl{margin-top:50px;margin-bottom:50px}}.govuk-section-break--l{margin-top:20px;margin-bottom:20px}@media (min-width:40.0625em){.govuk-section-break--l{margin-top:30px;margin-bottom:30px}}.govuk-section-break--m{margin-top:15px;margin-bottom:15px}@media (min-width:40.0625em){.govuk-section-break--m{margin-top:20px;margin-bottom:20px}}.govuk-section-break--visible{border-bottom:1px solid #bfc1c3}.govuk-form-group{margin-bottom:20px}@media (min-width:40.0625em){.govuk-form-group{margin-bottom:30px}}.govuk-form-group .govuk-form-group:last-of-type{margin-bottom:0}.govuk-form-group--error{padding-left:15px;border-left:5px solid #b10e1e}.govuk-form-group--error .govuk-form-group{padding:0;border:0}.govuk-grid-row{margin-right:-15px;margin-left:-15px}.govuk-grid-row:after{content:"";display:block;clear:both}.govuk-grid-column-one-quarter{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-quarter{width:25%;float:left}}.govuk-grid-column-one-third{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-third{width:33.3333%;float:left}}.govuk-grid-column-one-half{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-half{width:50%;float:left}}.govuk-grid-column-two-thirds{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-two-thirds{width:66.6666%;float:left}}.govuk-grid-column-three-quarters{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-three-quarters{width:75%;float:left}}.govuk-grid-column-full{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-full{width:100%;float:left}}.govuk-grid-column-one-quarter-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-quarter-from-desktop{width:25%;float:left}}.govuk-grid-column-one-third-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-third-from-desktop{width:33.3333%;float:left}}.govuk-grid-column-one-half-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-half-from-desktop{width:50%;float:left}}.govuk-grid-column-two-thirds-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-two-thirds-from-desktop{width:66.6666%;float:left}}.govuk-grid-column-three-quarters-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-three-quarters-from-desktop{width:75%;float:left}}.govuk-grid-column-full-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-full-from-desktop{width:100%;float:left}}.govuk-main-wrapper{padding-top:20px;padding-bottom:20px;display:block}@media (min-width:40.0625em){.govuk-main-wrapper{padding-top:30px;padding-bottom:30px}}.govuk-main-wrapper--l{padding-top:30px}@media (min-width:40.0625em){.govuk-main-wrapper--l{padding-top:50px}}.govuk-width-container{max-width:960px;margin:0 15px}@media (min-width:40.0625em){.govuk-width-container{margin:0 30px}}@media (min-width:1020px){.govuk-width-container{margin:0 auto}}.govuk-accordion{margin-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-accordion{margin-bottom:30px}}.govuk-accordion__section{border-top:1px solid #bfc1c3}.govuk-accordion__section-header{padding-bottom:15px}.govuk-accordion__section-heading{margin-top:0;margin-bottom:0}.govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:0;padding-top:15px}@media print{.govuk-accordion__section-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-accordion__section-button{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-accordion__section-button{font-size:18pt;line-height:1.15}}.govuk-accordion__section-summary{margin-top:10px;margin-bottom:0}.js-enabled .govuk-accordion__section-content{display:none;padding-top:15px;padding-bottom:15px}@media (min-width:40.0625em){.js-enabled .govuk-accordion__section-content{padding-top:15px;padding-bottom:15px}}.js-enabled .govuk-accordion__section-content>:last-child{margin-bottom:0}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-content{display:block}.js-enabled .govuk-accordion__open-all{font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline;border-width:0;color:#005ea5;background:none;cursor:pointer}@media (min-width:40.0625em){.js-enabled .govuk-accordion__open-all{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.js-enabled .govuk-accordion__open-all{font-size:14pt;line-height:1.2;font-family:sans-serif}}.js-enabled .govuk-accordion__open-all:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;background:none}.js-enabled .govuk-accordion__section-header{position:relative;padding-right:40px;cursor:pointer}.js-enabled .govuk-accordion__section-header:hover{background-color:#f8f8f8}.js-enabled .govuk-accordion__section-header--focused{outline:3px solid #ffbf47;outline-offset:0}.js-enabled .govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100%;margin-top:0;margin-bottom:0;margin-left:0;padding-top:15px;padding-bottom:0;padding-left:0;border-width:0;color:#005ea5;background:none;text-align:left;cursor:pointer}@media print{.js-enabled .govuk-accordion__section-button{font-family:sans-serif}}.js-enabled .govuk-accordion__section-button:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;outline:none;background:none}.js-enabled .govuk-accordion__section-button:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.js-enabled .govuk-accordion__controls{text-align:right}.js-enabled .govuk-accordion__icon{position:absolute;top:50%;right:15px;width:16px;height:16px;margin-top:-8px}.js-enabled .govuk-accordion__icon:after,.js-enabled .govuk-accordion__icon:before{content:"";box-sizing:border-box;position:absolute;top:0;right:0;bottom:0;left:0;width:25%;height:25%;margin:auto;border:2px solid rgba(0,0,0,0);background-color:#0b0c0c}.js-enabled .govuk-accordion__icon:before{width:100%}.js-enabled .govuk-accordion__icon:after{height:100%}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__icon:after{content:" ";display:none}.govuk-back-link{font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;position:relative;margin-top:15px;margin-bottom:15px;padding-left:14px;border-bottom:1px solid #0b0c0c;text-decoration:none}@media (min-width:40.0625em){.govuk-back-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-back-link{font-size:14pt;line-height:1.2;font-family:sans-serif}}.govuk-back-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#0b0c0c}@media print{.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#000}}.govuk-back-link:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 50%,100% 100%,100% 0);clip-path:polygon(0 50%,100% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:5px 6px 5px 0;border-right-color:inherit;content:"";position:absolute;left:0;margin:auto}.govuk-back-link:before{top:-1px;bottom:1px}.govuk-breadcrumbs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;margin-top:15px;margin-bottom:10px}@media print{.govuk-breadcrumbs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-breadcrumbs{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-breadcrumbs{font-size:14pt;line-height:1.2;color:#000}}.govuk-breadcrumbs__list{margin:0;padding:0;list-style-type:none}.govuk-breadcrumbs__list:after{content:"";display:block;clear:both}.govuk-breadcrumbs__list-item{display:inline-block;position:relative;margin-bottom:5px;margin-left:10px;padding-left:15.655px;float:left}.govuk-breadcrumbs__list-item:before{content:"";display:block;position:absolute;top:-1px;bottom:1px;left:-3.31px;width:7px;height:7px;margin:auto 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);border:solid;border-width:1px 1px 0 0;border-color:#6f777b}.govuk-breadcrumbs__list-item:first-child{margin-left:0;padding-left:0}.govuk-breadcrumbs__list-item:first-child:before{content:none;display:none}.govuk-breadcrumbs__link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media print{.govuk-breadcrumbs__link{font-family:sans-serif}}.govuk-breadcrumbs__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#0b0c0c}@media print{.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#000}}.govuk-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.1875;box-sizing:border-box;display:inline-block;position:relative;width:100%;margin-top:0;margin-bottom:22px;padding:7px 10px;border:2px solid rgba(0,0,0,0);border-radius:0;color:#fff;background-color:#00823b;box-shadow:0 2px 0 #003618;text-align:center;vertical-align:top;cursor:pointer;-webkit-appearance:none}@media print{.govuk-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-button{font-size:19px;font-size:1.1875rem;line-height:1}}@media print{.govuk-button{font-size:14pt;line-height:19px}}.govuk-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-button{margin-bottom:32px;width:auto}}.govuk-button:active,.govuk-button:hover,.govuk-button:link,.govuk-button:visited{color:#fff;text-decoration:none}.govuk-button::-moz-focus-inner{padding:0;border:0}.govuk-button:focus,.govuk-button:hover{background-color:#00692f}.govuk-button:active{top:2px;box-shadow:none}.govuk-button:before{content:"";display:block;position:absolute;top:-2px;right:-2px;bottom:-4px;left:-2px;background:rgba(0,0,0,0)}.govuk-button:active:before{top:-4px}.govuk-button--disabled,.govuk-button[disabled=disabled],.govuk-button[disabled]{opacity:.5;background:#00823b}.govuk-button--disabled:hover,.govuk-button[disabled=disabled]:hover,.govuk-button[disabled]:hover{background-color:#00823b;cursor:default}.govuk-button--disabled:focus,.govuk-button[disabled=disabled]:focus,.govuk-button[disabled]:focus{outline:none}.govuk-button--disabled:active,.govuk-button[disabled=disabled]:active,.govuk-button[disabled]:active{top:0;box-shadow:0 2px 0 #003618}.govuk-button--start{font-weight:700;font-size:18px;font-size:1.125rem;line-height:1;min-height:auto;padding:8px 40px 8px 15px;background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer.png);background-repeat:no-repeat;background-position:100% 50%}@media (min-width:40.0625em){.govuk-button--start{font-size:24px;font-size:1.5rem;line-height:1}}@media print{.govuk-button--start{font-size:18pt;line-height:1}}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-button--start{background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer-2x.png);background-size:30px 19px}}.govuk-button,.govuk-button--start{padding-top:9px;padding-bottom:6px}.govuk-error-message{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;clear:both;color:#b10e1e}@media print{.govuk-error-message{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-message{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-message{font-size:14pt;line-height:1.15}}.govuk-fieldset{margin:0;padding:0;border:0}.govuk-fieldset:after{content:"";display:block;clear:both}.govuk-fieldset__legend{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;box-sizing:border-box;display:table;max-width:100%;margin-bottom:10px;padding:0;overflow:hidden;white-space:normal}@media print{.govuk-fieldset__legend{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend{font-size:14pt;line-height:1.15;color:#000}}.govuk-fieldset__legend--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-fieldset__legend--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-fieldset__legend--xl{font-size:32pt;line-height:1.15}}.govuk-fieldset__legend--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-fieldset__legend--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-fieldset__legend--l{font-size:24pt;line-height:1.05}}.govuk-fieldset__legend--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:15px}@media print{.govuk-fieldset__legend--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-fieldset__legend--m{font-size:18pt;line-height:1.15}}.govuk-fieldset__legend--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-fieldset__legend--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend--s{font-size:14pt;line-height:1.15}}.govuk-fieldset__heading{margin:0;font-size:inherit;font-weight:inherit}.govuk-hint{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;color:#6f777b}@media print{.govuk-hint{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-hint{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-hint{font-size:14pt;line-height:1.15}}.govuk-label:not(.govuk-label--m):not(.govuk-label--l):not(.govuk-label--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend:not(.govuk-fieldset__legend--m):not(.govuk-fieldset__legend--l):not(.govuk-fieldset__legend--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend+.govuk-hint{margin-top:-5px}.govuk-label{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;display:block;margin-bottom:5px}@media print{.govuk-label{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label{font-size:14pt;line-height:1.15;color:#000}}.govuk-label--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-label--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-label--xl{font-size:32pt;line-height:1.15}}.govuk-label--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-label--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-label--l{font-size:24pt;line-height:1.05}}.govuk-label--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:10px}@media print{.govuk-label--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-label--m{font-size:18pt;line-height:1.15}}.govuk-label--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-label--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label--s{font-size:14pt;line-height:1.15}}.govuk-label-wrapper{margin:0}.govuk-checkboxes__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-checkboxes__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-checkboxes__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-checkboxes__item{font-size:14pt;line-height:1.15}}.govuk-checkboxes__item:last-child,.govuk-checkboxes__item:last-of-type{margin-bottom:0}.govuk-checkboxes__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-checkboxes__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-checkboxes__hint{display:block;padding-right:15px;padding-left:15px}.govuk-checkboxes__input+.govuk-checkboxes__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;background:rgba(0,0,0,0)}.govuk-checkboxes__input+.govuk-checkboxes__label:after{content:"";position:absolute;top:11px;left:9px;width:18px;height:7px;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);border:solid;border-width:0 0 5px 5px;border-top-color:rgba(0,0,0,0);opacity:0;background:rgba(0,0,0,0)}.govuk-checkboxes__input:focus+.govuk-checkboxes__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 3px #ffbf47}.govuk-checkboxes__input:checked+.govuk-checkboxes__label:after{opacity:1}.govuk-checkboxes__input:disabled,.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{cursor:default}.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{opacity:.5}.govuk-checkboxes__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-checkboxes__conditional{margin-bottom:20px}}.js-enabled .govuk-checkboxes__conditional--hidden{display:none}.govuk-checkboxes__conditional>:last-child{margin-bottom:0}.govuk-character-count{margin-bottom:20px}@media (min-width:40.0625em){.govuk-character-count{margin-bottom:30px}}.govuk-character-count .govuk-form-group,.govuk-character-count .govuk-textarea{margin-bottom:5px}.govuk-character-count .govuk-textarea--error{padding:3px}.govuk-character-count__message{margin-top:0;margin-bottom:0}.govuk-character-count__message--disabled{visibility:hidden}.govuk-summary-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin:0 0 20px}@media print{.govuk-summary-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-summary-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-summary-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-summary-list{display:table;width:100%;margin-bottom:30px}}@media (max-width:40.0525em){.govuk-summary-list__row{margin-bottom:15px;border-bottom:1px solid #bfc1c3}}@media (min-width:40.0625em){.govuk-summary-list__row{display:table-row}}.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{margin:0}@media (min-width:40.0625em){.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{display:table-cell;padding-right:20px;padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}}.govuk-summary-list__actions{margin-bottom:15px}@media (min-width:40.0625em){.govuk-summary-list__actions{padding-right:0}}.govuk-summary-list__key{margin-bottom:5px;font-weight:700;word-break:break-word}@media (min-width:40.0625em){.govuk-summary-list__key{width:30%}}@media (max-width:40.0525em){.govuk-summary-list__value{margin-bottom:15px}}.govuk-summary-list__value>p{margin-bottom:10px}.govuk-summary-list__value>:last-child{margin-bottom:0}.govuk-summary-list__actions-list{width:100%;margin:0;padding:0}@media (min-width:40.0625em){.govuk-summary-list__actions-list{text-align:right}}.govuk-summary-list__actions-list-item{display:inline;margin-right:10px;padding-right:10px}.govuk-summary-list__actions-list-item:not(:last-child){border-right:1px solid #bfc1c3}.govuk-summary-list__actions-list-item:last-child{margin-right:0;padding-right:0;border:0}.govuk-summary-list--no-border .govuk-summary-list__actions,.govuk-summary-list--no-border .govuk-summary-list__key,.govuk-summary-list--no-border .govuk-summary-list__row,.govuk-summary-list--no-border .govuk-summary-list__value{border:0}.govuk-input{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;width:100%;height:40px;margin-top:0;padding:5px;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media print{.govuk-input{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-input{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-input{font-size:14pt;line-height:1.15}}.govuk-input:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-input::-webkit-inner-spin-button,.govuk-input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.govuk-input[type=number]{-moz-appearance:textfield}.govuk-input--error{border:4px solid #b10e1e}.govuk-input--width-30{max-width:59ex}.govuk-input--width-20{max-width:41ex}.govuk-input--width-10{max-width:23ex}.govuk-input--width-5{max-width:10.8ex}.govuk-input--width-4{max-width:9ex}.govuk-input--width-3{max-width:7.2ex}.govuk-input--width-2{max-width:5.4ex}.govuk-date-input{font-size:0}.govuk-date-input:after{content:"";display:block;clear:both}.govuk-date-input__item{display:inline-block;margin-right:20px;margin-bottom:0}.govuk-date-input__label{display:block}.govuk-date-input__input{margin-bottom:0}.govuk-details{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-bottom:20px;display:block}@media print{.govuk-details{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-details{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-details{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-details{margin-bottom:30px}}.govuk-details__summary{display:inline-block;position:relative;margin-bottom:5px;padding-left:25px;color:#005ea5;cursor:pointer}.govuk-details__summary-text{text-decoration:underline}.govuk-details__summary:hover{color:#2b8cc4}.govuk-details__summary:focus{outline:4px solid #ffbf47;outline-offset:-1px;color:#0b0c0c;background:#ffbf47}.govuk-details__summary::-webkit-details-marker{display:none}.govuk-details__summary:before{content:"";position:absolute;top:0;bottom:0;left:0;margin:auto;display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,100% 50%,0 100%);clip-path:polygon(0 0,100% 50%,0 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:7px 0 7px 12.124px;border-left-color:inherit}.govuk-details[open]>.govuk-details__summary:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:12.124px 7px 0;border-top-color:inherit}.govuk-details__text{padding:15px 15px 15px 20px;border-left:5px solid #bfc1c3}.govuk-details__text p{margin-top:0;margin-bottom:20px}.govuk-details__text>:last-child{margin-bottom:0}.govuk-error-summary{color:#0b0c0c;padding:15px;margin-bottom:30px;border:4px solid #b10e1e}@media print{.govuk-error-summary{color:#000}}@media (min-width:40.0625em){.govuk-error-summary{padding:20px;margin-bottom:50px}}.govuk-error-summary:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-error-summary{border:5px solid #b10e1e}}.govuk-error-summary__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:15px}@media print{.govuk-error-summary__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__title{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-error-summary__title{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-error-summary__title{margin-bottom:20px}}.govuk-error-summary__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-error-summary__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__body{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-summary__body{font-size:14pt;line-height:1.15}}.govuk-error-summary__body p{margin-top:0;margin-bottom:15px}@media (min-width:40.0625em){.govuk-error-summary__body p{margin-bottom:20px}}.govuk-error-summary__list{margin-top:0;margin-bottom:0}.govuk-error-summary__list a{font-weight:700}.govuk-error-summary__list a:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-error-summary__list a:active,.govuk-error-summary__list a:hover,.govuk-error-summary__list a:link,.govuk-error-summary__list a:visited{color:#b10e1e}.govuk-error-summary__list a:focus{color:#0b0c0c}.govuk-file-upload{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c}@media print{.govuk-file-upload{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-file-upload{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-file-upload{font-size:14pt;line-height:1.15;color:#000}}.govuk-file-upload:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-file-upload--error{border:4px solid #b10e1e}.govuk-footer{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;padding-top:25px;padding-bottom:15px;border-top:1px solid #a1acb2;color:#454a4c;background:#dee0e2}@media print{.govuk-footer{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-footer{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-footer{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-footer{padding-top:40px;padding-bottom:25px}}.govuk-footer__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-footer__link:link,.govuk-footer__link:visited{color:#454a4c}.govuk-footer__link:active,.govuk-footer__link:hover{color:#171819}.govuk-footer__link:focus{color:#0b0c0c}.govuk-footer__section-break{margin:0 0 30px;border:0;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__section-break{margin-bottom:50px}}.govuk-footer__meta{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:end;-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.govuk-footer__meta-item{margin-right:15px;margin-bottom:25px;margin-left:15px}.govuk-footer__meta-item--grow{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}@media (max-width:40.0525em){.govuk-footer__meta-item--grow{-webkit-flex-basis:320px;-ms-flex-preferred-size:320px;flex-basis:320px}}.govuk-footer__licence-logo{display:inline-block;margin-right:10px;vertical-align:top}@media (max-width:48.0525em){.govuk-footer__licence-logo{margin-bottom:15px}}.govuk-footer__licence-description{display:inline-block}.govuk-footer__copyright-logo{display:inline-block;min-width:125px;padding-top:112px;background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest.png);background-repeat:no-repeat;background-position:50% 0;background-size:125px 102px;text-align:center;text-decoration:none;white-space:nowrap}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-footer__copyright-logo{background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest-2x.png)}}.govuk-footer__inline-list{margin-top:0;margin-bottom:15px;padding:0}.govuk-footer__meta-custom{margin-bottom:20px}.govuk-footer__inline-list-item{display:inline-block;margin-right:15px;margin-bottom:5px}.govuk-footer__heading{margin-bottom:25px;padding-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__heading{margin-bottom:40px}}@media (max-width:40.0525em){.govuk-footer__heading{padding-bottom:10px}}.govuk-footer__navigation{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.govuk-footer__section{display:inline-block;margin-right:15px;margin-bottom:30px;margin-left:15px;vertical-align:top;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}@media (max-width:48.0525em){.govuk-footer__section{-webkit-flex-basis:200px;-ms-flex-preferred-size:200px;flex-basis:200px}}@media (min-width:48.0625em){.govuk-footer__section:first-child{-webkit-box-flex:2;-webkit-flex-grow:2;-ms-flex-positive:2;flex-grow:2}}.govuk-footer__list{margin:0;padding:0;list-style:none;-webkit-column-gap:30px;column-gap:30px}@media (min-width:48.0625em){.govuk-footer__list--columns-2{-webkit-column-count:2;column-count:2}.govuk-footer__list--columns-3{-webkit-column-count:3;column-count:3}}.govuk-footer__list-item{margin-bottom:15px}@media (min-width:40.0625em){.govuk-footer__list-item{margin-bottom:20px}}.govuk-footer__list-item:last-child{margin-bottom:0}.govuk-header{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;border-bottom:10px solid #fff;color:#fff;background:#0b0c0c}@media print{.govuk-header{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header{font-size:14pt;line-height:1.2}}.govuk-header__container--full-width{padding:0 15px;border-color:#005ea5}.govuk-header__container--full-width .govuk-header__menu-button{right:15px}.govuk-header__container{position:relative;margin-bottom:-10px;padding-top:10px;border-bottom:10px solid #005ea5}.govuk-header__container:after{content:"";display:block;clear:both}.govuk-header__logotype{margin-right:5px}.govuk-header__logotype-crown{margin-right:1px;fill:currentColor;vertical-align:middle}.govuk-header__logotype-crown-fallback-image{width:36px;height:32px;border:0;vertical-align:middle}.govuk-header__product-name{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:inline-table;padding-right:10px}@media print{.govuk-header__product-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__product-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__product-name{font-size:18pt;line-height:1.15}}.govuk-header__link{text-decoration:none}.govuk-header__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-header__link:link,.govuk-header__link:visited{color:#fff}.govuk-header__link:hover{text-decoration:underline}.govuk-header__link:focus{color:#0b0c0c}.govuk-header__link--homepage{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;font-size:30px;line-height:30px}@media print{.govuk-header__link--homepage{font-family:sans-serif}}.govuk-header__link--homepage:link,.govuk-header__link--homepage:visited{text-decoration:none}.govuk-header__link--homepage:active,.govuk-header__link--homepage:hover{margin-bottom:-1px;border-bottom:1px solid}.govuk-header__link--service-name{display:inline-block;margin-bottom:10px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111}@media print{.govuk-header__link--service-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__link--service-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__link--service-name{font-size:18pt;line-height:1.15}}.govuk-header__logo{margin-bottom:10px;padding-right:50px}@media (min-width:40.0625em){.govuk-header__logo{margin-bottom:10px}}@media (min-width:48.0625em){.govuk-header__logo{width:33.33%;padding-right:0;float:left;vertical-align:top}}@media (min-width:48.0625em){.govuk-header__content{width:66.66%;float:left}}.govuk-header__menu-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;display:none;position:absolute;top:20px;right:0;margin:0;padding:0;border:0;color:#fff;background:none}@media print{.govuk-header__menu-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__menu-button{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__menu-button{font-size:14pt;line-height:1.2}}.govuk-header__menu-button:hover{text-decoration:underline}.govuk-header__menu-button:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:8.66px 5px 0;border-top-color:inherit;content:"";margin-left:5px}.govuk-header__menu-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-header__menu-button{top:15px}}.govuk-header__menu-button--open:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(50% 0,0 100%,100% 100%);clip-path:polygon(50% 0,0 100%,100% 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:0 5px 8.66px;border-bottom-color:inherit}.govuk-header__navigation{display:block;margin:0;padding:0;list-style:none}@media (min-width:40.0625em){.govuk-header__navigation{margin-bottom:10px}}.js-enabled .govuk-header__menu-button{display:block}@media (min-width:48.0625em){.js-enabled .govuk-header__menu-button{display:none}}.js-enabled .govuk-header__navigation{display:none}@media (min-width:48.0625em){.js-enabled .govuk-header__navigation{display:block}}.js-enabled .govuk-header__navigation--open{display:block}@media (min-width:48.0625em){.govuk-header__navigation--end{margin:0;padding:5px 0;text-align:right}}.govuk-header__navigation--no-service-name{padding-top:40px}.govuk-header__navigation-item{padding:10px 0;border-bottom:1px solid #2e3133}@media (min-width:48.0625em){.govuk-header__navigation-item{display:inline-block;margin-right:15px;padding:5px 0;border:0}}.govuk-header__navigation-item a{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.14286;white-space:nowrap}@media print{.govuk-header__navigation-item a{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__navigation-item a{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__navigation-item a{font-size:14pt;line-height:1.2}}.govuk-header__navigation-item--active a:hover,.govuk-header__navigation-item--active a:link,.govuk-header__navigation-item--active a:visited{color:#1d8feb}.govuk-header__navigation-item--active a:focus{color:#0b0c0c}.govuk-header__navigation-item:last-child{margin-right:0}@media print{.govuk-header{border-bottom-width:0;color:#0b0c0c;background:rgba(0,0,0,0)}.govuk-header__logotype-crown-fallback-image{display:none}.govuk-header__link:link,.govuk-header__link:visited{color:#0b0c0c}.govuk-header__link:after{display:none}}.govuk-header__logotype-crown,.govuk-header__logotype-crown-fallback-image{position:relative;top:-4px}.govuk-header{padding-top:3px}.govuk-inset-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;padding:15px;margin-top:20px;margin-bottom:20px;clear:both;border-left:10px solid #bfc1c3}@media print{.govuk-inset-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-inset-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-inset-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-inset-text{margin-top:30px;margin-bottom:30px}}.govuk-inset-text :first-child{margin-top:0}.govuk-inset-text :last-child,.govuk-inset-text :only-child{margin-bottom:0}.govuk-panel{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;margin-bottom:15px;padding:35px;border:5px solid rgba(0,0,0,0);text-align:center}@media print{.govuk-panel{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-panel{font-size:14pt;line-height:1.15}}@media (max-width:40.0525em){.govuk-panel{padding:25px}}.govuk-panel--confirmation{color:#fff;background:#00692f}.govuk-panel__title{margin-top:0;margin-bottom:30px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375}@media print{.govuk-panel__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__title{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-panel__title{font-size:32pt;line-height:1.15}}.govuk-panel__title:last-child{margin-bottom:0}.govuk-panel__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:24px;font-size:1.5rem;line-height:1.04167}@media print{.govuk-panel__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__body{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-panel__body{font-size:24pt;line-height:1.05}}.govuk-tag{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.25;display:inline-block;padding:4px 8px 1px;outline:2px solid rgba(0,0,0,0);outline-offset:-2px;color:#fff;background-color:#005ea5;letter-spacing:1px;text-decoration:none;text-transform:uppercase}@media print{.govuk-tag{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tag{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-tag{font-size:14pt;line-height:1.25}}.govuk-tag--inactive{background-color:#6f777b}.govuk-phase-banner{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}.govuk-phase-banner__content{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;display:table;margin:0}@media print{.govuk-phase-banner__content{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-phase-banner__content{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-phase-banner__content{font-size:14pt;line-height:1.2;color:#000}}.govuk-phase-banner__content__tag{margin-right:10px}.govuk-phase-banner__text{display:table-cell;vertical-align:baseline}.govuk-tabs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-top:5px;margin-bottom:20px}@media print{.govuk-tabs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-tabs{margin-top:5px;margin-bottom:30px}}.govuk-tabs__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-bottom:5px}@media print{.govuk-tabs__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__title{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__title{font-size:14pt;line-height:1.15}}.govuk-tabs__list{margin:0;padding:0;list-style:none}@media (max-width:40.0525em){.govuk-tabs__list{margin-bottom:20px}}@media (max-width:40.0525em) and (min-width:40.0625em){.govuk-tabs__list{margin-bottom:30px}}.govuk-tabs__list-item{margin-left:25px}.govuk-tabs__list-item:before{content:"— ";margin-left:-25px;padding-right:5px}.govuk-tabs__tab{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:inline-block;padding-top:10px;padding-bottom:10px}.govuk-tabs__tab:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-tabs__tab:link{color:#005ea5}.govuk-tabs__tab:visited{color:#4c2c92}.govuk-tabs__tab:active,.govuk-tabs__tab:hover{color:#2b8cc4}.govuk-tabs__tab:focus{color:#0b0c0c}@media print{.govuk-tabs__tab{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__tab{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__tab{font-size:14pt;line-height:1.15}}.govuk-tabs__tab[aria-current=true]{color:#0b0c0c;text-decoration:none}.govuk-tabs__panel{margin-bottom:30px}@media (min-width:40.0625em){.govuk-tabs__panel{margin-bottom:50px}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__list{border-bottom:1px solid #bfc1c3}.js-enabled .govuk-tabs__list:after{content:"";display:block;clear:both}.js-enabled .govuk-tabs__list-item{margin-left:0}.js-enabled .govuk-tabs__list-item:before{content:none}.js-enabled .govuk-tabs__title{display:none}.js-enabled .govuk-tabs__tab{margin-right:5px;padding-right:20px;padding-left:20px;float:left;color:#0b0c0c;background-color:#f8f8f8;text-align:center;text-decoration:none}.js-enabled .govuk-tabs__tab--selected{margin-top:-5px;margin-bottom:-1px;padding:14px 19px 16px;border:1px solid #bfc1c3;border-bottom:0;color:#0b0c0c;background-color:#fff}.js-enabled .govuk-tabs__tab--selected:focus{background-color:rgba(0,0,0,0)}.js-enabled .govuk-tabs__panel{margin-bottom:0;padding:30px 20px;border:1px solid #bfc1c3;border-top:0}}@media (min-width:40.0625em) and (min-width:40.0625em){.js-enabled .govuk-tabs__panel{margin-bottom:0}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__panel--hidden{display:none}.js-enabled .govuk-tabs__panel>:last-child{margin-bottom:0}}.govuk-radios__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-radios__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__item{font-size:14pt;line-height:1.15}}.govuk-radios__item:last-child,.govuk-radios__item:last-of-type{margin-bottom:0}.govuk-radios__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-radios__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-radios__hint{display:block;padding-right:15px;padding-left:15px}.govuk-radios__input+.govuk-radios__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;border-radius:50%;background:rgba(0,0,0,0)}.govuk-radios__input+.govuk-radios__label:after{content:"";position:absolute;top:10px;left:10px;width:0;height:0;border:10px solid;border-radius:50%;opacity:0;background:currentColor}.govuk-radios__input:focus+.govuk-radios__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 4px #ffbf47}.govuk-radios__input:checked+.govuk-radios__label:after{opacity:1}.govuk-radios__input:disabled,.govuk-radios__input:disabled+.govuk-radios__label{cursor:default}.govuk-radios__input:disabled+.govuk-radios__label{opacity:.5}@media (min-width:40.0625em){.govuk-radios--inline:after{content:"";display:block;clear:both}.govuk-radios--inline .govuk-radios__item{margin-right:20px;float:left;clear:none}}.govuk-radios--inline.govuk-radios--conditional .govuk-radios__item{margin-right:0;float:none}.govuk-radios__divider{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:40px;margin-bottom:10px;text-align:center}@media print{.govuk-radios__divider{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__divider{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__divider{font-size:14pt;line-height:1.15;color:#000}}.govuk-radios__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-radios__conditional{margin-bottom:20px}}.js-enabled .govuk-radios__conditional--hidden{display:none}.govuk-radios__conditional>:last-child{margin-bottom:0}.govuk-select{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;max-width:100%;height:40px;padding:5px;border:2px solid #0b0c0c}@media print{.govuk-select{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-select{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-select{font-size:14pt;line-height:1.25}}.govuk-select:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-select:focus::-ms-value,.govuk-select option:active,.govuk-select option:checked{color:#fff;background-color:#005ea5}.govuk-select--error{border:4px solid #b10e1e}.govuk-skip-link{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:14px;font-size:.875rem;line-height:1.14286;display:block;padding:10px 15px}.govuk-skip-link:active,.govuk-skip-link:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}@media print{.govuk-skip-link{font-family:sans-serif}}.govuk-skip-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#0b0c0c}@media print{.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#000}}@media (min-width:40.0625em){.govuk-skip-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-skip-link{font-size:14pt;line-height:1.2}}.govuk-table{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:100%;margin-bottom:20px;border-spacing:0;border-collapse:collapse}@media print{.govuk-table{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-table{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-table{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-table{margin-bottom:30px}}.govuk-table__header{font-weight:700}.govuk-table__cell,.govuk-table__header{padding:10px 20px 10px 0;border-bottom:1px solid #bfc1c3;text-align:left}.govuk-table__cell--numeric{font-family:ntatabularnumbers,nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400}@media print{.govuk-table__cell--numeric{font-family:sans-serif}}.govuk-table__cell--numeric,.govuk-table__header--numeric{text-align:right}.govuk-table__cell:last-child,.govuk-table__header:last-child{padding-right:0}.govuk-table__caption{font-weight:700;display:table-caption;text-align:left}.govuk-textarea{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;display:block;width:100%;min-height:40px;margin-bottom:20px;padding:5px;resize:vertical;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none}@media print{.govuk-textarea{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-textarea{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-textarea{font-size:14pt;line-height:1.25}}.govuk-textarea:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-textarea{margin-bottom:30px}}.govuk-textarea--error{border:4px solid #b10e1e}.govuk-warning-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;position:relative;margin-bottom:20px;padding:10px 0}@media print{.govuk-warning-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-warning-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-warning-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-warning-text{margin-bottom:30px}}.govuk-warning-text__assistive{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;padding:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;border:0!important;white-space:nowrap!important}.govuk-warning-text__icon{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;position:absolute;top:50%;left:0;min-width:32px;min-height:29px;margin-top:-20px;padding-top:3px;border:3px solid #0b0c0c;border-radius:50%;color:#fff;background:#0b0c0c;font-size:1.6em;line-height:29px;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media print{.govuk-warning-text__icon{font-family:sans-serif}}.govuk-warning-text__text{display:block;padding-left:50px}.govuk-clearfix:after{content:"";display:block;clear:both}.govuk-visually-hidden{padding:0!important;border:0!important}.govuk-visually-hidden,.govuk-visually-hidden-focusable{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important}.govuk-visually-hidden-focusable:active,.govuk-visually-hidden-focusable:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}.govuk-\!-display-inline{display:inline!important}.govuk-\!-display-inline-block{display:inline-block!important}.govuk-\!-display-block{display:block!important}.govuk-\!-margin-0{margin:0!important}@media (min-width:40.0625em){.govuk-\!-margin-0{margin:0!important}}.govuk-\!-margin-top-0{margin-top:0!important}@media (min-width:40.0625em){.govuk-\!-margin-top-0{margin-top:0!important}}.govuk-\!-margin-right-0{margin-right:0!important}@media (min-width:40.0625em){.govuk-\!-margin-right-0{margin-right:0!important}}.govuk-\!-margin-bottom-0{margin-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-0{margin-bottom:0!important}}.govuk-\!-margin-left-0{margin-left:0!important}@media (min-width:40.0625em){.govuk-\!-margin-left-0{margin-left:0!important}}.govuk-\!-margin-1{margin:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-1{margin:5px!important}}.govuk-\!-margin-top-1{margin-top:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-1{margin-top:5px!important}}.govuk-\!-margin-right-1{margin-right:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-1{margin-right:5px!important}}.govuk-\!-margin-bottom-1{margin-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-1{margin-bottom:5px!important}}.govuk-\!-margin-left-1{margin-left:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-1{margin-left:5px!important}}.govuk-\!-margin-2{margin:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-2{margin:10px!important}}.govuk-\!-margin-top-2{margin-top:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-2{margin-top:10px!important}}.govuk-\!-margin-right-2{margin-right:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-2{margin-right:10px!important}}.govuk-\!-margin-bottom-2{margin-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-2{margin-bottom:10px!important}}.govuk-\!-margin-left-2{margin-left:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-2{margin-left:10px!important}}.govuk-\!-margin-3{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-3{margin:15px!important}}.govuk-\!-margin-top-3{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-3{margin-top:15px!important}}.govuk-\!-margin-right-3{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-3{margin-right:15px!important}}.govuk-\!-margin-bottom-3{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-3{margin-bottom:15px!important}}.govuk-\!-margin-left-3{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-3{margin-left:15px!important}}.govuk-\!-margin-4{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-4{margin:20px!important}}.govuk-\!-margin-top-4{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-4{margin-top:20px!important}}.govuk-\!-margin-right-4{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-4{margin-right:20px!important}}.govuk-\!-margin-bottom-4{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-4{margin-bottom:20px!important}}.govuk-\!-margin-left-4{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-4{margin-left:20px!important}}.govuk-\!-margin-5{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-5{margin:25px!important}}.govuk-\!-margin-top-5{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-5{margin-top:25px!important}}.govuk-\!-margin-right-5{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-5{margin-right:25px!important}}.govuk-\!-margin-bottom-5{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-5{margin-bottom:25px!important}}.govuk-\!-margin-left-5{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-5{margin-left:25px!important}}.govuk-\!-margin-6{margin:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-6{margin:30px!important}}.govuk-\!-margin-top-6{margin-top:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-6{margin-top:30px!important}}.govuk-\!-margin-right-6{margin-right:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-6{margin-right:30px!important}}.govuk-\!-margin-bottom-6{margin-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-6{margin-bottom:30px!important}}.govuk-\!-margin-left-6{margin-left:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-6{margin-left:30px!important}}.govuk-\!-margin-7{margin:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-7{margin:40px!important}}.govuk-\!-margin-top-7{margin-top:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-7{margin-top:40px!important}}.govuk-\!-margin-right-7{margin-right:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-7{margin-right:40px!important}}.govuk-\!-margin-bottom-7{margin-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-7{margin-bottom:40px!important}}.govuk-\!-margin-left-7{margin-left:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-7{margin-left:40px!important}}.govuk-\!-margin-8{margin:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-8{margin:50px!important}}.govuk-\!-margin-top-8{margin-top:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-8{margin-top:50px!important}}.govuk-\!-margin-right-8{margin-right:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-8{margin-right:50px!important}}.govuk-\!-margin-bottom-8{margin-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-8{margin-bottom:50px!important}}.govuk-\!-margin-left-8{margin-left:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-8{margin-left:50px!important}}.govuk-\!-margin-9{margin:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-9{margin:60px!important}}.govuk-\!-margin-top-9{margin-top:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-9{margin-top:60px!important}}.govuk-\!-margin-right-9{margin-right:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-9{margin-right:60px!important}}.govuk-\!-margin-bottom-9{margin-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-9{margin-bottom:60px!important}}.govuk-\!-margin-left-9{margin-left:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-9{margin-left:60px!important}}.govuk-\!-padding-0{padding:0!important}@media (min-width:40.0625em){.govuk-\!-padding-0{padding:0!important}}.govuk-\!-padding-top-0{padding-top:0!important}@media (min-width:40.0625em){.govuk-\!-padding-top-0{padding-top:0!important}}.govuk-\!-padding-right-0{padding-right:0!important}@media (min-width:40.0625em){.govuk-\!-padding-right-0{padding-right:0!important}}.govuk-\!-padding-bottom-0{padding-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-0{padding-bottom:0!important}}.govuk-\!-padding-left-0{padding-left:0!important}@media (min-width:40.0625em){.govuk-\!-padding-left-0{padding-left:0!important}}.govuk-\!-padding-1{padding:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-1{padding:5px!important}}.govuk-\!-padding-top-1{padding-top:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-1{padding-top:5px!important}}.govuk-\!-padding-right-1{padding-right:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-1{padding-right:5px!important}}.govuk-\!-padding-bottom-1{padding-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-1{padding-bottom:5px!important}}.govuk-\!-padding-left-1{padding-left:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-1{padding-left:5px!important}}.govuk-\!-padding-2{padding:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-2{padding:10px!important}}.govuk-\!-padding-top-2{padding-top:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-2{padding-top:10px!important}}.govuk-\!-padding-right-2{padding-right:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-2{padding-right:10px!important}}.govuk-\!-padding-bottom-2{padding-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-2{padding-bottom:10px!important}}.govuk-\!-padding-left-2{padding-left:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-2{padding-left:10px!important}}.govuk-\!-padding-3{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-3{padding:15px!important}}.govuk-\!-padding-top-3{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-3{padding-top:15px!important}}.govuk-\!-padding-right-3{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-3{padding-right:15px!important}}.govuk-\!-padding-bottom-3{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-3{padding-bottom:15px!important}}.govuk-\!-padding-left-3{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-3{padding-left:15px!important}}.govuk-\!-padding-4{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-4{padding:20px!important}}.govuk-\!-padding-top-4{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-4{padding-top:20px!important}}.govuk-\!-padding-right-4{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-4{padding-right:20px!important}}.govuk-\!-padding-bottom-4{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-4{padding-bottom:20px!important}}.govuk-\!-padding-left-4{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-4{padding-left:20px!important}}.govuk-\!-padding-5{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-5{padding:25px!important}}.govuk-\!-padding-top-5{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-5{padding-top:25px!important}}.govuk-\!-padding-right-5{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-5{padding-right:25px!important}}.govuk-\!-padding-bottom-5{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-5{padding-bottom:25px!important}}.govuk-\!-padding-left-5{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-5{padding-left:25px!important}}.govuk-\!-padding-6{padding:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-6{padding:30px!important}}.govuk-\!-padding-top-6{padding-top:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-6{padding-top:30px!important}}.govuk-\!-padding-right-6{padding-right:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-6{padding-right:30px!important}}.govuk-\!-padding-bottom-6{padding-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-6{padding-bottom:30px!important}}.govuk-\!-padding-left-6{padding-left:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-6{padding-left:30px!important}}.govuk-\!-padding-7{padding:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-7{padding:40px!important}}.govuk-\!-padding-top-7{padding-top:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-7{padding-top:40px!important}}.govuk-\!-padding-right-7{padding-right:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-7{padding-right:40px!important}}.govuk-\!-padding-bottom-7{padding-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-7{padding-bottom:40px!important}}.govuk-\!-padding-left-7{padding-left:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-7{padding-left:40px!important}}.govuk-\!-padding-8{padding:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-8{padding:50px!important}}.govuk-\!-padding-top-8{padding-top:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-8{padding-top:50px!important}}.govuk-\!-padding-right-8{padding-right:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-8{padding-right:50px!important}}.govuk-\!-padding-bottom-8{padding-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-8{padding-bottom:50px!important}}.govuk-\!-padding-left-8{padding-left:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-8{padding-left:50px!important}}.govuk-\!-padding-9{padding:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-9{padding:60px!important}}.govuk-\!-padding-top-9{padding-top:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-9{padding-top:60px!important}}.govuk-\!-padding-right-9{padding-right:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-9{padding-right:60px!important}}.govuk-\!-padding-bottom-9{padding-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-9{padding-bottom:60px!important}}.govuk-\!-padding-left-9{padding-left:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-9{padding-left:60px!important}}.govuk-\!-font-size-80{font-size:53px!important;font-size:3.3125rem!important;line-height:1.03774!important}@media (min-width:40.0625em){.govuk-\!-font-size-80{font-size:80px!important;font-size:5rem!important;line-height:1!important}}@media print{.govuk-\!-font-size-80{font-size:53pt!important;line-height:1.1!important}}.govuk-\!-font-size-48{font-size:32px!important;font-size:2rem!important;line-height:1.09375!important}@media (min-width:40.0625em){.govuk-\!-font-size-48{font-size:48px!important;font-size:3rem!important;line-height:1.04167!important}}@media print{.govuk-\!-font-size-48{font-size:32pt!important;line-height:1.15!important}}.govuk-\!-font-size-36{font-size:24px!important;font-size:1.5rem!important;line-height:1.04167!important}@media (min-width:40.0625em){.govuk-\!-font-size-36{font-size:36px!important;font-size:2.25rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-36{font-size:24pt!important;line-height:1.05!important}}.govuk-\!-font-size-27{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-27{font-size:27px!important;font-size:1.6875rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-27{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-24{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-24{font-size:24px!important;font-size:1.5rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-24{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-19{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-19{font-size:19px!important;font-size:1.1875rem!important;line-height:1.31579!important}}@media print{.govuk-\!-font-size-19{font-size:14pt!important;line-height:1.15!important}}.govuk-\!-font-size-16{font-size:14px!important;font-size:.875rem!important;line-height:1.14286!important}@media (min-width:40.0625em){.govuk-\!-font-size-16{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-16{font-size:14pt!important;line-height:1.2!important}}.govuk-\!-font-size-14{font-size:12px!important;font-size:.75rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-14{font-size:14px!important;font-size:.875rem!important;line-height:1.42857!important}}@media print{.govuk-\!-font-size-14{font-size:12pt!important;line-height:1.2!important}}.govuk-\!-font-weight-regular{font-weight:400!important}.govuk-\!-font-weight-bold{font-weight:700!important}.govuk-\!-width-full,.govuk-\!-width-three-quarters{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-three-quarters{width:75%!important}}.govuk-\!-width-two-thirds{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-two-thirds{width:66.66%!important}}.govuk-\!-width-one-half{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-half{width:50%!important}}.govuk-\!-width-one-third{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-third{width:33.33%!important}}.govuk-\!-width-one-quarter{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-quarter{width:25%!important}} \ No newline at end of file diff --git a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs index 667843d291..83f10ebc05 100644 --- a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs +++ b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs @@ -90,6 +90,9 @@ private Vacancy CreateClone(CloneVacancyCommand message, Vacancy vacancy) clone.TransferInfo = null; clone.ReviewByUser = null; clone.ReviewDate = null; + clone.ReviewCount = 0; + clone.EmployerReviewFieldIndicators = null; + clone.EmployerRejectedReason = null; return clone; } diff --git a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs index 66598d1f08..61eba47e83 100644 --- a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs +++ b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs @@ -66,6 +66,7 @@ public async Task Handle(ReviewVacancyCommand message, CancellationToken cancell vacancy.Status = VacancyStatus.Review; vacancy.ReviewDate = now; + vacancy.ReviewCount += 1; vacancy.ReviewByUser = message.User; vacancy.LastUpdatedDate = now; vacancy.LastUpdatedByUser = message.User; diff --git a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs new file mode 100644 index 0000000000..151d549850 --- /dev/null +++ b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs @@ -0,0 +1,8 @@ +namespace Esfa.Recruit.Vacancies.Client.Domain.Entities +{ + public class EmployerReviewFieldIndicator + { + public string FieldIdentifier { get; set; } + public bool IsChangeRequested { get; set; } + } +} diff --git a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs index ee7f9495ac..8706bb6647 100644 --- a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs +++ b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs @@ -21,6 +21,7 @@ public class Vacancy public VacancyUser SubmittedByUser { get; set; } public DateTime? ReviewDate { get; set; } public VacancyUser ReviewByUser { get; set; } + public int ReviewCount { get; set; } public DateTime? ApprovedDate { get; set; } public DateTime? LiveDate { get; set; } @@ -41,6 +42,8 @@ public class Vacancy public Address EmployerLocation { get; set; } public string EmployerName { get; set; } public EmployerNameOption? EmployerNameOption { get; set; } + public List EmployerReviewFieldIndicators { get; set; } + public string EmployerRejectedReason { get; set; } public string LegalEntityName { get; set; } public string EmployerWebsiteUrl { get; set; } public GeoCodeMethod? GeoCodeMethod { get; set; } diff --git a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs index f7745aced0..d955d210e6 100644 --- a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs +++ b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs @@ -130,6 +130,7 @@ private static void AssertKnownProperties(Vacancy original, Vacancy clone) {nameof(Vacancy.SubmittedDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.SubmittedByUser), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.ReviewDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, + {nameof(Vacancy.ReviewCount), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Ignore)}, {nameof(Vacancy.ReviewByUser), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.ApprovedDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.LiveDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, @@ -150,6 +151,8 @@ private static void AssertKnownProperties(Vacancy original, Vacancy clone) {nameof(Vacancy.EmployerLocation), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.EmployerName), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.EmployerNameOption), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, + {nameof(Vacancy.EmployerReviewFieldIndicators), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, + {nameof(Vacancy.EmployerRejectedReason), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.LegalEntityName), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.EmployerWebsiteUrl), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.GeoCodeMethod), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, diff --git a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs index 3124756e9e..4f2c07ec8a 100644 --- a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs +++ b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs @@ -45,6 +45,7 @@ public async Task GivenEmployerDescription_ThenShouldUpdateVacancyWithThatDescri vacancy.Status.Should().Be(VacancyStatus.Review); vacancy.ReviewDate.Should().Be(now); vacancy.ReviewByUser.Should().Be(user); + vacancy.ReviewCount.Should().Be(1); vacancy.LastUpdatedDate.Should().Be(now); vacancy.LastUpdatedByUser.Should().Be(user); vacancy.EmployerDescription.Should().Be(expectedDescription); @@ -77,6 +78,7 @@ public async Task ShouldNotChangeEmployerDescriptionIfNotSpecifiedInCommand() vacancy.Status.Should().Be(VacancyStatus.Review); vacancy.ReviewDate.Should().Be(now); vacancy.ReviewByUser.Should().Be(user); + vacancy.ReviewCount.Should().Be(1); vacancy.LastUpdatedDate.Should().Be(now); vacancy.LastUpdatedByUser.Should().Be(user); vacancy.EmployerDescription.Should().Be(expectedDescription);