Skip to content

Commit

Permalink
Merge pull request #245 from SkillsFundingAgency/CON-3949---Add-searc…
Browse files Browse the repository at this point in the history
…h-+-sorting-to-Choose-an-Employer-page-in-Reserve-funding-journey

CON-3949 Add search + sorting to Choose an Employer page in Reserve funding journey
  • Loading branch information
narendranogothu authored Nov 17, 2021
2 parents 912cd1d + 89bce2a commit 4cb2a47
Show file tree
Hide file tree
Showing 14 changed files with 453 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
using SFA.DAS.Reservations.Application.Extensions;
using SFA.DAS.Reservations.Application.Providers.Services;
using SFA.DAS.Reservations.Application.Validation;
using SFA.DAS.Reservations.Domain.Interfaces;
using ValidationResult = System.ComponentModel.DataAnnotations.ValidationResult;

namespace SFA.DAS.Reservations.Application.Providers.Queries.GetTrustedEmployers
{
Expand Down Expand Up @@ -48,7 +46,7 @@ public async Task<GetTrustedEmployersResponse> Handle(GetTrustedEmployersQuery r

return new GetTrustedEmployersResponse
{
Employers = trustedEmployers
Employers = trustedEmployers.OrderBy(te => te.AccountLegalEntityName).ThenBy(te => te.AccountName)
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SFA.DAS.Encoding;
using SFA.DAS.Reservations.Application.Providers.Queries.GetTrustedEmployers;
using SFA.DAS.Reservations.Domain.Interfaces;
using SFA.DAS.Reservations.Infrastructure.Configuration;
using SFA.DAS.Reservations.Web.Controllers;
Expand Down Expand Up @@ -115,7 +116,8 @@ private static void RegisterControllers(IServiceCollection serviceCollection)
new ProviderReservationsController(
sp.GetService<IMediator>(),
sp.GetService<IExternalUrlHelper>(),
sp.GetService<IEncodingService>()
sp.GetService<IEncodingService>(),
sp.GetService<ISessionStorageService<GetTrustedEmployersResponse>>()
)
{
ControllerContext = GetControllerContext<ProviderReservationsController>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -15,6 +16,7 @@
using SFA.DAS.Reservations.Application.Providers.Queries;
using SFA.DAS.Reservations.Application.Providers.Queries.GetTrustedEmployers;
using SFA.DAS.Reservations.Domain.Employers;
using SFA.DAS.Reservations.Domain.Interfaces;
using SFA.DAS.Reservations.Web.Controllers;
using SFA.DAS.Reservations.Web.Models;
using SFA.DAS.Testing.AutoFixture;
Expand All @@ -30,6 +32,7 @@ public async Task Then_It_Calls_ProviderPermissions_Service_To_Get_Employers(
IEnumerable<AccountLegalEntity> expectedEmployers,
GetLegalEntitiesResponse getLegalEntitiesResponse,
[Frozen] Mock<IMediator> mockMediator,
[Frozen] Mock<ISessionStorageService<GetTrustedEmployersResponse>> sessionStorageService,
ProviderReservationsController controller)
{
mockMediator
Expand All @@ -40,44 +43,126 @@ public async Task Then_It_Calls_ProviderPermissions_Service_To_Get_Employers(
mockMediator
.Setup(m => m.Send(It.IsAny<GetTrustedEmployersQuery>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GetTrustedEmployersResponse{Employers = expectedEmployers});


sessionStorageService.Setup(x => x.Get()).Returns((GetTrustedEmployersResponse)null);

await controller.ChooseEmployer(routeModel);

mockMediator.Verify(m => m.Send(It.IsAny<GetTrustedEmployersQuery>(), It.IsAny<CancellationToken>()), Times.Once);
}

[Test, MoqAutoData]
[Test]
[MoqInlineAutoData(null, null, false, 6, null, null)]
[MoqInlineAutoData("ltd", null, false, 3, null, null)]
[MoqInlineAutoData("xxx", null, false, 0, null, null)]
[MoqInlineAutoData("tesco", null, false, 1, null, null)]
[MoqInlineAutoData(null, "AccountName", false, 6, "Aldi", "Tesco")]
[MoqInlineAutoData("ltd", "AccountName", false, 3, "Asda", "Sainsbury's")]
[MoqInlineAutoData("xxx", "AccountName", false, 0, null, null)]
[MoqInlineAutoData("tesco", "AccountName", false, 1, "Tesco", "Tesco")]
[MoqInlineAutoData(null, "AccountName", true, 6, "Tesco", "Aldi")]
[MoqInlineAutoData("ltd", "AccountName", true, 3, "Sainsbury's", "Asda")]
[MoqInlineAutoData("xxx", "AccountName", true, 0, null, null)]
[MoqInlineAutoData("tesco", "AccountName", true, 1, "Tesco", "Tesco")]
[MoqInlineAutoData(null, "AccountLegalEntityName", false, 6, "1 Lidl Plc", "6 Morrisons Ltd")]
[MoqInlineAutoData("ltd", "AccountLegalEntityName", false, 3, "2 Sainsbury's Ltd", "6 Morrisons Ltd")]
[MoqInlineAutoData("xxx", "AccountLegalEntityName", false, 0, null, null)]
[MoqInlineAutoData("tesco", "AccountLegalEntityName", false, 1, "3 Tesco Limited", "3 Tesco Limited")]
[MoqInlineAutoData(null, "AccountLegalEntityName", true, 6, "6 Morrisons Ltd", "1 Lidl Plc")]
[MoqInlineAutoData("ltd", "AccountLegalEntityName", true, 3, "6 Morrisons Ltd", "2 Sainsbury's Ltd")]
[MoqInlineAutoData("xxx", "AccountLegalEntityName", true, 0, null, null)]
[MoqInlineAutoData("tesco", "AccountLegalEntityName", true, 1, "3 Tesco Limited", "3 Tesco Limited")]
public async Task Then_It_Returns_The_Trusted_Employers(
string searchTerm,
string sortField,
bool reverseDirection,
int expectedResults,
string firstItem,
string lastItem,
string accountLegalEntityPublicHashedId,
ReservationsRouteModel routeModel,
List<AccountLegalEntity> expectedEmployers,
[Frozen] Mock<IEncodingService> encodingService,
[Frozen] Mock<IMediator> mockMediator,
[Frozen] Mock<ISessionStorageService<GetTrustedEmployersResponse>> sessionStorageService,
ProviderReservationsController controller)
{
var ale = AccountLegalEntities().ToList();

routeModel.SearchTerm = searchTerm;
routeModel.SortField = sortField;
routeModel.ReverseSort = reverseDirection;

encodingService.Setup(x => x.Encode(It.IsAny<long>(), EncodingType.PublicAccountLegalEntityId))
.Returns(accountLegalEntityPublicHashedId);
expectedEmployers = expectedEmployers.Select(arg => new AccountLegalEntity
{
AccountLegalEntityPublicHashedId = arg.AccountLegalEntityPublicHashedId,
AccountId = arg.AccountId,
IsLevy = false
}).ToList();


mockMediator
.Setup(service => service.Send(It.IsAny<GetTrustedEmployersQuery>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GetTrustedEmployersResponse{Employers = expectedEmployers});

.ReturnsAsync(new GetTrustedEmployersResponse{Employers = ale});

sessionStorageService.Setup(x => x.Get()).Returns((GetTrustedEmployersResponse)null);

var result = await controller.ChooseEmployer(routeModel);

var viewModel = result.Should().BeOfType<ViewResult>()
.Which.Model.Should().BeOfType<ChooseEmployerViewModel>()
.Subject;
viewModel.Employers.Should()
.BeEquivalentTo(expectedEmployers, options => options.Excluding(c=>c.AccountLegalEntityPublicHashedId));
viewModel.Employers.All(c => c.AccountLegalEntityPublicHashedId.Equals(accountLegalEntityPublicHashedId))
.Should().BeTrue();

viewModel.Employers.Count().Should().Be(expectedResults);

if (viewModel.Employers.Any() && !string.IsNullOrWhiteSpace(sortField))
{
viewModel.Employers.First().GetType().GetProperty(sortField).GetValue(viewModel.Employers.First(), null).ToString().Should().Be(firstItem);
viewModel.Employers.Last().GetType().GetProperty(sortField).GetValue(viewModel.Employers.Last(), null).ToString().Should().Be(lastItem);
}
}

private IEnumerable<AccountLegalEntity> AccountLegalEntities()
{
return new List<AccountLegalEntity>
{
new AccountLegalEntity
{
AccountId = 1,
AccountName = "Tesco",
AccountLegalEntityId = 1,
AccountLegalEntityName = "3 Tesco Limited"
},
new AccountLegalEntity
{
AccountId = 2,
AccountName = "Asda",
AccountLegalEntityId = 2,
AccountLegalEntityName = "5 Asda Ltd"
},
new AccountLegalEntity
{
AccountId = 3,
AccountName = "Lidl",
AccountLegalEntityId = 3,
AccountLegalEntityName = "1 Lidl Plc"
},
new AccountLegalEntity
{
AccountId = 4,
AccountName = "Morrisons",
AccountLegalEntityId = 4,
AccountLegalEntityName = "6 Morrisons Ltd"
},
new AccountLegalEntity
{
AccountId = 5,
AccountName = "Sainsbury's",
AccountLegalEntityId = 5,
AccountLegalEntityName = "2 Sainsbury's Ltd"
},
new AccountLegalEntity
{
AccountId = 6,
AccountName = "Aldi",
AccountLegalEntityId = 6,
AccountLegalEntityName = "4 Aldi"
},
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
using SFA.DAS.Reservations.Application.Reservations.Queries.GetCachedReservation;
using SFA.DAS.Reservations.Domain.Employers;
using SFA.DAS.Reservations.Domain.Interfaces;
using SFA.DAS.Reservations.Web.Filters;
using SFA.DAS.Reservations.Web.Extensions;
using SFA.DAS.Reservations.Web.Infrastructure;
using SFA.DAS.Reservations.Web.Models;

Expand All @@ -29,12 +29,18 @@ public class ProviderReservationsController : ReservationsBaseController
private readonly IMediator _mediator;
private readonly IExternalUrlHelper _externalUrlHelper;
private readonly IEncodingService _encodingService;
private readonly ISessionStorageService<GetTrustedEmployersResponse> _sessionStorageService;

public ProviderReservationsController(IMediator mediator, IExternalUrlHelper externalUrlHelper, IEncodingService encodingService) : base(mediator)
public ProviderReservationsController(
IMediator mediator,
IExternalUrlHelper externalUrlHelper,
IEncodingService encodingService,
ISessionStorageService<GetTrustedEmployersResponse> sessionStorageService) : base(mediator)
{
_mediator = mediator;
_externalUrlHelper = externalUrlHelper;
_encodingService = encodingService;
_sessionStorageService = sessionStorageService;
}

public async Task<IActionResult> Index(ReservationsRouteModel routeModel)
Expand Down Expand Up @@ -89,29 +95,66 @@ public async Task<IActionResult> ChooseEmployer(ReservationsRouteModel routeMode
throw new ArgumentException("UkPrn must be set", nameof(ReservationsRouteModel.UkPrn));
}

var getTrustedEmployersResponse = await _mediator.Send(new GetTrustedEmployersQuery {UkPrn = routeModel.UkPrn.Value});


var eoiEmployers = new List<AccountLegalEntity>();
foreach (var employer in getTrustedEmployersResponse.Employers)
var getTrustedEmployersResponse = _sessionStorageService.Get();

if (getTrustedEmployersResponse == null)
{
employer.AccountLegalEntityPublicHashedId = _encodingService.Encode(employer.AccountLegalEntityId,
EncodingType.PublicAccountLegalEntityId);
eoiEmployers.Add(employer);
getTrustedEmployersResponse = await _mediator.Send(new GetTrustedEmployersQuery {UkPrn = routeModel.UkPrn.Value});
_sessionStorageService.Store(getTrustedEmployersResponse);
}

var sortModel = new SortModel
{
ReverseSort = routeModel.ReverseSort,
SortField = routeModel.SortField
};

var eoiEmployers = getTrustedEmployersResponse.Employers
.Where(e => string.IsNullOrWhiteSpace(routeModel.SearchTerm) ||
e.AccountName.Replace(" ", string.Empty).Contains(routeModel.SearchTerm.Replace(" ", string.Empty), StringComparison.CurrentCultureIgnoreCase) ||
e.AccountLegalEntityName.Replace(" ", string.Empty).Contains(routeModel.SearchTerm.Replace(" ", string.Empty), StringComparison.CurrentCultureIgnoreCase))
.ToList();


eoiEmployers = eoiEmployers.Order(sortModel);

var viewModel = new ChooseEmployerViewModel
{
Employers = eoiEmployers
Employers = eoiEmployers,
SearchTerm = routeModel.SearchTerm,
SortModel = sortModel
};

return View(viewModel);
}

[HttpGet]
[Route("choose-employer-search", Name = RouteNames.ProviderChooseEmployerSearch)]
public async Task<JsonResult> ChooseEmployerSearch(ReservationsRouteModel routeModel, string searchTerm)
{
if (!routeModel.UkPrn.HasValue)
{
throw new ArgumentException("UkPrn must be set", nameof(ReservationsRouteModel.UkPrn));
}

var getTrustedEmployersResponse = _sessionStorageService.Get();

var eoiEmployersAccount = getTrustedEmployersResponse.Employers
.Where(eoi => eoi.AccountName.Contains(searchTerm, StringComparison.CurrentCultureIgnoreCase))
.Select(eoi => eoi.AccountName.ToUpper());

var eoiEmployersEmployer = getTrustedEmployersResponse.Employers
.Where(eoi => eoi.AccountLegalEntityName.Contains(searchTerm, StringComparison.CurrentCultureIgnoreCase))
.Select(eoi => eoi.AccountLegalEntityName.ToUpper());

return Json(eoiEmployersAccount.Concat(eoiEmployersEmployer).Distinct().OrderBy(eoi => eoi));
}

[HttpGet]
[Route("confirm-employer/{id?}", Name=RouteNames.ProviderConfirmEmployer)]
public async Task<IActionResult> ConfirmEmployer(ConfirmEmployerViewModel viewModel)
{
_sessionStorageService.Delete();

if (viewModel.Id.HasValue)
{
Expand All @@ -126,7 +169,6 @@ public async Task<IActionResult> ConfirmEmployer(ConfirmEmployerViewModel viewMo
viewModel.AccountLegalEntityPublicHashedId = result.AccountLegalEntityPublicHashedId;
viewModel.AccountName = result.AccountName;
return View(viewModel);

}

return View(viewModel);
Expand Down Expand Up @@ -209,7 +251,6 @@ public async Task<IActionResult> EmployerAgreementNotSigned(ReservationsRouteMod
};

return View(viewModel);

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using SFA.DAS.Reservations.Domain.Employers;
using SFA.DAS.Reservations.Web.Models;

namespace SFA.DAS.Reservations.Web.Extensions
{
public static class AccountLegalEntityExtension
{
public static List<AccountLegalEntity> Order(this List<AccountLegalEntity> accountLegalEntities, SortModel sortModel)
{
if (string.IsNullOrWhiteSpace(sortModel.SortField)) return accountLegalEntities;

if (sortModel.SortField == nameof(AccountLegalEntity.AccountLegalEntityName))
{
accountLegalEntities = (sortModel.ReverseSort
? accountLegalEntities.OrderByDescending(ale => ale.AccountLegalEntityName)
.ThenBy(ale => ale.AccountName)
.ThenBy(ale => ale.AccountLegalEntityPublicHashedId)
: accountLegalEntities.OrderBy(ale => ale.AccountLegalEntityName)
.ThenBy(ale => ale.AccountName)
.ThenBy(ale => ale.AccountLegalEntityPublicHashedId)).ToList();
}
else
{
accountLegalEntities = (sortModel.ReverseSort
? accountLegalEntities.OrderByDescending(ale => ale.AccountName)
.ThenBy(ale => ale.AccountLegalEntityName)
.ThenBy(ale => ale.AccountLegalEntityPublicHashedId)
: accountLegalEntities.OrderBy(ale => ale.AccountName)
.ThenBy(ale => ale.AccountLegalEntityName)
.ThenBy(ale => ale.AccountLegalEntityPublicHashedId)).ToList();
}

return accountLegalEntities;
}
}
}
1 change: 1 addition & 0 deletions src/SFA.DAS.Reservations.Web/Infrastructure/RouteNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class RouteNames
public const string ProviderSignOut = "provider-signout";
public const string ProviderPostCompleted = "provider-reservation-completed";
public const string ProviderChooseEmployer = "provider-choose-employer";
public const string ProviderChooseEmployerSearch = "provider-choose-employer-search";
public const string ProviderConfirmEmployer = "provider-confirm-employer";
public const string ProviderApprenticeshipTrainingRuleCheck = "provider-apprenticeship-training-rule-check";
public const string ProviderEmployerAgreementNotSigned = "provider-employer-agreement-not-signed";
Expand Down
Loading

0 comments on commit 4cb2a47

Please sign in to comment.