Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Data.Database;
public interface IValidationExceptionData
{
Task<bool> Create(ValidationException exception);
Task<List<ValidationException>?> GetAllFilteredExceptions(ExceptionStatus? exceptionStatus, SortOrder? sortOrder, ExceptionCategory exceptionCategory);
Task<List<ValidationException>?> GetFilteredExceptions(ExceptionStatus? exceptionStatus, SortOrder? sortOrder, ExceptionCategory exceptionCategory);
Task<ValidationException?> GetExceptionById(int exceptionId);
Task<bool> RemoveOldException(string nhsNumber, string screeningName);
Task<ServiceResponseModel> UpdateExceptionServiceNowId(int exceptionId, string serviceNowId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ namespace Data.Database;
using System;
using System.Data;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using Common;
using DataServices.Client;
using Microsoft.Extensions.Logging;
using Model;
using Model.DTO;
using Model.Enums;
using NHS.CohortManager.Shared.Utilities;

public class ValidationExceptionData : IValidationExceptionData
{
private readonly ILogger<ValidationExceptionData> _logger;
private readonly IDataServiceClient<ExceptionManagement> _validationExceptionDataServiceClient;
private readonly IDataServiceClient<ParticipantDemographic> _demographicDataServiceClient;
public ValidationExceptionData(
ILogger<ValidationExceptionData> logger,
IDataServiceClient<ExceptionManagement> validationExceptionDataServiceClient,
Expand All @@ -23,10 +25,9 @@ IDataServiceClient<ParticipantDemographic> demographicDataServiceClient
{
_logger = logger;
_validationExceptionDataServiceClient = validationExceptionDataServiceClient;
_demographicDataServiceClient = demographicDataServiceClient;
}

public async Task<List<ValidationException>?> GetAllFilteredExceptions(ExceptionStatus? exceptionStatus, SortOrder? sortOrder, ExceptionCategory exceptionCategory)
public async Task<List<ValidationException>?> GetFilteredExceptions(ExceptionStatus? exceptionStatus, SortOrder? sortOrder, ExceptionCategory exceptionCategory)
{
var category = (int)exceptionCategory;
var exceptions = await _validationExceptionDataServiceClient.GetByFilter(x => x.Category != null && x.Category.Value == category);
Expand All @@ -45,16 +46,10 @@ IDataServiceClient<ParticipantDemographic> demographicDataServiceClient
return null;
}

if (!long.TryParse(exception.NhsNumber, out long nhsNumber))
{
throw new FormatException("Unable to parse NHS Number");
}

var participantDemographic = await _demographicDataServiceClient.GetSingleByFilter(x => x.NhsNumber == nhsNumber);

return GetExceptionDetails(exception.ToValidationException(), participantDemographic);
return GetValidationExceptionWithDetails(exception);
}


public async Task<bool> Create(ValidationException exception)
{
var exceptionToUpdate = new ExceptionManagement().FromValidationException(exception);
Expand Down Expand Up @@ -129,6 +124,27 @@ public async Task<ServiceResponseModel> UpdateExceptionServiceNowId(int exceptio
return [];
}

var filteredExceptions = await GetFilteredReportExceptions(reportDate, exceptionCategory);

if (filteredExceptions == null || !filteredExceptions.Any())
return [];

var results = filteredExceptions.Select(GetValidationExceptionWithDetails);
return results.Where(x => x != null).ToList()!;
}

private ServiceResponseModel CreateSuccessResponse(string message) => CreateResponse(true, HttpStatusCode.OK, message);
private ServiceResponseModel CreateErrorResponse(string message, HttpStatusCode statusCode) => CreateResponse(false, statusCode, message);

private ValidationException? GetValidationExceptionWithDetails(ExceptionManagement exception)
{
var validationException = exception.ToValidationException();
var participantDemographic = ExtractParticipantDemographicFromErrorRecord(exception.ErrorRecord);
return GetExceptionDetails(validationException, participantDemographic);
}

private async Task<IEnumerable<ExceptionManagement>?> GetFilteredReportExceptions(DateTime? reportDate, ExceptionCategory exceptionCategory)
{
var filteredExceptions = (await _validationExceptionDataServiceClient.GetByFilter(x =>
x.Category.HasValue && (x.Category.Value == (int)ExceptionCategory.Confusion || x.Category.Value == (int)ExceptionCategory.Superseded)))?.AsEnumerable();

Expand All @@ -144,18 +160,48 @@ public async Task<ServiceResponseModel> UpdateExceptionServiceNowId(int exceptio
filteredExceptions = filteredExceptions?.Where(x => x.DateCreated >= startDate && x.DateCreated < endDate);
}

if (filteredExceptions?.Any() != true)
return [];
return filteredExceptions;
}

var tasks = filteredExceptions.Select(async exception =>
private ParticipantDemographic? ExtractParticipantDemographicFromErrorRecord(string? errorRecord)
{
if (string.IsNullOrWhiteSpace(errorRecord))
{
var validationException = exception.ToValidationException();
var participantDemographic = long.TryParse(exception.NhsNumber, out long nhsNumber) ? await _demographicDataServiceClient.GetSingleByFilter(x => x.NhsNumber == nhsNumber) : null;
return GetExceptionDetails(validationException, participantDemographic);
});
return null;
}

var results = await Task.WhenAll(tasks);
return results.Where(x => x != null).ToList()!;
try
{
var errorRecordData = JsonSerializer.Deserialize<ErrorRecordDto>(errorRecord);
if (errorRecordData == null)
{
return null;
}

return new ParticipantDemographic
{
NhsNumber = long.TryParse(errorRecordData.NhsNumber, out long nhsNumber) ? nhsNumber : 0,
GivenName = errorRecordData.FirstName,
FamilyName = errorRecordData.FamilyName,
DateOfBirth = MappingUtilities.FormatDateTime(MappingUtilities.ParseDates(errorRecordData.DateOfBirth)),
SupersededByNhsNumber = long.TryParse(errorRecordData.SupersededByNhsNumber, out long superseded) ? superseded : null,
Gender = errorRecordData.Gender,
AddressLine1 = errorRecordData.AddressLine1,
AddressLine2 = errorRecordData.AddressLine2,
AddressLine3 = errorRecordData.AddressLine3,
AddressLine4 = errorRecordData.AddressLine4,
AddressLine5 = errorRecordData.AddressLine5,
PostCode = errorRecordData.Postcode,
TelephoneNumberHome = errorRecordData.TelephoneNumber,
EmailAddressHome = errorRecordData.EmailAddress,
PrimaryCareProvider = errorRecordData.PrimaryCareProvider,
};
}
catch (JsonException ex)
{
_logger.LogWarning(ex, "Failed to deserialize ErrorRecord JSON: {ErrorRecord}. Error: {Error}", errorRecord, ex.Message);
return null;
}
}

private ServiceResponseModel CreateResponse(bool success, HttpStatusCode statusCode, string message)
Expand All @@ -173,8 +219,6 @@ private ServiceResponseModel CreateResponse(bool success, HttpStatusCode statusC
};
}

private ServiceResponseModel CreateSuccessResponse(string message) => CreateResponse(true, HttpStatusCode.OK, message);
private ServiceResponseModel CreateErrorResponse(string message, HttpStatusCode statusCode) => CreateResponse(false, statusCode, message);

private static string? ValidateServiceNowId(string serviceNowId)
{
Expand Down Expand Up @@ -225,7 +269,7 @@ private ServiceResponseModel CreateResponse(bool success, HttpStatusCode statusC

if (participantDemographic == null)
{
_logger.LogWarning("Missing data: ParticipantDemographic: {ParticipantDemographic}", participantDemographic != null);
_logger.LogWarning("Missing participant demographic data for exception");
}

return exception;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Model.DTO;

public class ErrorRecordDto
{
public string? NhsNumber { get; set; }
public string? SupersededByNhsNumber { get; set; }
public string? FirstName { get; set; }
public string? FamilyName { get; set; }
public string? DateOfBirth { get; set; }
public short? Gender { get; set; }
public string? AddressLine1 { get; set; }
public string? AddressLine2 { get; set; }
public string? AddressLine3 { get; set; }
public string? AddressLine4 { get; set; }
public string? AddressLine5 { get; set; }
public string? Postcode { get; set; }
public string? PrimaryCareProvider { get; set; }
public string? TelephoneNumber { get; set; }
public string? EmailAddress { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymou
return CreatePaginatedResponse(req, reportExceptions!.AsQueryable(), page);
}

var allExceptions = await _validationData.GetAllFilteredExceptions(exceptionStatus, sortOrder, exceptionCategory);
return CreatePaginatedResponse(req, allExceptions!.AsQueryable(), page);
var filteredExceptions = await _validationData.GetFilteredExceptions(exceptionStatus, sortOrder, exceptionCategory);
return CreatePaginatedResponse(req, filteredExceptions!.AsQueryable(), page);
}
catch (Exception ex)
{
Expand Down
6 changes: 4 additions & 2 deletions application/CohortManager/src/Web/app/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export const formatNhsNumber = (nhsNumber: string): string => {
return nhsNumber.replace(/(\d{3})(\d{3})(\d{4})/, "$1 $2 $3");
export const formatNhsNumber = (nhsNumber: string | number): string => {
if (!nhsNumber) return '';
const nhsString = String(nhsNumber);
return nhsString.replace(/(\d{3})(\d{3})(\d{4})/, "$1 $2 $3");
};

export const formatDate = (dateString: string): string => {
Expand Down
Loading
Loading