diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SearchService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SearchService.cs
deleted file mode 100644
index d3eb98d6..00000000
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SearchService.cs
+++ /dev/null
@@ -1,924 +0,0 @@
-namespace LearningHub.Nhs.OpenApi.Services.Services
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Http;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Web;
- using AutoMapper;
- using LearningHub.Nhs.Models.Entities.Activity;
- using LearningHub.Nhs.Models.Entities.Resource;
- using LearningHub.Nhs.Models.Enums;
- using LearningHub.Nhs.Models.Search;
- using LearningHub.Nhs.Models.Search.SearchClick;
- using LearningHub.Nhs.Models.Validation;
- using LearningHub.Nhs.Models.ViewModels.Helpers;
- using LearningHub.Nhs.OpenApi.Models.Configuration;
- using LearningHub.Nhs.OpenApi.Models.ServiceModels.Findwise;
- using LearningHub.Nhs.OpenApi.Models.ServiceModels.Resource;
- using LearningHub.Nhs.OpenApi.Models.ViewModels;
- using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
- using LearningHub.Nhs.OpenApi.Services.Helpers;
- using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients;
- using LearningHub.Nhs.OpenApi.Services.Interface.Services;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Options;
- using Newtonsoft.Json;
- using Event = LearningHub.Nhs.Models.Entities.Analytics.Event;
-
- ///
- /// The search service.
- ///
- public class SearchService : ISearchService
- {
-
- ///
- /// application id for search.
- ///
- private const string ApplicationId = "HEE";
-
- ///
- /// profile type for search.
- ///
- private const string ProfileType = "SEARCHER";
-
- private readonly IEventService eventService;
- private readonly ILearningHubService learningHubService;
- private readonly IResourceRepository resourceRepository;
- private readonly IFindwiseClient findwiseClient;
- private readonly ILogger logger;
- private readonly FindwiseConfig findwiseConfig;
- private readonly IMapper mapper;
-
- ///
- /// Initializes a new instance of the class.
- /// The search service.
- ///
- ///
- /// The .
- ///
- ///
- /// The .
- ///
- ///
- /// The .
- ///
- ///
- /// The .
- ///
- /// Logger.
- public SearchService(
- ILearningHubService learningHubService,
- IEventService eventService,
- IFindwiseClient findwiseClient,
- IOptions findwiseConfig,
- IResourceRepository resourceRepository,
- ILogger logger,
- IMapper mapper)
- {
- this.learningHubService = learningHubService;
- this.eventService = eventService;
- this.findwiseClient = findwiseClient;
- this.resourceRepository = resourceRepository;
- this.logger = logger;
- this.mapper = mapper;
- this.findwiseConfig = findwiseConfig.Value;
- }
-
- ///
- /// The Get Search Result Async method.
- ///
- /// The search request model.
- /// The user id.
- /// Cancellation token.
- /// The .
- public async Task GetSearchResultAsync(SearchRequestModel searchRequestModel, int userId, CancellationToken cancellationToken = default)
- {
- SearchResultModel viewmodel = new SearchResultModel();
-
- try
- {
- // e.g. if pagesize is 10, then offset would be 0,10,20,30
- var pageSize = searchRequestModel.PageSize;
- var offset = searchRequestModel.PageIndex * pageSize;
-
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.SearchBaseUrl);
-
- var request = string.Format(
- this.findwiseConfig.SearchEndpointPath + "{0}?offset={1}&hits={2}&q={3}&token={4}",
- this.findwiseConfig.CollectionIds.Resource,
- offset,
- pageSize,
- this.EncodeSearchText(searchRequestModel.SearchText) + searchRequestModel.FilterText + searchRequestModel.ResourceAccessLevelFilterText + searchRequestModel.ProviderFilterText,
- this.findwiseConfig.Token);
-
- if (searchRequestModel.CatalogueId.HasValue)
- {
- request += $"&catalogue_ids={searchRequestModel.CatalogueId}";
- }
-
- // if sort column is requested
- if (!string.IsNullOrEmpty(searchRequestModel.SortColumn))
- {
- var sortquery = $"&sort={searchRequestModel.SortColumn}";
-
- // if sort direction option is requested
- if (!string.IsNullOrEmpty(searchRequestModel.SortDirection))
- {
- var sortdirection = searchRequestModel.SortDirection.StartsWith("asc") ? "asc" : "desc";
- sortquery = $"{sortquery}_{sortdirection}";
- }
-
- request = $"{request}{sortquery}";
- }
-
- var response = await client.GetAsync(request).ConfigureAwait(false);
-
- if (response.IsSuccessStatusCode)
- {
- var result = response.Content.ReadAsStringAsync().Result;
- viewmodel = JsonConvert.DeserializeObject(result);
- searchRequestModel.TotalNumberOfHits = viewmodel.Stats.TotalHits;
- }
- else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError($"Get Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}");
- throw new Exception("AccessDenied to FindWise Server");
- }
- else
- {
- var error = response.Content.ReadAsStringAsync().Result.ToString();
- this.logger.LogError($"Get Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}, Error Message:{error}");
- throw new Exception("Error with FindWise Server");
- }
-
- return viewmodel;
- }
- catch (Exception)
- {
- throw;
- }
- }
-
- ///
- /// The Get Catalogue Search Result Async method.
- ///
- ///
- /// The catalog search request model.
- ///
- ///
- /// The user id.
- ///
- /// Cancellation token.
- ///
- /// The .
- ///
- public async Task GetCatalogueSearchResultAsync(CatalogueSearchRequestModel catalogSearchRequestModel, int userId, CancellationToken cancellationToken = default)
- {
- var viewmodel = new SearchCatalogueResultModel();
-
- try
- {
- // e.g. if pagesize is 3, then offset would be 0,3,6,9
- var offset = catalogSearchRequestModel.PageIndex * catalogSearchRequestModel.PageSize;
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.SearchBaseUrl);
- var request = string.Format(
- this.findwiseConfig.SearchEndpointPath + "{0}?offset={1}&hits={2}&q={3}&token={4}",
- this.findwiseConfig.CollectionIds.Catalogue,
- offset,
- catalogSearchRequestModel.PageSize,
- this.EncodeSearchText(catalogSearchRequestModel.SearchText),
- this.findwiseConfig.Token);
-
- var response = await client.GetAsync(request).ConfigureAwait(false);
-
- if (response.IsSuccessStatusCode)
- {
- var result = response.Content.ReadAsStringAsync().Result;
- viewmodel = JsonConvert.DeserializeObject(result);
- catalogSearchRequestModel.TotalNumberOfHits = viewmodel.Stats.TotalHits;
- }
- else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError($"Get Catalogue Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}");
- throw new Exception("AccessDenied to FindWise Server");
- }
- else
- {
- var error = response.Content.ReadAsStringAsync().Result.ToString();
- this.logger.LogError($"Get Catalogue Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}, Error Message:{error}");
- throw new Exception("Error with FindWise Server");
- }
-
- var remainingItems = catalogSearchRequestModel.TotalNumberOfHits - offset;
- var resultsPerPage = remainingItems >= catalogSearchRequestModel.PageSize ? catalogSearchRequestModel.PageSize : remainingItems;
- LearningHubValidationResult validationResult = await this.CreateCatalogueSearchTerm(catalogSearchRequestModel, resultsPerPage, userId);
-
- viewmodel.SearchId = validationResult.CreatedId ?? 0;
-
- return viewmodel;
- }
- catch (Exception)
- {
- throw;
- }
- }
-
- ///
- /// The create resource search action async.
- ///
- ///
- /// The search action request model.
- ///
- ///
- /// The user id.
- ///
- ///
- /// The .
- ///
- public async Task CreateResourceSearchActionAsync(SearchActionResourceModel searchActionResourceModel, int userId)
- {
- var jsonobj = new
- {
- searchActionResourceModel.SearchText,
- searchActionResourceModel.NodePathId,
- searchActionResourceModel.ItemIndex,
- searchActionResourceModel.NumberOfHits,
- searchActionResourceModel.TotalNumberOfHits,
- searchActionResourceModel.ResourceReferenceId,
- };
-
- var json = JsonConvert.SerializeObject(jsonobj);
-
- var eventEntity = new Event
- {
- EventTypeEnum = EventTypeEnum.SearchLaunchResource,
- JsonData = json,
- UserId = userId,
- GroupId = searchActionResourceModel.GroupId,
- };
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
- ///
- /// The create catalogue search action async.
- ///
- ///
- /// The search action request model.
- ///
- ///
- /// The user id.
- ///
- ///
- /// The .
- ///
- public async Task CreateCatalogueSearchActionAsync(SearchActionCatalogueModel searchActionCatalogueModel, int userId)
- {
- var jsonobj = new
- {
- searchActionCatalogueModel.SearchText,
- searchActionCatalogueModel.NodePathId,
- searchActionCatalogueModel.ItemIndex,
- searchActionCatalogueModel.NumberOfHits,
- searchActionCatalogueModel.TotalNumberOfHits,
- searchActionCatalogueModel.CatalogueId,
- };
-
- var json = JsonConvert.SerializeObject(jsonobj);
-
- var eventEntity = new Event();
- eventEntity.EventTypeEnum = EventTypeEnum.SearchLaunchCatalogue;
- eventEntity.JsonData = json;
- eventEntity.UserId = userId;
- eventEntity.GroupId = searchActionCatalogueModel.GroupId;
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
- ///
- /// The create catalogue resource search action async.
- ///
- ///
- /// The search action request model.
- ///
- ///
- /// The user id.
- ///
- ///
- /// The .
- ///
- public async Task CreateCatalogueResourceSearchActionAsync(SearchActionResourceModel searchActionResourceModel, int userId)
- {
- var jsonobj = new
- {
- searchActionResourceModel.SearchText,
- searchActionResourceModel.NodePathId,
- searchActionResourceModel.ItemIndex,
- searchActionResourceModel.ResourceReferenceId,
- searchActionResourceModel.NumberOfHits,
- searchActionResourceModel.TotalNumberOfHits,
- };
-
- var json = JsonConvert.SerializeObject(jsonobj);
-
- var eventEntity = new Event();
- eventEntity.EventTypeEnum = EventTypeEnum.LaunchCatalogueResource;
- eventEntity.JsonData = json;
- eventEntity.UserId = userId;
- eventEntity.GroupId = searchActionResourceModel.GroupId;
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
- ///
- /// The submt feedback async.
- ///
- /// The search feedback.
- /// The user id.
- /// The event id.
- public async Task SubmitFeedbackAsync(SearchFeedBackModel searchFeedbackModel, int userId)
- {
- var jsonobj = new
- {
- searchFeedbackModel.SearchText,
- searchFeedbackModel.Feedback,
- searchFeedbackModel.TotalNumberOfHits,
- };
-
- var json = JsonConvert.SerializeObject(jsonobj);
-
- var eventEntity = new Event();
- eventEntity.EventTypeEnum = EventTypeEnum.SearchSubmitFeedback;
- eventEntity.JsonData = json;
- eventEntity.UserId = userId;
- eventEntity.GroupId = searchFeedbackModel.GroupId;
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
- ///
- /// Create search term event entry.
- ///
- /// search request model.
- /// user id.
- /// The .
- public async Task CreateSearchTermEvent(SearchRequestModel searchRequestModel, int userId)
- {
- // e.g. if pagesize is 10, then offset would be 0,10,20,30
- var pageSize = searchRequestModel.PageSize;
- var offset = searchRequestModel.PageIndex * pageSize;
-
- var remainingItems = searchRequestModel.TotalNumberOfHits - offset;
- var resultsPerPage = remainingItems >= pageSize ? pageSize : remainingItems;
-
- var searchEventModel = this.mapper.Map(searchRequestModel);
- searchEventModel.ItemsViewed = resultsPerPage;
- var json = JsonConvert.SerializeObject(searchEventModel);
-
- var eventEntity = new Event();
- eventEntity.EventTypeEnum = searchRequestModel.EventTypeEnum;
- eventEntity.JsonData = json;
- eventEntity.UserId = userId;
- eventEntity.GroupId = searchRequestModel.GroupId;
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
- ///
- /// Create catalogue search term event.
- ///
- /// catalogue search request model.
- /// user id.
- /// The .
- public async Task CreateCatalogueSearchTermEvent(CatalogueSearchRequestModel catalogueSearchRequestModel, int userId)
- {
- // e.g. if pagesize is 3, then offset would be 0,3,6,9
- var offset = catalogueSearchRequestModel.PageIndex * catalogueSearchRequestModel.PageSize;
-
- var remainingItems = catalogueSearchRequestModel.TotalNumberOfHits - offset;
- var resultsPerPage = remainingItems >= catalogueSearchRequestModel.PageSize ? catalogueSearchRequestModel.PageSize : remainingItems;
-
- var searchCatalogueEventModel = this.mapper.Map(catalogueSearchRequestModel);
- searchCatalogueEventModel.ItemsViewed = resultsPerPage;
- var json = JsonConvert.SerializeObject(searchCatalogueEventModel);
- var eventEntity = new Event();
- eventEntity.EventTypeEnum = catalogueSearchRequestModel.EventTypeEnum;
- eventEntity.JsonData = json;
- eventEntity.UserId = userId;
- eventEntity.GroupId = catalogueSearchRequestModel.GroupId;
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
-
- ///
- /// The create resource search action async.
- ///
- ///
- /// The search action request model.
- ///
- ///
- /// The .
- ///
- public async Task SendResourceSearchEventClickAsync(SearchActionResourceModel searchActionResourceModel)
- {
- var searchClickPayloadModel = this.mapper.Map(searchActionResourceModel);
- searchClickPayloadModel.TimeOfClick = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- searchClickPayloadModel.SearchSignal.ProfileSignature.ApplicationId = ApplicationId;
- searchClickPayloadModel.SearchSignal.ProfileSignature.ProfileType = ProfileType;
- searchClickPayloadModel.SearchSignal.ProfileSignature.ProfileId = this.findwiseConfig.CollectionIds.Resource;
-
- return await this.SendSearchEventClickAsync(searchClickPayloadModel, true);
- }
-
- ///
- /// Create catalogue search term.
- ///
- /// catalogue search request model.
- /// results per page.
- /// user id.
- ///
- /// The .
- ///
- public async Task CreateCatalogueSearchTerm(CatalogueSearchRequestModel catalogueSearchRequestModel, int resultsPerPage, int userId)
- {
- var searchCatalogueEventModel = this.mapper.Map(catalogueSearchRequestModel);
- searchCatalogueEventModel.ItemsViewed = resultsPerPage;
- var json = JsonConvert.SerializeObject(searchCatalogueEventModel);
- var eventEntity = new Event();
- eventEntity.EventTypeEnum = catalogueSearchRequestModel.EventTypeEnum;
- eventEntity.JsonData = json;
- eventEntity.UserId = userId;
- eventEntity.GroupId = catalogueSearchRequestModel.GroupId;
-
- return await this.eventService.CreateAsync(userId, eventEntity);
- }
-
-
-
- ///
- public async Task Search(ResourceSearchRequest query, int? currentUserId)
- {
- var findwiseResultModel = await this.findwiseClient.Search(query);
-
- if (findwiseResultModel.FindwiseRequestStatus != FindwiseRequestStatus.Success)
- {
- return ResourceSearchResultModel.FailedWithStatus(findwiseResultModel.FindwiseRequestStatus);
- }
-
- var resourceMetadataViewModels = await this.GetResourceMetadataViewModels(findwiseResultModel, currentUserId);
-
- var totalHits = findwiseResultModel.SearchResults?.Stats.TotalHits;
-
- return new ResourceSearchResultModel(
- resourceMetadataViewModels,
- findwiseResultModel.FindwiseRequestStatus,
- totalHits ?? 0);
- }
-
- ///
- /// The remove resource from search async method.
- ///
- /// The resource to be removed from search.
- /// The .
- public async Task RemoveResourceFromSearchAsync(int resourceId)
- {
- try
- {
- if (string.IsNullOrEmpty(this.findwiseConfig.IndexMethod))
- {
- this.logger.LogWarning("The FindWiseIndexMethod is not configured. Resource not removed from search.");
- }
- else
- {
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.IndexUrl);
-
- var request = string.Format(this.findwiseConfig.IndexMethod, this.findwiseConfig.CollectionIds.Resource) + $"?id={resourceId.ToString()}&token={this.findwiseConfig.Token}";
-
- var response = await client.DeleteAsync(request).ConfigureAwait(false);
-
- if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- throw new Exception("AccessDenied");
- }
- else if (!response.IsSuccessStatusCode)
- {
- throw new Exception("Removal of resource to search failed: " + resourceId.ToString());
- }
- }
- }
- catch (Exception ex)
- {
- throw new Exception("Removal of resource from search failed: " + resourceId.ToString() + " : " + ex.Message);
- }
- }
-
- ///
- /// The send resource for search Async method.
- ///
- /// The resource to be added to search.
- /// The user id.
- /// number of iterations.
- /// The .
- public async Task SendResourceForSearchAsync(SearchResourceRequestModel searchResourceRequestModel, int userId, int? iterations)
- {
- try
- {
- if (string.IsNullOrEmpty(this.findwiseConfig.IndexMethod))
- {
- this.logger.LogWarning("The FindWiseIndexMethod is not configured. Resource not added to search results");
- }
- else
- {
- List resourceList =[searchResourceRequestModel];
-
- var json = JsonConvert.SerializeObject(resourceList, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-dd" });
-
- var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.IndexUrl);
-
- var request = string.Format(this.findwiseConfig.SearchBaseUrl, this.findwiseConfig.CollectionIds.Resource) + $"?token={this.findwiseConfig.Token}";
- var response = await client.PostAsync(request, stringContent).ConfigureAwait(false);
- iterations--;
- if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError("Save to FindWise failed for resourceId:" + searchResourceRequestModel.Id.ToString() + "HTTP Status Code:" + response.StatusCode.ToString());
- throw new Exception("AccessDenied");
- }
- else if (!response.IsSuccessStatusCode)
- {
- if (iterations < 0)
- {
- this.logger.LogError("Save to FindWise failed for resourceId:" + searchResourceRequestModel.Id.ToString() + "HTTP Status Code:" + response.StatusCode.ToString());
- throw new Exception("Posting of resource to search failed: " + stringContent);
- }
-
- await this.SendResourceForSearchAsync(searchResourceRequestModel, userId, iterations);
- }
- else
- {
- return true;
- }
- }
-
- return false;
- }
- catch (Exception ex)
- {
- throw new Exception("Posting of resource to search failed: " + searchResourceRequestModel.Id + " : " + ex.Message);
- }
- }
-
- ///
- /// The create catalogue search action async.
- ///
- ///
- /// The search action request model.
- ///
- ///
- /// The .
- ///
- public async Task SendCatalogueSearchEventAsync(SearchActionCatalogueModel searchActionCatalogueModel)
- {
- var searchClickPayloadModel = this.mapper.Map(searchActionCatalogueModel);
- searchClickPayloadModel.TimeOfClick = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- searchClickPayloadModel.SearchSignal.ProfileSignature.ApplicationId = ApplicationId;
- searchClickPayloadModel.SearchSignal.ProfileSignature.ProfileType = ProfileType;
- searchClickPayloadModel.SearchSignal.ProfileSignature.ProfileId = this.findwiseConfig.CollectionIds.Catalogue;
-
- return await this.SendSearchEventClickAsync(searchClickPayloadModel, false);
- }
-
- ///
- /// Gets AllCatalogue search results from findwise api call.
- ///
- /// The allcatalog search request model.
- /// The .
- public async Task GetAllCatalogueSearchResultsAsync(AllCatalogueSearchRequestModel catalogSearchRequestModel)
- {
- var viewmodel = new SearchAllCatalogueResultModel();
- try
- {
- var offset = catalogSearchRequestModel.PageIndex * catalogSearchRequestModel.PageSize;
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.SearchBaseUrl);
- var request = string.Format(
- this.findwiseConfig.SearchEndpointPath + "{0}?offset={1}&hits={2}&q={3}&token={4}",
- this.findwiseConfig.CollectionIds.Catalogue,
- offset,
- catalogSearchRequestModel.PageSize,
- this.EncodeSearchText(catalogSearchRequestModel.SearchText),
- this.findwiseConfig.Token);
-
- var response = await client.GetAsync(request).ConfigureAwait(false);
-
- if (response.IsSuccessStatusCode)
- {
- var result = response.Content.ReadAsStringAsync().Result;
- viewmodel = JsonConvert.DeserializeObject(result);
- }
- else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError($"Get AllCatalogue Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}");
- throw new Exception("AccessDenied to FindWise Server");
- }
- else
- {
- var error = response.Content.ReadAsStringAsync().Result.ToString();
- this.logger.LogError($"Get AllCatalogue Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}, Error Message:{error}");
- throw new Exception("Error with FindWise Server");
- }
-
- return viewmodel;
- }
- catch (Exception)
- {
- throw;
- }
- }
-
- ///
- /// The Get Auto suggestion Results Async method.
- ///
- /// The term.
- /// Cancellation token.
- /// The .
- public async Task GetAutoSuggestionResultsAsync(string term, CancellationToken cancellationToken = default)
- {
- var viewmodel = new AutoSuggestionModel();
-
- try
- {
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.SearchBaseUrl);
- var request = string.Format(
- this.findwiseConfig.SearchEndpointPath + "{0}?q={1}&token={2}",
- this.findwiseConfig.CollectionIds.AutoSuggestion,
- this.EncodeSearchText(term),
- this.findwiseConfig.Token);
-
-
- var response = await client.GetAsync(request).ConfigureAwait(false);
-
- if (response.IsSuccessStatusCode)
- {
- var result = response.Content.ReadAsStringAsync().Result;
- viewmodel = JsonConvert.DeserializeObject(result);
- }
- else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError($"Get Auto Suggetion Result failed in FindWise, HTTP Status Code:{response.StatusCode}");
- throw new Exception("AccessDenied to FindWise Server");
- }
- else
- {
- var error = response.Content.ReadAsStringAsync().Result.ToString();
- this.logger.LogError($"Get Auto Suggetion Result failed in FindWise, HTTP Status Code:{response.StatusCode}, Error Message:{error}");
- throw new Exception("Error with FindWise Server");
- }
-
- return viewmodel;
- }
- catch (Exception)
- {
- throw;
- }
- }
-
-
- ///
- /// The AutoSuggestion Event action async.
- ///
- ///
- /// The clic kPayload Model.
- ///
- ///
- /// The .
- ///
- public async Task SendAutoSuggestionEventAsync(AutoSuggestionClickPayloadModel clickPayloadModel)
- {
- clickPayloadModel.TimeOfClick = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- clickPayloadModel.SearchSignal.ProfileSignature.ApplicationId = ApplicationId;
- clickPayloadModel.SearchSignal.ProfileSignature.ProfileType = ProfileType;
- clickPayloadModel.SearchSignal.ProfileSignature.ProfileId = this.findwiseConfig.CollectionIds.AutoSuggestion;
-
- return await this.SendAutoSuggestionEventClickAsync(clickPayloadModel);
- }
-
- ///
- /// Send search click payload.
- ///
- /// search click payload model.
- /// isResource.
- ///
- /// The .
- ///
- private async Task SendSearchEventClickAsync(SearchClickPayloadModel searchClickPayloadModel, bool isResource)
- {
- var eventType = isResource ? "resource" : "catalog";
-
- try
- {
- if (string.IsNullOrEmpty(this.findwiseConfig.UrlClickComponent))
- {
- this.logger.LogWarning($"The UrlClickComponent is not configured. {eventType} click event not send to FindWise.");
- }
- else
- {
- var json = JsonConvert.SerializeObject(searchClickPayloadModel);
- var base64EncodedString = BinaryFormatterHelper.Base64EncodeObject(json);
-
- var request = $"{this.findwiseConfig.UrlClickComponent}?payload={base64EncodedString}";
-
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.SearchBaseUrl);
- var response = await client.PostAsync(request, null).ConfigureAwait(false);
-
- if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError($"Click event save to FindWise failed for {eventType}: {searchClickPayloadModel.ClickTargetUrl} HTTP Status Code: {response.StatusCode}");
- throw new Exception("AccessDenied");
- }
- else if (!response.IsSuccessStatusCode)
- {
- this.logger.LogError($"Click event save to FindWise failed for {eventType}: {searchClickPayloadModel.ClickTargetUrl} HTTP Status Code: {response.StatusCode}");
- throw new Exception($"Click event save to FindWise failed for {eventType}: {json}");
- }
- else
- {
- return true;
- }
- }
-
- return false;
- }
- catch (Exception ex)
- {
- throw new Exception($"Click event save to FindWise failed for {eventType}: {searchClickPayloadModel.ClickTargetUrl} : {ex.Message}");
- }
- }
-
- ///
- /// Send auto suggestion click payload.
- ///
- /// search click payload model.
- ///
- /// The .
- ///
- private async Task SendAutoSuggestionEventClickAsync(AutoSuggestionClickPayloadModel clickPayloadModel)
- {
- try
- {
- if (string.IsNullOrEmpty(this.findwiseConfig.UrlAutoSuggestionClickComponent))
- {
- this.logger.LogWarning($"The UrlClickComponent is not configured. Auto suggestion click event not send to FindWise.");
- }
- else
- {
- var json = JsonConvert.SerializeObject(clickPayloadModel);
- var base64EncodedString = BinaryFormatterHelper.Base64EncodeObject(json);
-
- var request = $"{this.findwiseConfig.UrlAutoSuggestionClickComponent}?payload={base64EncodedString}";
-
- var client = await this.findwiseClient.GetClient(this.findwiseConfig.SearchBaseUrl);
- var response = await client.PostAsync(request, null).ConfigureAwait(false);
-
- if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
- {
- this.logger.LogError($"Click event save to FindWise failed for Auto suggestion: {clickPayloadModel.ClickTargetUrl} HTTP Status Code: {response.StatusCode}");
- throw new Exception("AccessDenied");
- }
- else if (!response.IsSuccessStatusCode)
- {
- this.logger.LogError($"Click event save to FindWise failed for Auto suggestion: {clickPayloadModel.ClickTargetUrl} HTTP Status Code: {response.StatusCode}");
- throw new Exception($"Click event save to FindWise failed for Auto suggestion: {json}");
- }
- else
- {
- return true;
- }
- }
-
- return false;
- }
- catch (Exception ex)
- {
- throw new Exception($"Click event save to FindWise failed for Auto suggestion: {clickPayloadModel.ClickTargetUrl} : {ex.Message}");
- }
- }
-
-
- private string EncodeSearchText(string searchText)
- {
- string specialSearchCharacters = this.findwiseConfig.SpecialSearchCharacters;
-
- // Add backslash to the start of the string
- specialSearchCharacters = specialSearchCharacters.Replace(@"\", null);
- specialSearchCharacters = @"\" + specialSearchCharacters;
-
- for (int i = 0; i < specialSearchCharacters.Length; i++)
- {
- searchText = searchText.Replace(specialSearchCharacters[i].ToString(), @"\" + specialSearchCharacters[i]);
- }
-
- searchText = HttpUtility.UrlEncode(searchText);
- return searchText;
- }
-
- private async Task> GetResourceMetadataViewModels(
- FindwiseResultModel findwiseResultModel, int? currentUserId)
- {
- List resourceActivities = new List() { };
- List resourceMetadataViewModels = new List() { };
- var documentsFound = findwiseResultModel.SearchResults?.DocumentList.Documents?.ToList() ??
- new List();
- var findwiseResourceIds = documentsFound.Select(d => int.Parse(d.Id)).ToList();
-
- if (!findwiseResourceIds.Any())
- {
- return new List();
- }
-
- var resourcesFound = await this.resourceRepository.GetResourcesFromIds(findwiseResourceIds);
-
- if (currentUserId.HasValue)
- {
- List resourceIds = resourcesFound.Select(x => x.Id).ToList();
- List userIds = new List() { currentUserId.Value };
-
- resourceActivities = (await this.resourceRepository.GetResourceActivityPerResourceMajorVersion(resourceIds, userIds))?.ToList() ?? new List() { };
- }
-
- resourceMetadataViewModels = resourcesFound.Select(resource => this.MapToViewModel(resource, resourceActivities.Where(x => x.ResourceId == resource.Id).ToList()))
- .OrderBySequence(findwiseResourceIds)
- .ToList();
-
- var unmatchedResources = findwiseResourceIds
- .Except(resourceMetadataViewModels.Select(r => r.ResourceId)).ToList();
-
- if (unmatchedResources.Any())
- {
- var unmatchedResourcesIdsString = string.Join(", ", unmatchedResources);
- this.logger.LogWarning(
- "Findwise returned documents that were not found in the database with IDs: " +
- unmatchedResourcesIdsString);
- }
-
- return resourceMetadataViewModels;
- }
-
- private ResourceMetadataViewModel MapToViewModel(Resource resource, List resourceActivities)
- {
- var hasCurrentResourceVersion = resource.CurrentResourceVersion != null;
- var hasRating = resource.CurrentResourceVersion?.ResourceVersionRatingSummary != null;
-
- List majorVersionIdActivityStatusDescription = new List() { };
-
- if (resourceActivities != null && resourceActivities.Count != 0)
- {
- majorVersionIdActivityStatusDescription = ActivityStatusHelper.GetMajorVersionIdActivityStatusDescriptionLSPerResource(resource, resourceActivities)
- .ToList();
- }
-
- if (!hasCurrentResourceVersion)
- {
- this.logger.LogInformation(
- $"Resource with id {resource.Id} is missing a current resource version");
- }
-
- if (!hasRating)
- {
- this.logger.LogInformation(
- $"Resource with id {resource.Id} is missing a ResourceVersionRatingSummary");
- }
-
- var resourceTypeNameOrEmpty = resource.GetResourceTypeNameOrEmpty();
- if (resourceTypeNameOrEmpty == string.Empty)
- {
- this.logger.LogError($"Resource has unrecognised type: {resource.ResourceTypeEnum}");
- }
-
-
- return new ResourceMetadataViewModel(
- resource.Id,
- resource.CurrentResourceVersion?.Title ?? ResourceHelpers.NoResourceVersionText,
- resource.CurrentResourceVersion?.Description ?? string.Empty,
- resource.ResourceReference.Select(this.GetResourceReferenceViewModel).ToList(),
- resourceTypeNameOrEmpty,
- resource.CurrentResourceVersion?.MajorVersion ?? 0,
- resource.CurrentResourceVersion?.ResourceVersionRatingSummary?.AverageRating ?? 0.0m,
- majorVersionIdActivityStatusDescription
- );
- }
-
- private ResourceReferenceViewModel GetResourceReferenceViewModel(
- ResourceReference resourceReference)
- {
- return new ResourceReferenceViewModel(
- resourceReference.OriginalResourceReferenceId,
- resourceReference.GetCatalogue(),
- this.learningHubService.GetResourceLaunchUrl(resourceReference.OriginalResourceReferenceId));
- }
- }
-}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
index c2e0ae59..56b9450e 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
@@ -33,8 +33,7 @@ public static void AddServices(this IServiceCollection services, IConfiguration
}
else
{
- services.AddScoped();
- services.AddScoped();
+ services.AddScoped();
}
services.AddHttpClient();
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/SearchServiceTests.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/SearchServiceTests.cs
index d8d0568b..bc4f1407 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/SearchServiceTests.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/SearchServiceTests.cs
@@ -20,6 +20,7 @@ namespace LearningHub.Nhs.OpenApi.Tests.Services.Services
using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients;
using LearningHub.Nhs.OpenApi.Services.Interface.Services;
using LearningHub.Nhs.OpenApi.Services.Services;
+ using LearningHub.Nhs.OpenApi.Services.Services.AzureSearch;
using LearningHub.Nhs.OpenApi.Tests.TestHelpers;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -33,11 +34,13 @@ public class SearchServiceTests
private readonly Mock learningHubService;
private readonly Mock resourceRepository;
private readonly Mock resourceService;
+ private readonly Mock cachingService;
private readonly Mock eventService;
- private readonly SearchService searchService;
+ private readonly AzureSearchService searchService;
private readonly Mock> findwiseConfig;
- private Mock> mockLogger;
+ private Mock> mockLogger;
private readonly Mock mapper;
+ private readonly Mock> azureSearchConfig;
public SearchServiceTests()
{
@@ -45,19 +48,22 @@ public SearchServiceTests()
this.learningHubService = new Mock();
this.resourceRepository = new Mock();
this.resourceService = new Mock();
+ this.cachingService = new Mock();
+ this.azureSearchConfig = new Mock>();
this.eventService = new Mock();
this.mapper = new Mock();
this.findwiseConfig = new Mock>();
- this.mockLogger = new Mock>();
- this.searchService = new SearchService(
+ this.mockLogger = new Mock>();
+ this.searchService = new AzureSearchService(
this.learningHubService.Object,
this.eventService.Object,
- this.findwiseClient.Object,
- this.findwiseConfig.Object,
+ this.azureSearchConfig.Object,
this.resourceRepository.Object,
+ this.cachingService.Object,
this.mockLogger.Object,
- this.mapper.Object);
+ this.mapper.Object
+ );
}
public static IEnumerable