From e5f7c7af140a5df5c3e78dbab8c1b9c0254c7b16 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:49:10 +0000 Subject: [PATCH 01/19] feat: data service migration --- .../CreateCohortDistribution.cs | 18 +- .../CreateCohortDistribution/Program.cs | 6 +- .../RetrieveParticipantData/Program.cs | 6 +- .../RetrieveParticipantData.cs | 13 +- .../Shared/Common/CreateParticipant.cs | 14 +- .../Common/Interfaces/ICreateParticipant.cs | 2 +- .../src/Functions/Shared/Model/Participant.cs | 20 ++ .../createParticipant/Program.cs | 1 - .../updateParticipantDetails/Program.cs | 1 - .../updateParticipantDetails.cs | 18 +- .../UpdateParticipantDetailsTests.cs | 274 +++++------------- .../UpdateParticipantDetailsTests.csproj | 1 + 12 files changed, 141 insertions(+), 233 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs index 65c557984..d33198533 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs @@ -9,6 +9,7 @@ namespace NHS.CohortManager.CohortDistributionService; using Model; using Model.Enums; using Data.Database; +using DataServices.Client; public class CreateCohortDistribution { @@ -16,22 +17,22 @@ public class CreateCohortDistribution private readonly ICallFunction _callFunction; private readonly ICohortDistributionHelper _CohortDistributionHelper; private readonly IExceptionHandler _exceptionHandler; - private readonly IParticipantManagerData _participantManagerData; private readonly IAzureQueueStorageHelper _azureQueueStorageHelper; + private readonly IDataServiceClient _participantManagementClient; public CreateCohortDistribution(ILogger logger, ICallFunction callFunction, ICohortDistributionHelper CohortDistributionHelper, IExceptionHandler exceptionHandler, - IParticipantManagerData participantManagerData, + IDataServiceClient participantManagementClient, IAzureQueueStorageHelper azureQueueStorageHelper) { _logger = logger; _callFunction = callFunction; _CohortDistributionHelper = CohortDistributionHelper; _exceptionHandler = exceptionHandler; - _participantManagerData = participantManagerData; _azureQueueStorageHelper = azureQueueStorageHelper; + _participantManagementClient = participantManagementClient; } [Function(nameof(CreateCohortDistribution))] @@ -79,7 +80,9 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur var ignoreParticipantExceptions = (bool)DatabaseHelper.ConvertBoolStringToBoolByType("IgnoreParticipantExceptions", DataTypes.Boolean); - if (ParticipantHasException(basicParticipantCsvRecord.NhsNumber, participantData.ScreeningServiceId) && !ignoreParticipantExceptions) // Will only run if IgnoreParticipantExceptions is false. + bool participantHasException = await ParticipantHasException(basicParticipantCsvRecord.NhsNumber, participantData.ScreeningServiceId); + + if (participantHasException && !ignoreParticipantExceptions) // Will only run if IgnoreParticipantExceptions is false. { var ParticipantExceptionErrorMessage = $"Unable to add to cohort distribution. As participant with ParticipantId: {participantData.ParticipantId}. Has an Exception against it"; _logger.LogInformation(ParticipantExceptionErrorMessage, participantData.ParticipantId); @@ -149,10 +152,9 @@ private async Task AddCohortDistribution(CohortDistributionPart return response; } - private bool ParticipantHasException(string nhsNumber, string screeningId) + private async Task ParticipantHasException(string nhsNumber, string screeningId) { - var participant = _participantManagerData.GetParticipant(nhsNumber, screeningId); - var exceptionFlag = Enum.TryParse(participant.ExceptionFlag, out Exists value) ? value : Exists.No; - return exceptionFlag == Exists.Yes; + var participant = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber.ToString() == nhsNumber && p.ScreeningId.ToString() == screeningId); + return participant.ExceptionFlag == 1; } } diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs index 2ffed571a..997c78088 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs @@ -3,16 +3,20 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; +using DataServices.Client; +using Model; var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() + .AddDataServicesHandler() + .AddDataService(Environment.GetEnvironmentVariable("ParticipantManagementUrl")) + .Build() .ConfigureServices(services => { services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.TryAddTransient(); - services.TryAddTransient(); }) .AddAzureQueues() .AddDatabaseConnection() diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/Program.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/Program.cs index c2e1af01f..6abecd78c 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/Program.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/Program.cs @@ -2,14 +2,18 @@ using Data.Database; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using DataServices.Client; +using Model; var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() + .AddDataServicesHandler() + .AddDataService(Environment.GetEnvironmentVariable("ParticipantManagementUrl")) + .Build() .ConfigureServices(services => { services.AddSingleton(); services.AddSingleton(); - services.AddTransient(); services.AddSingleton(); services.AddTransient(); services.AddSingleton(); diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index 208d80bd3..3507fbf49 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -10,24 +10,27 @@ namespace NHS.CohortManager.CohortDistributionService; using System.Text; using System.Text.Json; using Data.Database; +using DataServices.Client; public class RetrieveParticipantData { private readonly ICreateResponse _createResponse; private readonly ILogger _logger; - private readonly IParticipantManagerData _participantManagerData; private readonly ICreateDemographicData _createDemographicData; private readonly ICreateParticipant _createParticipant; private readonly IExceptionHandler _exceptionHandler; + private readonly IDataServiceClient _participantManagementClient; - public RetrieveParticipantData(ICreateResponse createResponse, ILogger logger, IParticipantManagerData participantManagerData, ICreateDemographicData createDemographicData, ICreateParticipant createParticipant, IExceptionHandler exceptionHandler) + public RetrieveParticipantData(ICreateResponse createResponse, ILogger logger, + ICreateDemographicData createDemographicData, ICreateParticipant createParticipant, + IExceptionHandler exceptionHandler, IDataServiceClient participantManagementClient) { _createResponse = createResponse; _logger = logger; - _participantManagerData = participantManagerData; _createDemographicData = createDemographicData; _createParticipant = createParticipant; _exceptionHandler = exceptionHandler; + _participantManagementClient = participantManagementClient; } [Function("RetrieveParticipantData")] @@ -52,8 +55,10 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano try { - var participantData = _participantManagerData.GetParticipantFromIDAndScreeningService(requestBody); + var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber.ToString() == requestBody.NhsNumber && + p.ScreeningId.ToString() == requestBody.ScreeningService); _logger.LogInformation("Got the participant. ScreeningId: {ScreeningServiceId}", participantData.ScreeningId); + var demographicData = _createDemographicData.GetDemographicData(requestBody.NhsNumber); participant = _createParticipant.CreateCohortDistributionParticipantModel(participantData, demographicData); var responseBody = JsonSerializer.Serialize(participant); diff --git a/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs b/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs index 2bddc4dc2..23ba0e194 100644 --- a/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs +++ b/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs @@ -52,12 +52,12 @@ public Participant CreateResponseParticipantModel(BasicParticipantData participa } - public CohortDistributionParticipant CreateCohortDistributionParticipantModel(Participant participant, Demographic demographic) + public CohortDistributionParticipant CreateCohortDistributionParticipantModel(ParticipantManagement participant, Demographic demographic) { return new CohortDistributionParticipant { - ParticipantId = participant.ParticipantId, - NhsNumber = participant.NhsNumber, + ParticipantId = participant.ParticipantId.ToString(), + NhsNumber = participant.NHSNumber.ToString(), SupersededByNhsNumber = demographic.SupersededByNhsNumber, PrimaryCareProvider = demographic.PrimaryCareProvider, PrimaryCareProviderEffectiveFromDate = demographic.PrimaryCareProviderEffectiveFromDate, @@ -85,12 +85,10 @@ public CohortDistributionParticipant CreateCohortDistributionParticipantModel(Pa PreferredLanguage = demographic.PreferredLanguage, IsInterpreterRequired = demographic.IsInterpreterRequired, ReasonForRemoval = participant.ReasonForRemoval, - ReasonForRemovalEffectiveFromDate = participant.ReasonForRemovalEffectiveFromDate, + ReasonForRemovalEffectiveFromDate = participant.ReasonForRemovalDate.ToString(), RecordInsertDateTime = demographic.RecordInsertDateTime, - RecordUpdateDateTime = participant.RecordUpdateDateTime, - ScreeningAcronym = participant.ScreeningAcronym, - ScreeningServiceId = participant.ScreeningId, - ScreeningName = participant.ScreeningName, + RecordUpdateDateTime = participant.RecordUpdateDateTime.ToString(), + ScreeningServiceId = participant.ScreeningId.ToString(), Extracted = null, RecordType = participant.RecordType, CurrentPosting = demographic.CurrentPosting, diff --git a/application/CohortManager/src/Functions/Shared/Common/Interfaces/ICreateParticipant.cs b/application/CohortManager/src/Functions/Shared/Common/Interfaces/ICreateParticipant.cs index 84b89be69..97b80c203 100644 --- a/application/CohortManager/src/Functions/Shared/Common/Interfaces/ICreateParticipant.cs +++ b/application/CohortManager/src/Functions/Shared/Common/Interfaces/ICreateParticipant.cs @@ -5,5 +5,5 @@ namespace Common; public interface ICreateParticipant { public Participant CreateResponseParticipantModel(BasicParticipantData participant, Demographic demographic); - public CohortDistributionParticipant CreateCohortDistributionParticipantModel(Participant participant, Demographic demographic); + public CohortDistributionParticipant CreateCohortDistributionParticipantModel(ParticipantManagement participant, Demographic demographic); } diff --git a/application/CohortManager/src/Functions/Shared/Model/Participant.cs b/application/CohortManager/src/Functions/Shared/Model/Participant.cs index 1b1902193..f34a7604a 100644 --- a/application/CohortManager/src/Functions/Shared/Model/Participant.cs +++ b/application/CohortManager/src/Functions/Shared/Model/Participant.cs @@ -109,6 +109,26 @@ public ParticipantDemographic ToParticipantDemographic() }; } + public ParticipantManagement ToParticipantManagement() + { + var participantManagement = new ParticipantManagement + { + ParticipantId = long.TryParse(ParticipantId, out var participantId) ? participantId : 0, + ScreeningId = long.TryParse(ScreeningId, out var screeningId) ? screeningId : 0, + NHSNumber = long.TryParse(NhsNumber, out var nhsNumber) ? nhsNumber : 0, + RecordType = RecordType ?? string.Empty, + EligibilityFlag = short.TryParse(EligibilityFlag, out var eligibilityFlag) ? eligibilityFlag : (short)0, + ReasonForRemoval = ReasonForRemoval, + ReasonForRemovalDate = DateTime.TryParse(ReasonForRemovalEffectiveFromDate, out var removalDate) ? removalDate : null, + BusinessRuleVersion = BusinessRuleVersion, + ExceptionFlag = short.TryParse(ExceptionFlag, out var exceptionFlag) ? exceptionFlag : (short)0, + RecordInsertDateTime = DateTime.TryParse(RecordInsertDateTime, out var insertDate) ? insertDate : null, + RecordUpdateDateTime = DateTime.TryParse(RecordUpdateDateTime, out var updateDate) ? updateDate : null, + }; + + return participantManagement; + } + private int GetInvalidFlag() { int result = 0; diff --git a/application/CohortManager/src/Functions/screeningDataServices/createParticipant/Program.cs b/application/CohortManager/src/Functions/screeningDataServices/createParticipant/Program.cs index fd91d1413..a82a709e0 100644 --- a/application/CohortManager/src/Functions/screeningDataServices/createParticipant/Program.cs +++ b/application/CohortManager/src/Functions/screeningDataServices/createParticipant/Program.cs @@ -13,7 +13,6 @@ .ConfigureServices(services => { services.AddTransient(); - services.AddTransient(); services.AddSingleton(); services.AddTransient(); services.AddSingleton(); diff --git a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/Program.cs b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/Program.cs index 7d9249971..309ac3e13 100644 --- a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/Program.cs +++ b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/Program.cs @@ -11,7 +11,6 @@ services.AddSingleton(); services.AddSingleton(); services.AddTransient(); - services.AddTransient(); services.AddSingleton(); }) .AddDatabaseConnection() diff --git a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs index 8a2160e02..06f8ce54d 100644 --- a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs +++ b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs @@ -10,22 +10,25 @@ namespace updateParticipantDetails; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; using Model; +using DataServices.Client; public class UpdateParticipantDetails { private readonly ILogger _logger; private readonly ICreateResponse _createResponse; - private readonly IParticipantManagerData _participantManagerData; private readonly IExceptionHandler _handleException; private readonly ICallFunction _callFunction; + private readonly IDataServiceClient _participantManagementClient; - public UpdateParticipantDetails(ILogger logger, ICreateResponse createResponse, IParticipantManagerData participantManagerData, IExceptionHandler handleException, ICallFunction callFunction) + public UpdateParticipantDetails(ILogger logger, ICreateResponse createResponse, + IExceptionHandler handleException, ICallFunction callFunction, + IDataServiceClient participantManagementClient) { _logger = logger; _createResponse = createResponse; - _participantManagerData = participantManagerData; _handleException = handleException; _callFunction = callFunction; + _participantManagementClient = participantManagementClient; } [Function("updateParticipantDetails")] @@ -42,9 +45,12 @@ public async Task Run([HttpTrigger(AuthorizationLevel.Anonymou participantCsvRecord = JsonSerializer.Deserialize(requestBody); } - var existingParticipantData = _participantManagerData.GetParticipant(participantCsvRecord.Participant.NhsNumber, participantCsvRecord.Participant.ScreeningId); + Participant reqParticipant = participantCsvRecord.Participant; + + var existingParticipantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber == long.Parse(reqParticipant.NhsNumber) + && p.ScreeningId == long.Parse(reqParticipant.ParticipantId)); - var response = await ValidateData(existingParticipantData, participantCsvRecord.Participant, participantCsvRecord.FileName); + var response = await ValidateData(new Participant(existingParticipantData), participantCsvRecord.Participant, participantCsvRecord.FileName); if (response.IsFatal) { _logger.LogError("Validation Error: A fatal Rule was violated and therefore the record cannot be added to the database with Nhs number: {NhsNumber}", participantCsvRecord.Participant.NhsNumber); @@ -57,7 +63,7 @@ public async Task Run([HttpTrigger(AuthorizationLevel.Anonymou participantCsvRecord.Participant.ExceptionFlag = "Y"; } - var isAdded = _participantManagerData.UpdateParticipantDetails(participantCsvRecord); + var isAdded = await _participantManagementClient.Update(reqParticipant.ToParticipantManagement()); if (isAdded) { diff --git a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs index e061b0140..a3e8530f1 100644 --- a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs +++ b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs @@ -7,258 +7,128 @@ namespace NHS.CohortManager.Tests.UnitTests.ScreeningDataServicesTests; using Model; using Model.Enums; using Moq; +using updateParticipantDetails; +using DataServices.Client; +using Common; +using System.Linq.Expressions; +using NHS.CohortManager.Tests.TestUtils; +using System.Text.Json; [TestClass] public class UpdateParticipantDetailsTests { - private readonly Mock _mockDBConnection = new(); private readonly ParticipantCsvRecord _participantCsvRecord; - private readonly Mock _commandMock = new(); - private readonly Mock _moqDataReader = new(); - private readonly Mock> _loggerMock = new(); - private readonly Mock _databaseHelperMock = new(); - private readonly Mock _mockParameter = new(); - private readonly Mock _mockTransaction = new(); - private readonly Mock _webResponse = new(); + private readonly Mock> _participantManagementClientMock = new(); + private readonly Mock> _loggerMock = new(); + private readonly Mock _callFunctionMock = new(); + private readonly Mock _createResponseMock = new(); + private readonly Mock _exceptionHandlerMock = new(); + private readonly SetupRequest _setupRequest = new(); public UpdateParticipantDetailsTests() { - Environment.SetEnvironmentVariable("DtOsDatabaseConnectionString", "DtOsDatabaseConnectionString"); - Environment.SetEnvironmentVariable("LookupValidationURL", "LookupValidationURL"); + // Environment.SetEnvironmentVariable("DtOsDatabaseConnectionString", "DtOsDatabaseConnectionString"); + // Environment.SetEnvironmentVariable("LookupValidationURL", "LookupValidationURL"); + _participantManagementClientMock + .Setup(c => c.Update(It.IsAny())) + .ReturnsAsync(true); - _mockDBConnection.Setup(x => x.ConnectionString).Returns("someFakeCOnnectionString"); - _mockDBConnection.Setup(x => x.BeginTransaction()).Returns(_mockTransaction.Object); - _mockTransaction.Setup(x => x.Commit()); - _commandMock.Setup(c => c.Dispose()); - _commandMock.SetupSequence(m => m.Parameters.Add(It.IsAny())); - _commandMock.Setup(m => m.Parameters.Clear()).Verifiable(); - _commandMock.SetupProperty(c => c.CommandType); - _commandMock.SetupProperty(c => c.CommandText); - _commandMock.SetupProperty(c => c.Transaction); - _mockParameter.Setup(m => m.ParameterName).Returns("@fakeparam"); - _mockParameter.Setup(m => m.Value).Returns("fakeValue"); - - _commandMock.Setup(x => x.CreateParameter()).Returns(_mockParameter.Object); - - _mockDBConnection.Setup(m => m.CreateCommand()).Returns(_commandMock.Object); - _commandMock.Setup(m => m.Parameters.Add(It.IsAny())).Verifiable(); - _commandMock.Setup(m => m.ExecuteReader()) - .Returns(_moqDataReader.Object); - _mockDBConnection.Setup(conn => conn.Open()); - - _databaseHelperMock.Setup(helper => helper.ConvertNullToDbNull(It.IsAny())).Returns(DBNull.Value); - _databaseHelperMock.Setup(helper => helper.ParseDates(It.IsAny())).Returns(DateTime.Today); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement {NHSNumber = 1, ScreeningId = 1}); _participantCsvRecord = new ParticipantCsvRecord { FileName = "test.csv", - Participant = GetParticipant() + Participant = new Participant() + { + ParticipantId = "1", + NhsNumber = "123456", + SupersededByNhsNumber = "789012", + PrimaryCareProvider = "ABC Clinic", + NamePrefix = "Mr.", + FirstName = "John", + OtherGivenNames = "Middle", + FamilyName = "Doe", + DateOfBirth = "1990-01-01", + Gender = Gender.Male, + AddressLine1 = "123 Main Street", + AddressLine2 = "Apt 101", + AddressLine3 = "Suburb", + AddressLine4 = "City", + AddressLine5 = "State", + Postcode = "12345", + ReasonForRemoval = "Moved", + ReasonForRemovalEffectiveFromDate = "2023-01-01", + DateOfDeath = "2024-04-23", + TelephoneNumber = "123-456-7890", + MobileNumber = "987-654-3210", + EmailAddress = "john.doe@example.com", + PreferredLanguage = "English", + IsInterpreterRequired = "0", + RecordType = Actions.Amended, + ScreeningId = "1" + + } }; } [TestMethod] - public void UpdateParticipantDetails_Success() + public async Task Run_ValidRequest_ReturnOk() { // Arrange - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(true) - .Returns(false); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync((ParticipantManagement)null); - _commandMock.Setup(x => x.ExecuteNonQuery()).Returns(1); - SetUpReader(); - - _webResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.OK); - - - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); + var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, + _callFunctionMock.Object, _participantManagementClientMock.Object); + + string json = JsonSerializer.Serialize(_participantCsvRecord); + var request = _setupRequest.Setup(json); // Act - var participant = GetParticipant(); - var result = sut.UpdateParticipantDetails(_participantCsvRecord); + var response = await sut.Run(request.Object); // Assert - Assert.IsTrue(result); + Assert.AreEqual(response.StatusCode, HttpStatusCode.OK); } [TestMethod] - public void UpdateParticipantDetails_FailsToGetOldId_False() + public async Task Run_GetOldParticipantFails_ReturnInternalServerError() { // Arrange - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(true) - .Returns(false); - - _commandMock.Setup(x => x.ExecuteNonQuery()) - .Throws(); + var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, + _callFunctionMock.Object, _participantManagementClientMock.Object); - SetUpReader(); - - _webResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.OK); - - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); + string json = JsonSerializer.Serialize(_participantCsvRecord); + var request = _setupRequest.Setup(json); // Act - var result = sut.UpdateParticipantDetails(_participantCsvRecord); + var response = await sut.Run(request.Object); // Assert - Assert.IsFalse(result); + Assert.AreEqual(response.StatusCode, HttpStatusCode.InternalServerError); } - - [TestMethod] - public void UpdateParticipantAsEligible_UpdatesRecords_True() + public void Run_LookupValidationFails_ReturnInternalServerError() { // Arrange _moqDataReader.SetupSequence(reader => reader.Read()) .Returns(true) .Returns(false); - _commandMock.Setup(x => x.ExecuteNonQuery()).Returns(1); - SetUpReader(); - - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); - - // Act - var result = sut.UpdateParticipantAsEligible(_participantCsvRecord.Participant); - - // Assert - Assert.IsTrue(result); - } - - [TestMethod] - public void UpdateParticipantAsEligible_DoesNotGetOldId_False() - { - // Arrange - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(false); - _commandMock.Setup(x => x.ExecuteNonQuery()).Returns(0); - - SetUpReader(); - - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); - - // Act - var result = sut.UpdateParticipantAsEligible(_participantCsvRecord.Participant); - - // Assert - Assert.IsFalse(result); - } - - [TestMethod] - public void GetParticipantId_SuccessfulQueryExecution_ReturnsParticipantId() - { - // Arrange - var nhsId = "123456"; - var screeningId = "1"; - var expectedParticipantId = 123456; - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(true) - .Returns(false); - _moqDataReader.Setup(reader => reader.GetInt32(0)).Returns(expectedParticipantId); - _commandMock.Setup(x => x.ExecuteNonQuery()).Returns(1); - - SetUpReader(); - - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); - - // Act - var result = sut.GetParticipant(nhsId, screeningId); - - // Assert - Assert.AreEqual(nhsId, result.NhsNumber); - } - - [TestMethod] - public void GetParticipantId_EmptyResultSet_ReturnsDefaultParticipantId() - { - // Arrange - var nhsId = "123456"; - var screeningId = "1"; - - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(true) - .Returns(false); - _moqDataReader.Setup(reader => reader.GetInt32(0)).Returns(0); - _commandMock.Setup(x => x.ExecuteNonQuery()).Returns(1); - - SetUpReader(); - - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); - - // Act - var result = sut.GetParticipant(nhsId, screeningId); - - // Assert - Assert.AreEqual("123456", result.NhsNumber); - } - - [TestMethod] - public void UpdateParticipantDetails_Fails_When_Validation_Fails() - { - // Arrange - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(true) - .Returns(false); - - SetUpReader(); _webResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.BadRequest); - var sut = new ParticipantManagerData(_mockDBConnection.Object, _databaseHelperMock.Object, _loggerMock.Object); + // Act var result = sut.UpdateParticipantDetails(_participantCsvRecord); // Assert Assert.IsFalse(result); - _commandMock.Verify(command => command.ExecuteNonQuery(), Times.AtMost(2));//We still update the participant, but only set the Exception Flag. - } - - private void SetUpReader() - { - _moqDataReader.Setup(m => m["PARTICIPANT_ID"]).Returns("123456"); - _moqDataReader.Setup(m => m["SCREENING_ID"]).Returns(DBNull.Value); - _moqDataReader.Setup(m => m["NHS_NUMBER"]).Returns("123456"); - _moqDataReader.Setup(m => m["REASON_FOR_REMOVAL"]).Returns("Some Provider"); - _moqDataReader.Setup(m => m["REASON_FOR_REMOVAL_FROM_DT"]).Returns(DBNull.Value); - _moqDataReader.Setup(m => m["BUSINESS_RULE_VERSION"]).Returns(DBNull.Value); - _moqDataReader.Setup(m => m["EXCEPTION_FLAG"]).Returns(DBNull.Value); - _moqDataReader.Setup(m => m["OTHER_NAME"]).Returns(DBNull.Value); - _moqDataReader.Setup(m => m["RECORD_INSERT_DATETIME"]).Returns(DBNull.Value); - _moqDataReader.Setup(m => m["RECORD_UPDATE_DATETIME"]).Returns(DBNull.Value); - } - - private static Participant GetParticipant() - { - return new Participant() - { - ParticipantId = "1", - NhsNumber = "123456", - SupersededByNhsNumber = "789012", - PrimaryCareProvider = "ABC Clinic", - NamePrefix = "Mr.", - FirstName = "John", - OtherGivenNames = "Middle", - FamilyName = "Doe", - DateOfBirth = "1990-01-01", - Gender = Gender.Male, - AddressLine1 = "123 Main Street", - AddressLine2 = "Apt 101", - AddressLine3 = "Suburb", - AddressLine4 = "City", - AddressLine5 = "State", - Postcode = "12345", - ReasonForRemoval = "Moved", - ReasonForRemovalEffectiveFromDate = "2023-01-01", - DateOfDeath = "2024-04-23", - TelephoneNumber = "123-456-7890", - MobileNumber = "987-654-3210", - EmailAddress = "john.doe@example.com", - PreferredLanguage = "English", - IsInterpreterRequired = "0", - RecordType = Actions.Amended, - ScreeningId = "1" - - }; + _commandMock.Verify(command => command.ExecuteNonQuery(), Times.AtMost(2)); + //We still update the participant, but only set the Exception Flag. } } diff --git a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.csproj b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.csproj index f661a3f35..65aa8ee40 100644 --- a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.csproj +++ b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.csproj @@ -25,6 +25,7 @@ + From 15761fcf3394fb4c864f2e977b6cac04a06dd2fc Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:47:30 +0000 Subject: [PATCH 02/19] Update UpdateParticipantDetailsTests.cs --- .../UpdateParticipantDetailsTests.cs | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs index a3e8530f1..ddf78aad0 100644 --- a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs +++ b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs @@ -18,17 +18,18 @@ namespace NHS.CohortManager.Tests.UnitTests.ScreeningDataServicesTests; public class UpdateParticipantDetailsTests { private readonly ParticipantCsvRecord _participantCsvRecord; - private readonly Mock> _participantManagementClientMock = new(); + private Mock> _participantManagementClientMock = new(); private readonly Mock> _loggerMock = new(); private readonly Mock _callFunctionMock = new(); private readonly Mock _createResponseMock = new(); - private readonly Mock _exceptionHandlerMock = new(); + private readonly Mock _exceptionHandlerMock = new(); private readonly SetupRequest _setupRequest = new(); + private readonly Mock _webResponse = new(); public UpdateParticipantDetailsTests() { - // Environment.SetEnvironmentVariable("DtOsDatabaseConnectionString", "DtOsDatabaseConnectionString"); - // Environment.SetEnvironmentVariable("LookupValidationURL", "LookupValidationURL"); + Environment.SetEnvironmentVariable("LookupValidationURL", "LookupValidationURL"); + _participantManagementClientMock .Setup(c => c.Update(It.IsAny())) .ReturnsAsync(true); @@ -71,6 +72,15 @@ public UpdateParticipantDetailsTests() } }; + + _webResponse + .Setup(m => m.StatusCode) + .Returns(HttpStatusCode.OK); + + _callFunctionMock + .Setup(m => m.SendPost("LookupValidationURL", It.IsAny())) + .ReturnsAsync(_webResponse.Object); + } [TestMethod] @@ -91,7 +101,7 @@ public async Task Run_ValidRequest_ReturnOk() var response = await sut.Run(request.Object); // Assert - Assert.AreEqual(response.StatusCode, HttpStatusCode.OK); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); } [TestMethod] @@ -108,27 +118,27 @@ public async Task Run_GetOldParticipantFails_ReturnInternalServerError() var response = await sut.Run(request.Object); // Assert - Assert.AreEqual(response.StatusCode, HttpStatusCode.InternalServerError); + Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode); } - [TestMethod] - public void Run_LookupValidationFails_ReturnInternalServerError() - { - // Arrange - _moqDataReader.SetupSequence(reader => reader.Read()) - .Returns(true) - .Returns(false); + // [TestMethod] + // public void Run_LookupValidationFails_ReturnInternalServerError() + // { + // // Arrange + // _moqDataReader.SetupSequence(reader => reader.Read()) + // .Returns(true) + // .Returns(false); - _webResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.BadRequest); + // _webResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.BadRequest); - // Act - var result = sut.UpdateParticipantDetails(_participantCsvRecord); - // Assert - Assert.IsFalse(result); - _commandMock.Verify(command => command.ExecuteNonQuery(), Times.AtMost(2)); - //We still update the participant, but only set the Exception Flag. - } + // // Act + // var result = sut.UpdateParticipantDetails(_participantCsvRecord); + // // Assert + // Assert.IsFalse(result); + // _commandMock.Verify(command => command.ExecuteNonQuery(), Times.AtMost(2)); + // //We still update the participant, but only set the Exception Flag. + // } } From d5361b0a60a836475fdf302e3a01da002979e1c5 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Tue, 4 Feb 2025 10:42:58 +0000 Subject: [PATCH 03/19] test: updating tests --- .../src/Functions/Shared/Model/Participant.cs | 2 +- .../updateParticipantDetails.cs | 3 +- .../UpdateParticipantDetailsTests.cs | 106 ++++++++++++++---- 3 files changed, 87 insertions(+), 24 deletions(-) diff --git a/application/CohortManager/src/Functions/Shared/Model/Participant.cs b/application/CohortManager/src/Functions/Shared/Model/Participant.cs index f34a7604a..ba6988070 100644 --- a/application/CohortManager/src/Functions/Shared/Model/Participant.cs +++ b/application/CohortManager/src/Functions/Shared/Model/Participant.cs @@ -121,7 +121,7 @@ public ParticipantManagement ToParticipantManagement() ReasonForRemoval = ReasonForRemoval, ReasonForRemovalDate = DateTime.TryParse(ReasonForRemovalEffectiveFromDate, out var removalDate) ? removalDate : null, BusinessRuleVersion = BusinessRuleVersion, - ExceptionFlag = short.TryParse(ExceptionFlag, out var exceptionFlag) ? exceptionFlag : (short)0, + ExceptionFlag = short.Parse(ExceptionFlag ?? "0"), RecordInsertDateTime = DateTime.TryParse(RecordInsertDateTime, out var insertDate) ? insertDate : null, RecordUpdateDateTime = DateTime.TryParse(RecordUpdateDateTime, out var updateDate) ? updateDate : null, }; diff --git a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs index 06f8ce54d..1f5c1af29 100644 --- a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs +++ b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs @@ -60,7 +60,7 @@ public async Task Run([HttpTrigger(AuthorizationLevel.Anonymou if (response.CreatedException) { _logger.LogInformation("Validation Error: A Rule was violated but it was not Fatal for record with Nhs number: {NhsNumber}", participantCsvRecord.Participant.NhsNumber); - participantCsvRecord.Participant.ExceptionFlag = "Y"; + reqParticipant.ExceptionFlag = "1"; } var isAdded = await _participantManagementClient.Update(reqParticipant.ToParticipantManagement()); @@ -93,6 +93,7 @@ private async Task ValidateData(Participant existingPart } catch (Exception ex) { + System.Console.WriteLine(ex); _logger.LogInformation(ex, "Lookup validation failed.\nMessage: {Message}\nParticipant: {NewParticipant}", ex.Message, newParticipant); return null; } diff --git a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs index ddf78aad0..db52c14d2 100644 --- a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs +++ b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs @@ -12,6 +12,7 @@ namespace NHS.CohortManager.Tests.UnitTests.ScreeningDataServicesTests; using Common; using System.Linq.Expressions; using NHS.CohortManager.Tests.TestUtils; +using Microsoft.Azure.Functions.Worker; using System.Text.Json; [TestClass] @@ -24,7 +25,8 @@ public class UpdateParticipantDetailsTests private readonly Mock _createResponseMock = new(); private readonly Mock _exceptionHandlerMock = new(); private readonly SetupRequest _setupRequest = new(); - private readonly Mock _webResponse = new(); + private readonly Mock _LookupValidationWebResponse = new(); + private ValidationExceptionLog _lookupValidationResponseBody = new(); public UpdateParticipantDetailsTests() { @@ -73,24 +75,27 @@ public UpdateParticipantDetailsTests() } }; - _webResponse + _LookupValidationWebResponse .Setup(m => m.StatusCode) .Returns(HttpStatusCode.OK); _callFunctionMock .Setup(m => m.SendPost("LookupValidationURL", It.IsAny())) - .ReturnsAsync(_webResponse.Object); + .ReturnsAsync(_LookupValidationWebResponse.Object); + _lookupValidationResponseBody.CreatedException = false; + _lookupValidationResponseBody.IsFatal = false; + string lookupResponseJson = JsonSerializer.Serialize(_lookupValidationResponseBody); + + _callFunctionMock + .Setup(x => x.GetResponseText(It.IsAny())) + .ReturnsAsync(lookupResponseJson); } [TestMethod] public async Task Run_ValidRequest_ReturnOk() { // Arrange - _participantManagementClientMock - .Setup(c => c.GetSingleByFilter(It.IsAny>>())) - .ReturnsAsync((ParticipantManagement)null); - var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, _callFunctionMock.Object, _participantManagementClientMock.Object); @@ -108,6 +113,10 @@ public async Task Run_ValidRequest_ReturnOk() public async Task Run_GetOldParticipantFails_ReturnInternalServerError() { // Arrange + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .Throws(new Exception()); + var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, _callFunctionMock.Object, _participantManagementClientMock.Object); @@ -121,24 +130,77 @@ public async Task Run_GetOldParticipantFails_ReturnInternalServerError() Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode); } - // [TestMethod] - // public void Run_LookupValidationFails_ReturnInternalServerError() - // { - // // Arrange - // _moqDataReader.SetupSequence(reader => reader.Read()) - // .Returns(true) - // .Returns(false); + [TestMethod] + public async Task Run_LookupValidationFails_ReturnInternalServerError() + { + // Arrange + _callFunctionMock + .Setup(x => x.GetResponseText(It.IsAny())) + .Throws(new Exception()); + + var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, + _callFunctionMock.Object, _participantManagementClientMock.Object); + + string json = JsonSerializer.Serialize(_participantCsvRecord); + var request = _setupRequest.Setup(json); + + // Act + var response = await sut.Run(request.Object); + + // Assert + Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode); + } + + [TestMethod] + public async Task Run_FatalValidationRuleTriggered_ReturnCreatedAndDoNotUpdate() + { + // Arrange + _lookupValidationResponseBody.CreatedException = true; + _lookupValidationResponseBody.IsFatal = true; + string lookupResponseJson = JsonSerializer.Serialize(_lookupValidationResponseBody); + + _callFunctionMock + .Setup(x => x.GetResponseText(It.IsAny())) + .ReturnsAsync(lookupResponseJson); + + var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, + _callFunctionMock.Object, _participantManagementClientMock.Object); + + string json = JsonSerializer.Serialize(_participantCsvRecord); + var request = _setupRequest.Setup(json); + + // Act + var response = await sut.Run(request.Object); + + // Assert + Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); + _participantManagementClientMock + .Verify(x => x.Update(It.IsAny()), Times.Never()); + } + + [TestMethod] + public async Task Run_NonFatalValidationRuleTriggered_SetExceptionFlagAndUpdate() + { + // Arrange + _lookupValidationResponseBody.CreatedException = true; + _lookupValidationResponseBody.IsFatal = false; + string lookupResponseJson = JsonSerializer.Serialize(_lookupValidationResponseBody); + _callFunctionMock + .Setup(x => x.GetResponseText(It.IsAny())) + .ReturnsAsync(lookupResponseJson); - // _webResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.BadRequest); + var sut = new UpdateParticipantDetails(_loggerMock.Object, _createResponseMock.Object, _exceptionHandlerMock.Object, + _callFunctionMock.Object, _participantManagementClientMock.Object); + string json = JsonSerializer.Serialize(_participantCsvRecord); + var request = _setupRequest.Setup(json); + // Act + var response = await sut.Run(request.Object); - // // Act - // var result = sut.UpdateParticipantDetails(_participantCsvRecord); - // // Assert - // Assert.IsFalse(result); - // _commandMock.Verify(command => command.ExecuteNonQuery(), Times.AtMost(2)); - // //We still update the participant, but only set the Exception Flag. - // } + // Assert + _participantManagementClientMock + .Verify(x => x.Update(It.Is(p => p.ExceptionFlag == 1)), Times.Once()); + } } From 62d51cb60e1a53361a33bf5dd25631766f90d428 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:00:38 +0000 Subject: [PATCH 04/19] feat: tests --- .../RetrieveParticipantData.cs | 4 +- .../Data/Database/IParticipantManagerData.cs | 13 - .../Data/Database/ParticipantManagerData.cs | 274 ------------------ .../CreateCohortDistributionTests.cs | 247 ++++++++-------- .../RetrieveParticipantDataTests.cs | 130 ++++----- .../UpdateParticipantDetailsTests.cs | 3 - 6 files changed, 185 insertions(+), 486 deletions(-) delete mode 100644 application/CohortManager/src/Functions/Shared/Data/Database/IParticipantManagerData.cs delete mode 100644 application/CohortManager/src/Functions/Shared/Data/Database/ParticipantManagerData.cs diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index 3507fbf49..5bd24feef 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -50,7 +50,7 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano catch (Exception ex) { _logger.LogError(ex, ex.Message); - return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req); + return _createResponse.CreateHttpResponse(HttpStatusCode.BadRequest, req); } try @@ -70,7 +70,7 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano { _logger.LogError(ex, "Retrieve participant data failed.\nMessage: {Message}\nStack Trace: {StackTrace}", ex.Message, ex.StackTrace); await _exceptionHandler.CreateSystemExceptionLogFromNhsNumber(ex, requestBody.NhsNumber, "", "", JsonSerializer.Serialize(participant) ?? "N/A"); - return _createResponse.CreateHttpResponse(HttpStatusCode.BadRequest, req); + return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req); } } } diff --git a/application/CohortManager/src/Functions/Shared/Data/Database/IParticipantManagerData.cs b/application/CohortManager/src/Functions/Shared/Data/Database/IParticipantManagerData.cs deleted file mode 100644 index 5e5137953..000000000 --- a/application/CohortManager/src/Functions/Shared/Data/Database/IParticipantManagerData.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Data.Database; - -using Model; -using NHS.CohortManager.CohortDistribution; - -public interface IParticipantManagerData -{ - bool UpdateParticipantAsEligible(Participant participant); - [Obsolete("Replacing With data")] - bool UpdateParticipantDetails(ParticipantCsvRecord participantCsvRecord); - Participant GetParticipant(string nhsNumber, string screeningId); - Participant GetParticipantFromIDAndScreeningService(RetrieveParticipantRequestBody retrieveParticipantRequestBody); -} diff --git a/application/CohortManager/src/Functions/Shared/Data/Database/ParticipantManagerData.cs b/application/CohortManager/src/Functions/Shared/Data/Database/ParticipantManagerData.cs deleted file mode 100644 index 66aaf2e5a..000000000 --- a/application/CohortManager/src/Functions/Shared/Data/Database/ParticipantManagerData.cs +++ /dev/null @@ -1,274 +0,0 @@ -namespace Data.Database; - -using System.Data; -using System.Security.Cryptography; -using Microsoft.Extensions.Logging; -using Model; -using NHS.CohortManager.CohortDistribution; - -public class ParticipantManagerData : IParticipantManagerData -{ - private readonly IDbConnection _dbConnection; - private readonly IDatabaseHelper _databaseHelper; - private readonly string _connectionString; - private readonly ILogger _logger; - - public ParticipantManagerData(IDbConnection IdbConnection, IDatabaseHelper databaseHelper, ILogger logger) - { - _dbConnection = IdbConnection; - _databaseHelper = databaseHelper; - _logger = logger; - _connectionString = Environment.GetEnvironmentVariable("DtOsDatabaseConnectionString") ?? string.Empty; - } - - #region Update methods - public bool UpdateParticipantAsEligible(Participant participant) - { - try - { - var Participant = GetParticipant(participant.NhsNumber, participant.ScreeningId); - - var recordUpdateTime = DateTime.Now; - - var SQL = " UPDATE [dbo].[PARTICIPANT_MANAGEMENT] with (rowlock)" + - " SET RECORD_UPDATE_DATETIME = @recordEndDateOldRecords, " + - " ELIGIBILITY_FLAG = @eligibilityFlag " + - " WHERE PARTICIPANT_ID = @participantId "; - - var Parameters = new Dictionary - { - {"@participantId", Participant.ParticipantId }, - {"@recordEndDateOldRecords", recordUpdateTime }, - {"@eligibilityFlag", _databaseHelper.CheckIfNumberNull(participant.EligibilityFlag) ? DBNull.Value : participant.EligibilityFlag } - }; - - - return ExecuteCommand(SQL, Parameters); - } - catch (Exception ex) - { - _logger.LogError(ex, "{MessageType} UpdateParticipantAsEligible failed.\nMessage:{ExMessage}\nStack Trace: {ExStackTrace}", ex.GetType().Name, ex.Message, ex.StackTrace); - return false; - } - } - - public bool UpdateParticipantDetails(ParticipantCsvRecord participantCsvRecord) - { - try - { - var participantData = participantCsvRecord.Participant; - var dateToday = DateTime.Now; - - string insertParticipant = "UPDATE [dbo].[PARTICIPANT_MANAGEMENT] SET " + - " REASON_FOR_REMOVAL = @reasonForRemoval, " + - " RECORD_TYPE = @recordType, " + - " REASON_FOR_REMOVAL_FROM_DT = @reasonForRemovalDate, " + - " BUSINESS_RULE_VERSION = @businessRuleVersion, " + - " EXCEPTION_FLAG = @exceptionFlag, " + - " RECORD_UPDATE_DATETIME = @recordUpdateDateTime " + - " WHERE SCREENING_ID = @screeningId " + - " AND NHS_NUMBER = @NHSNumber"; - - var commonParameters = new Dictionary - { - { "@screeningId", _databaseHelper.CheckIfNumberNull(participantData.ScreeningId) ? DBNull.Value : participantData.ScreeningId}, - { "@recordType", _databaseHelper.ConvertNullToDbNull(participantData.RecordType)}, - { "@NHSNumber", _databaseHelper.CheckIfNumberNull(participantData.NhsNumber) ? DBNull.Value : participantData.NhsNumber}, - { "@reasonForRemoval", _databaseHelper.ConvertNullToDbNull(participantData.ReasonForRemoval)}, - { "@reasonForRemovalDate", _databaseHelper.ParseDates(participantData.ReasonForRemovalEffectiveFromDate)}, - { "@businessRuleVersion", _databaseHelper.ConvertNullToDbNull(participantData.BusinessRuleVersion)}, - { "@exceptionFlag", _databaseHelper.ParseExceptionFlag(_databaseHelper.ConvertNullToDbNull(participantData.ExceptionFlag)) }, - { "@recordUpdateDateTime", dateToday }, - }; - - var updatedRecord = ExecuteCommand(insertParticipant, commonParameters); - return updatedRecord; - } - catch (Exception ex) - { - _logger.LogError(ex, "{MessageType} UpdateParticipantDetails failed.\nMessage:{ExMessage}\nStack Trace: {ExStackTrace}", ex.GetType().Name, ex.Message, ex.StackTrace); - return false; - } - } - #endregion - - #region get methods - public Participant GetParticipant(string nhsNumber, string screeningId) - { - var SQL = "SELECT " + - "[PARTICIPANT_MANAGEMENT].[PARTICIPANT_ID], " + - "[PARTICIPANT_MANAGEMENT].[SCREENING_ID], " + - "[PARTICIPANT_MANAGEMENT].[NHS_NUMBER], " + - "[PARTICIPANT_MANAGEMENT].[REASON_FOR_REMOVAL], " + - "[PARTICIPANT_MANAGEMENT].[REASON_FOR_REMOVAL_FROM_DT], " + - "[PARTICIPANT_MANAGEMENT].[BUSINESS_RULE_VERSION], " + - "[PARTICIPANT_MANAGEMENT].[EXCEPTION_FLAG], " + - "[PARTICIPANT_MANAGEMENT].[RECORD_INSERT_DATETIME], " + - "[PARTICIPANT_MANAGEMENT].[RECORD_UPDATE_DATETIME] " + - "FROM [dbo].[PARTICIPANT_MANAGEMENT] " + - "WHERE [PARTICIPANT_MANAGEMENT].[NHS_NUMBER] = @NhsNumber " + - "AND [PARTICIPANT_MANAGEMENT].[SCREENING_ID] = @ScreeningId"; - - var parameters = new Dictionary - { - {"@NhsNumber", nhsNumber }, - {"@ScreeningId", screeningId} - }; - - var command = CreateCommand(parameters); - command.CommandText = SQL; - - return GetParticipantWithScreeningName(command, false); - } - - public Participant GetParticipantFromIDAndScreeningService(RetrieveParticipantRequestBody retrieveParticipantRequestBody) - { - var SQL = " SELECT TOP (1) * " + - " FROM [PARTICIPANT_MANAGEMENT] AS P " + - " JOIN SCREENING_LKP AS SLPK ON P.SCREENING_ID = SLPK.SCREENING_ID " + - " WHERE P.[NHS_NUMBER] = @NhsNumber AND P.[SCREENING_ID] = @ScreeningId AND SLPK.SCREENING_ID = @ScreeningId " + - " ORDER BY PARTICIPANT_ID DESC "; - - var parameters = new Dictionary - { - {"@NhsNumber", retrieveParticipantRequestBody.NhsNumber }, - {"@ScreeningId", retrieveParticipantRequestBody.ScreeningService } - }; - - var command = CreateCommand(parameters); - command.CommandText = SQL; - - return GetParticipantWithScreeningName(command, true); - } - #endregion - - #region private methods - - private Participant GetParticipantWithScreeningName(IDbCommand command, bool withScreeningName) - { - return ExecuteQuery(command, reader => - { - var participant = new Participant(); - while (reader.Read()) - { - participant.ParticipantId = reader["PARTICIPANT_ID"] == DBNull.Value ? "-1" : reader["PARTICIPANT_ID"].ToString(); - participant.ScreeningId = reader["SCREENING_ID"] == DBNull.Value ? null : reader["SCREENING_ID"].ToString(); - participant.NhsNumber = reader["NHS_NUMBER"] == DBNull.Value ? null : reader["NHS_NUMBER"].ToString(); - participant.ReasonForRemoval = reader["REASON_FOR_REMOVAL"] == DBNull.Value ? null : reader["REASON_FOR_REMOVAL"].ToString(); - participant.ReasonForRemovalEffectiveFromDate = reader["REASON_FOR_REMOVAL_FROM_DT"] == DBNull.Value ? null : reader["REASON_FOR_REMOVAL_FROM_DT"].ToString(); - participant.BusinessRuleVersion = reader["BUSINESS_RULE_VERSION"] == DBNull.Value ? null : reader["BUSINESS_RULE_VERSION"].ToString(); - participant.ExceptionFlag = reader["EXCEPTION_FLAG"] == DBNull.Value ? null : reader["EXCEPTION_FLAG"].ToString(); - participant.RecordInsertDateTime = reader["RECORD_INSERT_DATETIME"] == DBNull.Value ? null : reader["RECORD_INSERT_DATETIME"].ToString(); - participant.RecordUpdateDateTime = reader["RECORD_UPDATE_DATETIME"] == DBNull.Value ? null : reader["RECORD_UPDATE_DATETIME"].ToString(); - if (withScreeningName) - { - participant.ScreeningAcronym = reader["SCREENING_ACRONYM"] == DBNull.Value ? null : reader["SCREENING_ACRONYM"].ToString(); - participant.ScreeningName = reader["SCREENING_NAME"] == DBNull.Value ? null : reader["SCREENING_NAME"].ToString(); - } - else - { - participant.ScreeningAcronym = null; - participant.ScreeningName = null; - } - } - return participant; - }); - } - - private T ExecuteQuery(IDbCommand command, Func mapFunction) - { - try - { - var result = default(T); - using (_dbConnection) - { - if (_dbConnection.ConnectionString != _connectionString) - { - _dbConnection.ConnectionString = _connectionString; - } - _dbConnection.Open(); - using (command) - { - using (IDataReader reader = command.ExecuteReader()) - { - result = mapFunction(reader); - } - } - - return result; - } - } - finally - { - if (_dbConnection != null) - { - _dbConnection.Close(); - } - } - - - } - - private bool ExecuteCommand(string sqlCommandText, Dictionary commonParams) - { - var command = CreateCommand(commonParams); - command.Transaction = BeginTransaction(); - command.CommandText = sqlCommandText; - - try - { - var result = command.ExecuteNonQuery(); - _logger.LogInformation(result.ToString()); - - if (result == 0) - { - command.Transaction.Rollback(); - return false; - } - - command.Transaction.Commit(); - return true; - } - catch (Exception ex) - { - command.Transaction.Rollback(); - _logger.LogError(ex, "{MessageType} ExecuteCommand failed.\nMessage:{ExMessage}\nStack Trace: {ExStackTrace}", ex.GetType().Name, ex.Message, ex.StackTrace); - return false; - } - finally - { - _dbConnection.Close(); - } - } - - private IDbTransaction BeginTransaction() - { - _dbConnection.ConnectionString = _connectionString; - _dbConnection.Open(); - return _dbConnection.BeginTransaction(); - } - - private IDbCommand CreateCommand(Dictionary parameters) - { - var dbCommand = _dbConnection.CreateCommand(); - return AddParameters(parameters, dbCommand); - } - - private static IDbCommand AddParameters(Dictionary parameters, IDbCommand dbCommand) - { - if (parameters == null) return dbCommand; - - foreach (var param in parameters) - { - var parameter = dbCommand.CreateParameter(); - - parameter.ParameterName = param.Key; - parameter.Value = param.Value; - dbCommand.Parameters.Add(parameter); - } - - return dbCommand; - } - - #endregion -} diff --git a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs index b66548cad..187035c21 100644 --- a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs +++ b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs @@ -14,6 +14,8 @@ namespace NHS.CohortManager.Tests.UnitTests.CreateCohortDistributionTests; using Model; using Model.Enums; using Data.Database; +using DataServices.Client; +using System.Linq.Expressions; [TestClass] public class CreateCohortDistributionTests @@ -21,14 +23,16 @@ public class CreateCohortDistributionTests private readonly Mock _callFunction = new(); private readonly Mock> _logger = new(); private readonly Mock _cohortDistributionHelper = new(); - private readonly CreateCohortDistribution _function; + private readonly CreateCohortDistribution _sut; private readonly Mock _context = new(); - private readonly Mock _request; + private Mock _request; private readonly Mock _exceptionHandler = new(); private readonly CreateCohortDistributionRequestBody _requestBody; - private readonly Mock _participantManagerData = new(); private readonly Mock _azureQueueStorageHelper = new(); private readonly Mock _sendToCohortDistributionResponse = new(); + private readonly SetupRequest _setupRequest = new(); + private Mock> _participantManagementClientMock = new(); + public CreateCohortDistributionTests() { @@ -39,58 +43,31 @@ public CreateCohortDistributionTests() Environment.SetEnvironmentVariable("IsExtractedToBSSelect", "IsExtractedToBSSelect"); Environment.SetEnvironmentVariable("IgnoreParticipantExceptions", "IgnoreParticipantExceptions"); - _request = new Mock(_context.Object); - _requestBody = new CreateCohortDistributionRequestBody() { NhsNumber = "1234567890", ScreeningService = "BSS", }; - _function = new CreateCohortDistribution(_logger.Object, _callFunction.Object, _cohortDistributionHelper.Object, _exceptionHandler.Object, _participantManagerData.Object, _azureQueueStorageHelper.Object); - - _request.Setup(r => r.CreateResponse()).Returns(() => - { - var response = new Mock(_context.Object); - response.SetupProperty(r => r.Headers, new HttpHeadersCollection()); - response.SetupProperty(r => r.StatusCode); - response.SetupProperty(r => r.Body, new MemoryStream()); - return response.Object; - }); - } + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - [TestMethod] - [DataRow(null)] - [DataRow("")] - [DataRow(" ")] - public async Task RunAsync_BadRequestBody_ReturnsBadRequest(string screeningService) - { - // Act - _requestBody.ScreeningService = screeningService; - await _function.RunAsync(_requestBody); + _sut = new CreateCohortDistribution(_logger.Object, _callFunction.Object, _cohortDistributionHelper.Object, _exceptionHandler.Object, + _participantManagementClientMock.Object, _azureQueueStorageHelper.Object); - // Assert - _logger.Verify(x => x.Log(It.Is(l => l == LogLevel.Error), - It.IsAny(), - It.Is((v, t) => v.ToString().Contains("One or more of the required parameters is missing")), - It.IsAny(), - It.IsAny>()), - Times.Once); } [TestMethod] [DataRow(null, "BSS")] [DataRow("1234567890", null)] - public async Task RunAsync_MissingFieldsOnRequestBody_ReturnsBadRequest(string nhsNumber, string screeningService) + public async Task RunAsync_MissingFieldsOnRequestBody_ReturnBadRequest(string nhsNumber, string screeningService) { // Arrange _requestBody.NhsNumber = nhsNumber; _requestBody.ScreeningService = screeningService; - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); // Act - _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _logger.Verify(x => x.Log(It.Is(l => l == LogLevel.Error), @@ -102,19 +79,20 @@ public async Task RunAsync_MissingFieldsOnRequestBody_ReturnsBadRequest(string n } [TestMethod] - public async Task RunAsync_RetrieveParticipantDataRequestFails_ReturnsBadRequest() + public async Task RunAsync_RetrieveParticipantDataRequestFails_ReturnBadRequest() { // Arrange Exception caughtException = null; - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Throws(new Exception("some error")); + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .Throws(new Exception("some error")); // Act try { - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); } catch (Exception ex) { @@ -138,32 +116,35 @@ public async Task RunAsync_AllocateServiceProviderToParticipantRequestFails_Retu { // Arrange Exception caughtException = null; - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); + + CohortDistributionParticipant cohortParticipant = new() { ScreeningServiceId = "screeningservice", NhsNumber = "11111111", RecordType = "NEW", + }; - })); - _participantManagerData.Setup(x => x.GetParticipant(It.IsAny(), It.IsAny())).Returns(new Participant() - { - ExceptionFlag = "0", - }); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .Returns(Task.FromResult(new CohortDistributionParticipant() - { - ScreeningServiceId = "screeningservice", - Postcode = "POSTCODE", - })); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Throws(new Exception("some error")); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement {ExceptionFlag = 0}); + + // _cohortDistributionHelper + // .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + // .ReturnsAsync(cohortParticipant); + + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant() {ScreeningServiceId = "screeningservice", Postcode = "POSTCODE"}); + + _cohortDistributionHelper + .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Throws(new Exception("some error")); // Assert try { - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); } catch (Exception ex) { @@ -186,22 +167,30 @@ public async Task RunAsync_AllocateServiceProviderToParticipantRequestFails_Retu public async Task RunAsync_TransformDataServiceRequestFails_ReturnsBadRequest() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); - - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" })); - _cohortDistributionHelper.Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _participantManagerData.Setup(x => x.GetParticipant(It.IsAny(), It.IsAny())).Returns(new Participant() - { - ExceptionFlag = "0", - }); - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(null)); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); + + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" })); + _cohortDistributionHelper + .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(false); + // _cohortDistributionHelper + // .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + // .Returns(Task.FromResult("")); + _cohortDistributionHelper + .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(""); + _cohortDistributionHelper + .Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync((CohortDistributionParticipant)null); + + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement {ExceptionFlag = 0}); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); _logger.Verify(x => x.Log(It.Is(l => l == LogLevel.Error), It.IsAny(), @@ -216,27 +205,35 @@ public async Task RunAsync_AddCohortDistributionRequestFails_ReturnsBadRequest() { // Arrange Exception caughtException = null; - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); - - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" })); - _cohortDistributionHelper.Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _participantManagerData.Setup(x => x.GetParticipant(It.IsAny(), It.IsAny())).Returns(new Participant() - { - ExceptionFlag = "0", - }); - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new CohortDistributionParticipant())); - - _callFunction.Setup(call => call.SendPost(It.Is(s => s.Contains("AddCohortDistributionURL")), It.IsAny())) + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); + + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" }); + _cohortDistributionHelper + .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(false); + _cohortDistributionHelper + .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(""); + _cohortDistributionHelper + .Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant()); + // _cohortDistributionHelper + // .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + // .ReturnsAsync(""); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement { ExceptionFlag = 0 }); + + _callFunction + .Setup(call => call.SendPost(It.Is(s => s.Contains("AddCohortDistributionURL")), It.IsAny())) .Throws(new Exception("an error happened")); try { //Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); } catch (Exception ex) { @@ -259,31 +256,39 @@ public async Task RunAsync_AddCohortDistributionRequestFails_ReturnsBadRequest() public async Task RunAsync_AllSuccessfulRequests_AddsToCOhort() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); - - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" })); - _cohortDistributionHelper.Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _participantManagerData.Setup(x => x.GetParticipant(It.IsAny(), It.IsAny())).Returns(new Participant() - { - ExceptionFlag = "0", - }); - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new CohortDistributionParticipant())); - - - _sendToCohortDistributionResponse.Setup(x => x.StatusCode).Returns(HttpStatusCode.OK); - _callFunction.Setup(call => call.SendPost(It.Is(s => s.Contains("AddCohortDistributionURL")), It.IsAny())) - .Returns(Task.FromResult(_sendToCohortDistributionResponse.Object)); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); + + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" }); + _cohortDistributionHelper + .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(false); + _cohortDistributionHelper + .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(""); + _cohortDistributionHelper + .Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant()); + + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement { ExceptionFlag = 0 }); + + _sendToCohortDistributionResponse + .Setup(x => x.StatusCode) + .Returns(HttpStatusCode.OK); + _callFunction + .Setup(call => call.SendPost(It.Is(s => s.Contains("AddCohortDistributionURL")), It.IsAny())) + .ReturnsAsync(_sendToCohortDistributionResponse.Object); + ParticipantException(false); var response = MockHelpers.CreateMockHttpResponseData(HttpStatusCode.OK); _callFunction.Setup(call => call.SendPost(It.IsAny(), It.IsAny())).Returns(Task.FromResult(response)); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _logger.Verify(x => x.Log(It.Is(l => l == LogLevel.Information), @@ -298,8 +303,7 @@ public async Task RunAsync_AllSuccessfulRequests_AddsToCOhort() public async Task RunAsync_ParticipantExceptionExpected_AddToCohortNotCalled() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); @@ -309,7 +313,7 @@ public async Task RunAsync_ParticipantExceptionExpected_AddToCohortNotCalled() ParticipantException(true); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _callFunction.Verify(call => call.SendPost(It.Is(s => s == "AddCohortDistributionURL"), It.IsAny()), Times.Never()); @@ -319,8 +323,7 @@ public async Task RunAsync_ParticipantExceptionExpected_AddToCohortNotCalled() public async Task RunAsync_ParticipantIsNull_CreatesSystemExceptionLog() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); @@ -328,7 +331,7 @@ public async Task RunAsync_ParticipantIsNull_CreatesSystemExceptionLog() ParticipantException(false); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _exceptionHandler.Verify(x => x.CreateSystemExceptionLog( @@ -344,8 +347,7 @@ public async Task RunAsync_ParticipantIsNull_CreatesSystemExceptionLog() public async Task RunAsync_ParticipantMissingPostcodeAndServiceProvider_CreatesSystemExceptionLog() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() @@ -357,7 +359,7 @@ public async Task RunAsync_ParticipantMissingPostcodeAndServiceProvider_CreatesS ParticipantException(false); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _exceptionHandler.Verify(x => x.CreateSystemExceptionLog( @@ -373,8 +375,7 @@ public async Task RunAsync_ParticipantMissingPostcodeAndServiceProvider_CreatesS public async Task RunAsync_ParticipantHasException_CreatesSystemExceptionLog() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() @@ -389,7 +390,7 @@ public async Task RunAsync_ParticipantHasException_CreatesSystemExceptionLog() ParticipantException(true); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _exceptionHandler.Verify(x => x.CreateSystemExceptionLog( @@ -418,7 +419,7 @@ public async Task RunAsync_WhenAddCohortDistributionFails_CreatesRecordValidatio ParticipantException(false); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _callFunction.Verify(x => x.SendPost(It.IsAny(), It.IsAny()), Times.Once); @@ -439,7 +440,7 @@ public async Task RunAsync_WhenExceptionOccurs_CreatesSystemExceptionLogFromNhsN .ThrowsAsync(new Exception("Test exception")); // Act & Assert - await Assert.ThrowsExceptionAsync(() => _function.RunAsync(_requestBody)); + await Assert.ThrowsExceptionAsync(() => _sut.RunAsync(_requestBody)); _exceptionHandler.Verify(x => x.CreateSystemExceptionLogFromNhsNumber( It.IsAny(), @@ -477,7 +478,7 @@ public async Task RunAsync_ValidationFailed_CreatesValidationExceptionLog() ParticipantException(false); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _exceptionHandler.Verify(x => x.CreateRecordValidationExceptionLog( @@ -506,7 +507,7 @@ public async Task RunAsync_ParticipantHasExceptionAndEnvironmentVariableFalse_Cr ParticipantException(true); // Act - await _function.RunAsync(_requestBody); + await _sut.RunAsync(_requestBody); // Assert _logger.Verify(x => x.Log( diff --git a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs index 9237b0aa0..10ba5e04d 100644 --- a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs +++ b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs @@ -13,41 +13,36 @@ namespace NHS.CohortManager.Tests.UnitTests.RetrieveParticipantDataTests; using Model; using Data.Database; using NHS.CohortManager.Tests.TestUtils; +using DataServices.Client; +using System.Linq.Expressions; [TestClass] public class RetrieveParticipantDataTests { private readonly Mock _createResponse = new(); private readonly Mock> _logger = new(); - private readonly RetrieveParticipantData _function; + private readonly RetrieveParticipantData _sut; private readonly Mock _context = new(); - private readonly Mock _request; + private Mock _request; + private readonly SetupRequest _setupRequest = new(); private readonly RetrieveParticipantRequestBody _requestBody; - private readonly Mock _updateParticipantData = new(); private readonly Mock _createDemographicData = new(); private readonly CreateParticipant _createParticipant = new(); private readonly Mock _exceptionHandler = new(); + private Mock> _participantManagementClientMock = new(); public RetrieveParticipantDataTests() { - _request = new Mock(_context.Object); - _requestBody = new RetrieveParticipantRequestBody() { NhsNumber = "1234567890", ScreeningService = "BSS" }; + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - _function = new RetrieveParticipantData(_createResponse.Object, _logger.Object, _updateParticipantData.Object, _createDemographicData.Object, _createParticipant, _exceptionHandler.Object); - - _request.Setup(r => r.CreateResponse()).Returns(() => - { - var response = new Mock(_context.Object); - response.SetupProperty(r => r.Headers, new HttpHeadersCollection()); - response.SetupProperty(r => r.StatusCode); - response.SetupProperty(r => r.Body, new MemoryStream()); - return response.Object; - }); + _sut = new RetrieveParticipantData(_createResponse.Object, _logger.Object, + _createDemographicData.Object, _createParticipant, + _exceptionHandler.Object, _participantManagementClientMock.Object); _createResponse.Setup(x => x.CreateHttpResponse(It.IsAny(), It.IsAny(), It.IsAny())) .Returns((HttpStatusCode statusCode, HttpRequestData req, string ResponseBody) => @@ -60,73 +55,75 @@ public RetrieveParticipantDataTests() } [TestMethod] - public async Task Run_Should_Return_BadRequest_When_Request_Body_Empty() - { - // Act - var result = await _function.RunAsync(_request.Object); - - // Assert - Assert.AreEqual(HttpStatusCode.InternalServerError, result.StatusCode); - } - - [TestMethod] - public async Task Run_Should_Return_BadRequest_When_Request_Body_Invalid() + public async Task Run_RequestBodyInvalid_ReturnBadRequest() { // Arrange - SetUpRequestBody("Invalid request body"); + _request = _setupRequest.Setup(JsonSerializer.Serialize("Invalid")); // Act - var result = await _function.RunAsync(_request.Object); + var result = await _sut.RunAsync(_request.Object); // Assert - Assert.AreEqual(HttpStatusCode.InternalServerError, result.StatusCode); + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); } [TestMethod] - public async Task Run_Should_Return_BadRequest_When_GetParticipant_Fails() + public async Task Run_GetParticipantFails_ReturnInternalServerError() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - _updateParticipantData.Setup(x => x.GetParticipantFromIDAndScreeningService(It.IsAny())).Throws(new Exception("there has been an error")).Verifiable(); - _createDemographicData.Setup(x => x.GetDemographicData(It.IsAny())).Returns(new Demographic()).Verifiable(); + _participantManagementClientMock + .Setup(x => x.GetSingleByFilter(It.IsAny>>())) + .Throws(new Exception("there has been an error")); + // .ReturnsAsync(new ParticipantManagement { NHSNumber = 1, ScreeningId = 1 }); + _createDemographicData + .Setup(x => x.GetDemographicData(It.IsAny())) + .Returns(new Demographic()) + .Verifiable(); // Act - var result = await _function.RunAsync(_request.Object); + var result = await _sut.RunAsync(_request.Object); // Assert - _updateParticipantData.Verify(x => x.GetParticipantFromIDAndScreeningService(It.IsAny()), Times.Once); - _createDemographicData.Verify(x => x.GetDemographicData(It.IsAny()), Times.Never); + _participantManagementClientMock + .Verify(x => x.GetSingleByFilter(It.IsAny>>()), Times.Once); + _createDemographicData + .Verify(x => x.GetDemographicData(It.IsAny()), Times.Never); - Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + Assert.AreEqual(HttpStatusCode.InternalServerError, result.StatusCode); } [TestMethod] - public async Task Run_Should_Return_BadRequest_When_GetDemographicData_Fails() + public async Task Run_GetDemographicDataFails_ReturnInternalServerError() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - _updateParticipantData.Setup(x => x.GetParticipantFromIDAndScreeningService(It.IsAny())).Returns(new Participant()).Verifiable(); - _createDemographicData.Setup(x => x.GetDemographicData(It.IsAny())).Throws(new Exception("there has been an error")).Verifiable(); + _participantManagementClientMock + .Setup(x => x.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement()); + _createDemographicData + .Setup(x => x.GetDemographicData(It.IsAny())) + .Throws(new Exception("there has been an error")) + .Verifiable(); // Act - var result = await _function.RunAsync(_request.Object); + var result = await _sut.RunAsync(_request.Object); // Assert - _updateParticipantData.Verify(x => x.GetParticipantFromIDAndScreeningService(It.IsAny()), Times.Once); - _createDemographicData.Verify(x => x.GetDemographicData(It.IsAny()), Times.Once); - Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + _participantManagementClientMock + .Verify(x => x.GetSingleByFilter(It.IsAny>>()), Times.Once); + _createDemographicData + .Verify(x => x.GetDemographicData(It.IsAny()), Times.Once); + Assert.AreEqual(HttpStatusCode.InternalServerError, result.StatusCode); } [TestMethod] - public async Task Run_Should_Return_OK_When_Request_Body_Valid() + public async Task Run_ValidRequest_ReturnOk() { // Arrange - var json = JsonSerializer.Serialize(_requestBody); - SetUpRequestBody(json); + _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); var participant = new Participant { @@ -144,37 +141,28 @@ public async Task Run_Should_Return_OK_When_Request_Body_Valid() FirstName = demographic.FirstName }; - _updateParticipantData.Setup(x => x.GetParticipantFromIDAndScreeningService(It.IsAny())).Returns(participant).Verifiable(); - _createDemographicData.Setup(x => x.GetDemographicData(It.IsAny())).Returns(demographic).Verifiable(); + _participantManagementClientMock + .Setup(x => x.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement {NHSNumber = 1234567890}); + _createDemographicData + .Setup(x => x.GetDemographicData(It.IsAny())) + .Returns(demographic) + .Verifiable(); // Act - var result = await _function.RunAsync(_request.Object); + var result = await _sut.RunAsync(_request.Object); string responseBody = await AssertionHelper.ReadResponseBodyAsync(result); var response = JsonSerializer.Deserialize(responseBody); // Assert - _updateParticipantData.Verify(x => x.GetParticipantFromIDAndScreeningService(It.IsAny()), Times.Once); - _createDemographicData.Verify(x => x.GetDemographicData(It.IsAny()), Times.Once); + _participantManagementClientMock + .Verify(x => x.GetSingleByFilter(It.IsAny>>()), Times.Once); + _createDemographicData + .Verify(x => x.GetDemographicData(It.IsAny()), Times.Once); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); Assert.IsNotNull(response); Assert.AreEqual(expectedResponse.NhsNumber, response.NhsNumber); Assert.AreEqual(expectedResponse.FirstName, response.FirstName); } - - private void SetUpRequestBody(string json) - { - var byteArray = Encoding.ASCII.GetBytes(json); - var bodyStream = new MemoryStream(byteArray); - - _request.Setup(r => r.Body).Returns(bodyStream); - _request.Setup(r => r.CreateResponse()).Returns(() => - { - var response = new Mock(_context.Object); - response.SetupProperty(r => r.Headers, new HttpHeadersCollection()); - response.SetupProperty(r => r.StatusCode); - response.SetupProperty(r => r.Body, new MemoryStream()); - return response.Object; - }); - } } diff --git a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs index db52c14d2..d4e041314 100644 --- a/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs +++ b/tests/UnitTests/ScreeningDataServicesTests/UpdateParticipantDetailsTests/UpdateParticipantDetailsTests.cs @@ -1,8 +1,6 @@ namespace NHS.CohortManager.Tests.UnitTests.ScreeningDataServicesTests; -using System.Data; using System.Net; -using Data.Database; using Microsoft.Extensions.Logging; using Model; using Model.Enums; @@ -12,7 +10,6 @@ namespace NHS.CohortManager.Tests.UnitTests.ScreeningDataServicesTests; using Common; using System.Linq.Expressions; using NHS.CohortManager.Tests.TestUtils; -using Microsoft.Azure.Functions.Worker; using System.Text.Json; [TestClass] From 4f7f0e56e366512a764bd2401e7971241fd8c739 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:04:26 +0000 Subject: [PATCH 05/19] feat: tests --- .../CreateCohortDistribution.cs | 3 +- .../CreateCohortDistributionTests.cs | 236 +++--------------- 2 files changed, 42 insertions(+), 197 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs index d33198533..ae2e33c3e 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs @@ -111,7 +111,7 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur var cohortAddResponse = await AddCohortDistribution(transformedParticipant); if (cohortAddResponse.StatusCode != HttpStatusCode.OK) { - await HandleErrorResponseAsync("The transformed participant returned null from the transform participant function", transformedParticipant, basicParticipantCsvRecord.FileName); + await HandleErrorResponseAsync("Failed to add the participant to the Cohort Distribution table", transformedParticipant, basicParticipantCsvRecord.FileName); return; } _logger.LogInformation("Participant has been successfully put on the cohort distribution table"); @@ -155,6 +155,7 @@ private async Task AddCohortDistribution(CohortDistributionPart private async Task ParticipantHasException(string nhsNumber, string screeningId) { var participant = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber.ToString() == nhsNumber && p.ScreeningId.ToString() == screeningId); + System.Console.WriteLine("participant has exception:", participant.ExceptionFlag == 1); return participant.ExceptionFlag == 1; } } diff --git a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs index 187035c21..b57b845a2 100644 --- a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs +++ b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs @@ -24,13 +24,13 @@ public class CreateCohortDistributionTests private readonly Mock> _logger = new(); private readonly Mock _cohortDistributionHelper = new(); private readonly CreateCohortDistribution _sut; - private readonly Mock _context = new(); - private Mock _request; private readonly Mock _exceptionHandler = new(); private readonly CreateCohortDistributionRequestBody _requestBody; private readonly Mock _azureQueueStorageHelper = new(); private readonly Mock _sendToCohortDistributionResponse = new(); + private Mock _request; private readonly SetupRequest _setupRequest = new(); + private CohortDistributionParticipant _cohortDistributionParticipant; private Mock> _participantManagementClientMock = new(); @@ -51,6 +51,18 @@ public CreateCohortDistributionTests() _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); + _cohortDistributionParticipant = new() + { + ParticipantId = "1234", + NhsNumber = "5678", + ScreeningServiceId = "Screening123", + Postcode = "AB1 2CD" + }; + + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .ReturnsAsync(_cohortDistributionParticipant); + _sut = new CreateCohortDistribution(_logger.Object, _callFunction.Object, _cohortDistributionHelper.Object, _exceptionHandler.Object, _participantManagementClientMock.Object, _azureQueueStorageHelper.Object); @@ -128,10 +140,6 @@ public async Task RunAsync_AllocateServiceProviderToParticipantRequestFails_Retu _participantManagementClientMock .Setup(c => c.GetSingleByFilter(It.IsAny>>())) .ReturnsAsync(new ParticipantManagement {ExceptionFlag = 0}); - - // _cohortDistributionHelper - // .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - // .ReturnsAsync(cohortParticipant); _cohortDistributionHelper .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) @@ -167,17 +175,9 @@ public async Task RunAsync_AllocateServiceProviderToParticipantRequestFails_Retu public async Task RunAsync_TransformDataServiceRequestFails_ReturnsBadRequest() { // Arrange - _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - - _cohortDistributionHelper - .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .ReturnsAsync(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" })); _cohortDistributionHelper .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(false); - // _cohortDistributionHelper - // .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - // .Returns(Task.FromResult("")); _cohortDistributionHelper .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(""); @@ -207,9 +207,6 @@ public async Task RunAsync_AddCohortDistributionRequestFails_ReturnsBadRequest() Exception caughtException = null; _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - _cohortDistributionHelper - .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .ReturnsAsync(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" }); _cohortDistributionHelper .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(false); @@ -219,9 +216,6 @@ public async Task RunAsync_AddCohortDistributionRequestFails_ReturnsBadRequest() _cohortDistributionHelper .Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new CohortDistributionParticipant()); - // _cohortDistributionHelper - // .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(""); _participantManagementClientMock .Setup(c => c.GetSingleByFilter(It.IsAny>>())) .ReturnsAsync(new ParticipantManagement { ExceptionFlag = 0 }); @@ -256,11 +250,6 @@ public async Task RunAsync_AddCohortDistributionRequestFails_ReturnsBadRequest() public async Task RunAsync_AllSuccessfulRequests_AddsToCOhort() { // Arrange - _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - - _cohortDistributionHelper - .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .ReturnsAsync(new CohortDistributionParticipant() { ScreeningServiceId = "Screening123" }); _cohortDistributionHelper .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(false); @@ -281,8 +270,10 @@ public async Task RunAsync_AllSuccessfulRequests_AddsToCOhort() _callFunction .Setup(call => call.SendPost(It.Is(s => s.Contains("AddCohortDistributionURL")), It.IsAny())) .ReturnsAsync(_sendToCohortDistributionResponse.Object); - - ParticipantException(false); + + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement() { ExceptionFlag = 0 }); var response = MockHelpers.CreateMockHttpResponseData(HttpStatusCode.OK); _callFunction.Setup(call => call.SendPost(It.IsAny(), It.IsAny())).Returns(Task.FromResult(response)); @@ -299,95 +290,22 @@ public async Task RunAsync_AllSuccessfulRequests_AddsToCOhort() Times.Once); } - [TestMethod] - public async Task RunAsync_ParticipantExceptionExpected_AddToCohortNotCalled() - { - // Arrange - _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - _callFunction.Setup(call => call.SendPost(It.Is(s => s.Contains("AddCohortDistributionURL")), It.IsAny())).Verifiable(); - - ParticipantException(true); - - // Act - await _sut.RunAsync(_requestBody); - - // Assert - _callFunction.Verify(call => call.SendPost(It.Is(s => s == "AddCohortDistributionURL"), It.IsAny()), Times.Never()); - } - - [TestMethod] - public async Task RunAsync_ParticipantIsNull_CreatesSystemExceptionLog() - { - // Arrange - _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); - _cohortDistributionHelper.Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult("")); - - ParticipantException(false); - - // Act - await _sut.RunAsync(_requestBody); - - // Assert - _exceptionHandler.Verify(x => x.CreateSystemExceptionLog( - It.IsAny(), - It.IsAny(), - It.IsAny()), - Times.Once); - - _callFunction.Verify(call => call.SendPost(It.IsAny(), It.IsAny()), Times.Never()); - } - - [TestMethod] - public async Task RunAsync_ParticipantMissingPostcodeAndServiceProvider_CreatesSystemExceptionLog() - { - // Arrange - _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() - { - ScreeningServiceId = "screeningServiceId", - Postcode = "T357 P01", - })); - - ParticipantException(false); - - // Act - await _sut.RunAsync(_requestBody); - - // Assert - _exceptionHandler.Verify(x => x.CreateSystemExceptionLog( - It.IsAny(), - It.IsAny(), - It.IsAny()), - Times.Once); - - _callFunction.Verify(call => call.SendPost(It.IsAny(), It.IsAny()), Times.Never()); - } - [TestMethod] public async Task RunAsync_ParticipantHasException_CreatesSystemExceptionLog() { // Arrange _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() - { - ScreeningServiceId = "screeningServiceId", - Postcode = string.Empty, - })); + _cohortDistributionHelper + .Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new CohortDistributionParticipant()); var response = new Mock(); response.Setup(r => r.StatusCode).Returns(HttpStatusCode.BadRequest); _callFunction.Setup(x => x.SendPost(It.IsAny(), It.IsAny())).ReturnsAsync(response.Object); - ParticipantException(true); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement() {ExceptionFlag = 1}); // Act await _sut.RunAsync(_requestBody); @@ -400,82 +318,25 @@ public async Task RunAsync_ParticipantHasException_CreatesSystemExceptionLog() Times.Once); } - [TestMethod] - public async Task RunAsync_WhenAddCohortDistributionFails_CreatesRecordValidationExceptionLog() - { - // Arrange - var response = new Mock(); - response.Setup(r => r.StatusCode).Returns(HttpStatusCode.BadRequest); - - _cohortDistributionHelper.Setup(x => x.TransformParticipantAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant())); - _cohortDistributionHelper.Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())).Returns(Task.FromResult(new CohortDistributionParticipant() - { - ScreeningServiceId = "screeningServiceId", - Postcode = string.Empty, - })); - - _callFunction.Setup(x => x.SendPost(It.IsAny(), It.IsAny())).ReturnsAsync(response.Object); - - ParticipantException(false); - // Act - await _sut.RunAsync(_requestBody); - - // Assert - _callFunction.Verify(x => x.SendPost(It.IsAny(), It.IsAny()), Times.Once); - _exceptionHandler.Verify(x => x.CreateRecordValidationExceptionLog( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), - Times.Never); - } - - [TestMethod] - public async Task RunAsync_WhenExceptionOccurs_CreatesSystemExceptionLogFromNhsNumber() - { - // Arrange - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .ThrowsAsync(new Exception("Test exception")); - - // Act & Assert - await Assert.ThrowsExceptionAsync(() => _sut.RunAsync(_requestBody)); - - _exceptionHandler.Verify(x => x.CreateSystemExceptionLogFromNhsNumber( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny() - ), Times.Once); - - _callFunction.Verify(call => call.SendPost(It.IsAny(), It.IsAny()), Times.Never()); - } - [TestMethod] public async Task RunAsync_ValidationFailed_CreatesValidationExceptionLog() { // Arrange - var participant = new CohortDistributionParticipant - { - ParticipantId = "123", - NhsNumber = "NHS123", - ScreeningServiceId = "Screening123" - }; - - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .ReturnsAsync(participant); - - _cohortDistributionHelper.Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) + _cohortDistributionHelper + .Setup(x => x.ValidateCohortDistributionRecordAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(true); + _cohortDistributionHelper + .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(""); var response = new Mock(); - response.Setup(r => r.StatusCode).Returns(HttpStatusCode.BadRequest); + response.Setup(r => r.StatusCode).Returns(HttpStatusCode.OK); - _callFunction.Setup(x => x.SendPost(It.IsAny(), It.IsAny())).ReturnsAsync(response.Object); + _callFunction.Setup(x => x.SendPost("AddCohortDistributionURL", It.IsAny())).ReturnsAsync(response.Object); - ParticipantException(false); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement() { ExceptionFlag = 0 }); // Act await _sut.RunAsync(_requestBody); @@ -494,17 +355,13 @@ public async Task RunAsync_ValidationFailed_CreatesValidationExceptionLog() public async Task RunAsync_ParticipantHasExceptionAndEnvironmentVariableFalse_CreateSystemExceptionLog() { // Arrange - var participant = new CohortDistributionParticipant - { - ScreeningServiceId = "test", - ParticipantId = "123", - }; - - _cohortDistributionHelper.Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) - .ReturnsAsync(participant); - Environment.SetEnvironmentVariable("IgnoreParticipantExceptions", "false"); - ParticipantException(true); + _participantManagementClientMock + .Setup(c => c.GetSingleByFilter(It.IsAny>>())) + .ReturnsAsync(new ParticipantManagement() { ExceptionFlag = 1 }); + _cohortDistributionHelper + .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(""); // Act await _sut.RunAsync(_requestBody); @@ -517,17 +374,4 @@ public async Task RunAsync_ParticipantHasExceptionAndEnvironmentVariableFalse_Cr It.IsAny(), It.IsAny>())); } - private void SetUpRequestBody(string json) - { - var byteArray = Encoding.ASCII.GetBytes(json); - var bodyStream = new MemoryStream(byteArray); - - _request.Setup(r => r.Body).Returns(bodyStream); - } - - private void ParticipantException(bool hasException) - { - var participant = new Participant() { ExceptionFlag = hasException ? Exists.Yes.ToString() : Exists.No.ToString() }; - _participantManagerData.Setup(x => x.GetParticipant(It.IsAny(), It.IsAny())).Returns(participant); - } } From e2aa2d414629e158ee7b196e4111775d4471241d Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:16:52 +0000 Subject: [PATCH 06/19] feat: env variables --- .../CohortManager/compose.cohort-distribution.yaml | 2 +- .../tf-core/environments/development.tfvars | 12 ++++++++++++ .../tf-core/environments/integration.tfvars | 12 ++++++++++++ infrastructure/tf-core/environments/nft.tfvars | 12 ++++++++++++ infrastructure/tf-core/environments/preprod.tfvars | 12 ++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/application/CohortManager/compose.cohort-distribution.yaml b/application/CohortManager/compose.cohort-distribution.yaml index b8c8b1d46..78f0e7457 100644 --- a/application/CohortManager/compose.cohort-distribution.yaml +++ b/application/CohortManager/compose.cohort-distribution.yaml @@ -87,7 +87,7 @@ services: environment: - ASPNETCORE_URLS=http://*:7083 - ExceptionFunctionURL=http://localhost:7070/api/CreateException - - DtOsDatabaseConnectionString=Server=localhost,1433;Database=${DB_NAME};User Id=SA;Password=${PASSWORD};TrustServerCertificate=True + - ParticipantManagementUrl=http://localhost:7994/api/ParticipantManagementDataService validate-cohort-distribution-record: container_name: validate-cohort-distribution-record diff --git a/infrastructure/tf-core/environments/development.tfvars b/infrastructure/tf-core/environments/development.tfvars index 4817f9c78..96d9f8f78 100644 --- a/infrastructure/tf-core/environments/development.tfvars +++ b/infrastructure/tf-core/environments/development.tfvars @@ -405,6 +405,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } @@ -658,6 +662,10 @@ function_apps = { { env_var_name = "ValidateCohortDistributionRecordURL" function_app_key = "ValidateCohortDistributionRecord" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] env_vars_static = { @@ -677,6 +685,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } diff --git a/infrastructure/tf-core/environments/integration.tfvars b/infrastructure/tf-core/environments/integration.tfvars index 011c62d2e..022b3d896 100644 --- a/infrastructure/tf-core/environments/integration.tfvars +++ b/infrastructure/tf-core/environments/integration.tfvars @@ -400,6 +400,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } @@ -623,6 +627,10 @@ function_apps = { { env_var_name = "ValidateCohortDistributionRecordURL" function_app_key = "ValidateCohortDistributionRecord" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] env_vars_static = { @@ -640,6 +648,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } diff --git a/infrastructure/tf-core/environments/nft.tfvars b/infrastructure/tf-core/environments/nft.tfvars index b6bf0a73b..d7d7051d3 100644 --- a/infrastructure/tf-core/environments/nft.tfvars +++ b/infrastructure/tf-core/environments/nft.tfvars @@ -401,6 +401,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } @@ -654,6 +658,10 @@ function_apps = { { env_var_name = "ValidateCohortDistributionRecordURL" function_app_key = "ValidateCohortDistributionRecord" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] env_vars_static = { @@ -673,6 +681,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } diff --git a/infrastructure/tf-core/environments/preprod.tfvars b/infrastructure/tf-core/environments/preprod.tfvars index 05e0eb705..2f1fa9cfa 100644 --- a/infrastructure/tf-core/environments/preprod.tfvars +++ b/infrastructure/tf-core/environments/preprod.tfvars @@ -400,6 +400,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } @@ -623,6 +627,10 @@ function_apps = { { env_var_name = "ValidateCohortDistributionRecordURL" function_app_key = "ValidateCohortDistributionRecord" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] env_vars_static = { @@ -640,6 +648,10 @@ function_apps = { { env_var_name = "ExceptionFunctionURL" function_app_key = "CreateException" + }, + { + env_var_name = "ParticipantManagementUrl" + function_app_key = "ParticipantManagementDataService" } ] } From 7a22356ebd9880d965ef041057c2f5cfb6d57092 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:43:28 +0000 Subject: [PATCH 07/19] responding to comments --- .../CreateCohortDistribution.cs | 85 ++++++++----------- .../RetrieveParticipantData.cs | 4 +- .../Shared/Common/CreateParticipant.cs | 3 +- .../Model/CohortDistributionParticipant.cs | 1 + .../src/Functions/Shared/Model/Participant.cs | 16 ++-- .../CreateCohortDistributionTests.cs | 19 +++-- 6 files changed, 57 insertions(+), 71 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs index ae2e33c3e..fdf2bb864 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs @@ -40,9 +40,7 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur { if (string.IsNullOrWhiteSpace(basicParticipantCsvRecord.ScreeningService) || string.IsNullOrWhiteSpace(basicParticipantCsvRecord.NhsNumber)) { - string logMessage = $"One or more of the required parameters is missing."; - _logger.LogError(logMessage); - await HandleErrorResponseAsync(logMessage, null, basicParticipantCsvRecord.FileName); + await HandleErrorResponseAsync("One or more of the required parameters is missing.", null, basicParticipantCsvRecord.FileName); return; } @@ -50,17 +48,9 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur { // Retrieve participant data var participantData = await _CohortDistributionHelper.RetrieveParticipantDataAsync(basicParticipantCsvRecord); - if (participantData == null) + if (participantData == null || string.IsNullOrEmpty(participantData.ScreeningServiceId)) { - _logger.LogInformation("Participant data in cohort distribution was null"); - await HandleErrorResponseAsync("There was a problem getting participant data in cohort distribution", participantData, basicParticipantCsvRecord.FileName); - return; - } - - if (string.IsNullOrEmpty(participantData.ScreeningServiceId)) - { - _logger.LogInformation("Participant data was missing ScreeningServiceId"); - await HandleErrorResponseAsync("There was a problem getting participant data in cohort distribution", participantData, basicParticipantCsvRecord.FileName); + await HandleErrorResponseAsync("Participant data returned from database is missing required fields", participantData, basicParticipantCsvRecord.FileName); return; } @@ -77,49 +67,48 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur return; } } - - var ignoreParticipantExceptions = (bool)DatabaseHelper.ConvertBoolStringToBoolByType("IgnoreParticipantExceptions", DataTypes.Boolean); - - bool participantHasException = await ParticipantHasException(basicParticipantCsvRecord.NhsNumber, participantData.ScreeningServiceId); + + // Check if participant has exceptions + bool ignoreParticipantExceptions = Environment.GetEnvironmentVariable("IgnoreParticipantExceptions") == "true"; + bool participantHasException = participantData.ExceptionFlag == 1; if (participantHasException && !ignoreParticipantExceptions) // Will only run if IgnoreParticipantExceptions is false. { - var ParticipantExceptionErrorMessage = $"Unable to add to cohort distribution. As participant with ParticipantId: {participantData.ParticipantId}. Has an Exception against it"; - _logger.LogInformation(ParticipantExceptionErrorMessage, participantData.ParticipantId); - await HandleErrorResponseAsync(ParticipantExceptionErrorMessage, participantData, basicParticipantCsvRecord.FileName); + await HandleErrorResponseAsync($"Unable to add to cohort distribution. As participant with ParticipantId: {participantData.ParticipantId}. Has an Exception against it", + participantData, basicParticipantCsvRecord.FileName); return; } - else - { - _logger.LogInformation("Ignore Participant Exceptions is enabled, Record will be processed"); - } - // Validate cohort distribution record & transform data service + // Validation participantData.RecordType = basicParticipantCsvRecord.RecordType; var validationRecordCreated = await _CohortDistributionHelper.ValidateCohortDistributionRecordAsync(basicParticipantCsvRecord.NhsNumber, basicParticipantCsvRecord.FileName, participantData); - if (!validationRecordCreated || ignoreParticipantExceptions) + + if (validationRecordCreated && !ignoreParticipantExceptions) { - _logger.LogInformation("Validation has passed the record with NHS number: {NhsNumber} will be added to the database", participantData.NhsNumber); - var transformedParticipant = await _CohortDistributionHelper.TransformParticipantAsync(serviceProvider, participantData); - if (transformedParticipant == null) - { - _logger.LogError("The transform participant returned null in cohort distribution"); - await HandleErrorResponseAsync("the transformed participant returned null from the transform participant function", transformedParticipant, basicParticipantCsvRecord.FileName); - return; - } + var errorMessage = $"Validation error: A rule triggered a fatal error, preventing the cohort distribution record with participant Id {participantData.ParticipantId} from being added to the database"; + _logger.LogInformation(errorMessage); + await _exceptionHandler.CreateRecordValidationExceptionLog(participantData.NhsNumber, basicParticipantCsvRecord.FileName, errorMessage, serviceProvider, JsonSerializer.Serialize(participantData)); + return; + } + _logger.LogInformation("Validation has passed or exceptions are ignored, the record with participant id: {ParticipantId} will be added to the database", participantData.ParticipantId); - var cohortAddResponse = await AddCohortDistribution(transformedParticipant); - if (cohortAddResponse.StatusCode != HttpStatusCode.OK) - { - await HandleErrorResponseAsync("Failed to add the participant to the Cohort Distribution table", transformedParticipant, basicParticipantCsvRecord.FileName); - return; - } - _logger.LogInformation("Participant has been successfully put on the cohort distribution table"); + // Transformation + var transformedParticipant = await _CohortDistributionHelper.TransformParticipantAsync(serviceProvider, participantData); + if (transformedParticipant == null) + { + await HandleErrorResponseAsync("The transformed participant returned null from the transform participant function", transformedParticipant, basicParticipantCsvRecord.FileName); return; } - var errorMessage = $"Validation error: A rule triggered a fatal error, preventing the cohort distribution record with participant Id {participantData.ParticipantId} from being added to the database"; - _logger.LogInformation(errorMessage); - await _exceptionHandler.CreateRecordValidationExceptionLog(participantData.NhsNumber, basicParticipantCsvRecord.FileName, errorMessage, serviceProvider, JsonSerializer.Serialize(participantData)); + + // Add to cohort distribution table + var cohortAddResponse = await AddCohortDistribution(transformedParticipant); + if (cohortAddResponse.StatusCode != HttpStatusCode.OK) + { + await HandleErrorResponseAsync("Failed to add the participant to the Cohort Distribution table", transformedParticipant, basicParticipantCsvRecord.FileName); + return; + } + _logger.LogInformation("Participant has been successfully put on the cohort distribution table"); + return; } catch (Exception ex) { @@ -132,6 +121,7 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur private async Task HandleErrorResponseAsync(string errorMessage, CohortDistributionParticipant cohortDistributionParticipant, string fileName) { + _logger.LogError(errorMessage); var participant = new Participant(); if (cohortDistributionParticipant != null) { @@ -151,11 +141,4 @@ private async Task AddCohortDistribution(CohortDistributionPart _logger.LogInformation("Called {AddCohortDistribution} function", nameof(AddCohortDistribution)); return response; } - - private async Task ParticipantHasException(string nhsNumber, string screeningId) - { - var participant = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber.ToString() == nhsNumber && p.ScreeningId.ToString() == screeningId); - System.Console.WriteLine("participant has exception:", participant.ExceptionFlag == 1); - return participant.ExceptionFlag == 1; - } } diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index 5bd24feef..96766da27 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -55,8 +55,8 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano try { - var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber.ToString() == requestBody.NhsNumber && - p.ScreeningId.ToString() == requestBody.ScreeningService); + var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber == long.Parse(requestBody.NhsNumber) && + p.ScreeningId == long.Parse(requestBody.ScreeningService)); _logger.LogInformation("Got the participant. ScreeningId: {ScreeningServiceId}", participantData.ScreeningId); var demographicData = _createDemographicData.GetDemographicData(requestBody.NhsNumber); diff --git a/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs b/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs index 23ba0e194..11cfb06fe 100644 --- a/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs +++ b/application/CohortManager/src/Functions/Shared/Common/CreateParticipant.cs @@ -92,7 +92,8 @@ public CohortDistributionParticipant CreateCohortDistributionParticipantModel(Pa Extracted = null, RecordType = participant.RecordType, CurrentPosting = demographic.CurrentPosting, - CurrentPostingEffectiveFromDate = demographic.CurrentPostingEffectiveFromDate + CurrentPostingEffectiveFromDate = demographic.CurrentPostingEffectiveFromDate, + ExceptionFlag = participant.ExceptionFlag }; } } diff --git a/application/CohortManager/src/Functions/Shared/Model/CohortDistributionParticipant.cs b/application/CohortManager/src/Functions/Shared/Model/CohortDistributionParticipant.cs index 101910d7b..1d984e770 100644 --- a/application/CohortManager/src/Functions/Shared/Model/CohortDistributionParticipant.cs +++ b/application/CohortManager/src/Functions/Shared/Model/CohortDistributionParticipant.cs @@ -41,6 +41,7 @@ public class CohortDistributionParticipant public string? ScreeningServiceId { get; set; } public string? ScreeningName { get; set; } public string? EligibilityFlag { get; set; } + public short? ExceptionFlag { get; set; } public string? CurrentPosting { get; set; } public string? CurrentPostingEffectiveFromDate { get; set; } public string? ParticipantId { get; set; } diff --git a/application/CohortManager/src/Functions/Shared/Model/Participant.cs b/application/CohortManager/src/Functions/Shared/Model/Participant.cs index ba6988070..d9e2f48f3 100644 --- a/application/CohortManager/src/Functions/Shared/Model/Participant.cs +++ b/application/CohortManager/src/Functions/Shared/Model/Participant.cs @@ -113,17 +113,17 @@ public ParticipantManagement ToParticipantManagement() { var participantManagement = new ParticipantManagement { - ParticipantId = long.TryParse(ParticipantId, out var participantId) ? participantId : 0, - ScreeningId = long.TryParse(ScreeningId, out var screeningId) ? screeningId : 0, - NHSNumber = long.TryParse(NhsNumber, out var nhsNumber) ? nhsNumber : 0, - RecordType = RecordType ?? string.Empty, - EligibilityFlag = short.TryParse(EligibilityFlag, out var eligibilityFlag) ? eligibilityFlag : (short)0, + ParticipantId = long.Parse(ParticipantId), + ScreeningId = long.Parse(ScreeningId), + NHSNumber = long.Parse(NhsNumber), + RecordType = RecordType, + EligibilityFlag = short.Parse(EligibilityFlag), ReasonForRemoval = ReasonForRemoval, - ReasonForRemovalDate = DateTime.TryParse(ReasonForRemovalEffectiveFromDate, out var removalDate) ? removalDate : null, + ReasonForRemovalDate = DateTime.Parse(ReasonForRemovalEffectiveFromDate), BusinessRuleVersion = BusinessRuleVersion, ExceptionFlag = short.Parse(ExceptionFlag ?? "0"), - RecordInsertDateTime = DateTime.TryParse(RecordInsertDateTime, out var insertDate) ? insertDate : null, - RecordUpdateDateTime = DateTime.TryParse(RecordUpdateDateTime, out var updateDate) ? updateDate : null, + RecordInsertDateTime = DateTime.Parse(RecordInsertDateTime), + RecordUpdateDateTime = DateTime.Parse(RecordUpdateDateTime), }; return participantManagement; diff --git a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs index b57b845a2..47c33b8ea 100644 --- a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs +++ b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs @@ -172,7 +172,7 @@ public async Task RunAsync_AllocateServiceProviderToParticipantRequestFails_Retu } [TestMethod] - public async Task RunAsync_TransformDataServiceRequestFails_ReturnsBadRequest() + public async Task RunAsync_TransformDataServiceRequestFails_LogError() { // Arrange _cohortDistributionHelper @@ -194,14 +194,14 @@ public async Task RunAsync_TransformDataServiceRequestFails_ReturnsBadRequest() _logger.Verify(x => x.Log(It.Is(l => l == LogLevel.Error), It.IsAny(), - It.Is((v, t) => v.ToString().Contains("The transform participant returned null in cohort distribution")), + It.Is((v, t) => v.ToString().Contains("The transformed participant returned null from the transform participant function")), It.IsAny(), It.IsAny>()), Times.Once); } [TestMethod] - public async Task RunAsync_AddCohortDistributionRequestFails_ReturnsBadRequest() + public async Task RunAsync_AddCohortDistributionRequestFails_LogError() { // Arrange Exception caughtException = null; @@ -319,7 +319,7 @@ public async Task RunAsync_ParticipantHasException_CreatesSystemExceptionLog() } [TestMethod] - public async Task RunAsync_ValidationFailed_CreatesValidationExceptionLog() + public async Task RunAsync_ValidationRequestFailed_CreateValidationExceptionLog() { // Arrange _cohortDistributionHelper @@ -356,9 +356,10 @@ public async Task RunAsync_ParticipantHasExceptionAndEnvironmentVariableFalse_Cr { // Arrange Environment.SetEnvironmentVariable("IgnoreParticipantExceptions", "false"); - _participantManagementClientMock - .Setup(c => c.GetSingleByFilter(It.IsAny>>())) - .ReturnsAsync(new ParticipantManagement() { ExceptionFlag = 1 }); + _cohortDistributionParticipant.ExceptionFlag = 1; + _cohortDistributionHelper + .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) + .ReturnsAsync(_cohortDistributionParticipant); _cohortDistributionHelper .Setup(x => x.AllocateServiceProviderAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(""); @@ -368,9 +369,9 @@ public async Task RunAsync_ParticipantHasExceptionAndEnvironmentVariableFalse_Cr // Assert _logger.Verify(x => x.Log( - LogLevel.Information, + LogLevel.Error, It.IsAny(), - It.Is((v, t) => v.ToString().Contains($"Unable to add to cohort distribution.")), + It.Is((v, t) => v.ToString().Contains($"Unable to add to cohort distribution")), It.IsAny(), It.IsAny>())); } From edb38bc34a334a29296e41ece543add6b4d51a67 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:55:46 +0000 Subject: [PATCH 08/19] fix: sonarqube isssues --- .../CreateCohortDistribution.cs | 5 ----- .../src/Functions/Shared/Model/Participant.cs | 16 ++++++++++++---- .../updateParticipantDetails.cs | 5 +++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs index fdf2bb864..022b46fba 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs @@ -18,7 +18,6 @@ public class CreateCohortDistribution private readonly ICohortDistributionHelper _CohortDistributionHelper; private readonly IExceptionHandler _exceptionHandler; private readonly IAzureQueueStorageHelper _azureQueueStorageHelper; - private readonly IDataServiceClient _participantManagementClient; public CreateCohortDistribution(ILogger logger, ICallFunction callFunction, @@ -32,7 +31,6 @@ public CreateCohortDistribution(ILogger logger, _CohortDistributionHelper = CohortDistributionHelper; _exceptionHandler = exceptionHandler; _azureQueueStorageHelper = azureQueueStorageHelper; - _participantManagementClient = participantManagementClient; } [Function(nameof(CreateCohortDistribution))] @@ -54,8 +52,6 @@ public async Task RunAsync([QueueTrigger("%CohortQueueName%", Connection = "Azur return; } - _logger.LogInformation("Participant data Screening Id: {participantData}", participantData.ScreeningServiceId); - // Allocate service provider var serviceProvider = EnumHelper.GetDisplayName(ServiceProvider.BSS); if (!string.IsNullOrEmpty(participantData.Postcode)) @@ -108,7 +104,6 @@ await HandleErrorResponseAsync($"Unable to add to cohort distribution. As partic return; } _logger.LogInformation("Participant has been successfully put on the cohort distribution table"); - return; } catch (Exception ex) { diff --git a/application/CohortManager/src/Functions/Shared/Model/Participant.cs b/application/CohortManager/src/Functions/Shared/Model/Participant.cs index d9e2f48f3..8deb2b3f4 100644 --- a/application/CohortManager/src/Functions/Shared/Model/Participant.cs +++ b/application/CohortManager/src/Functions/Shared/Model/Participant.cs @@ -1,6 +1,8 @@ namespace Model; using Model.Enums; +using System; +using System.Globalization; public class Participant { @@ -111,19 +113,25 @@ public ParticipantDemographic ToParticipantDemographic() public ParticipantManagement ToParticipantManagement() { + // string format = "yyyy-MM-dd HH:mm:ss"; // Matches the exact format + // CultureInfo culture = CultureInfo.InvariantCulture; + var participantManagement = new ParticipantManagement { ParticipantId = long.Parse(ParticipantId), ScreeningId = long.Parse(ScreeningId), NHSNumber = long.Parse(NhsNumber), RecordType = RecordType, - EligibilityFlag = short.Parse(EligibilityFlag), + EligibilityFlag = short.Parse(EligibilityFlag ?? "1"), ReasonForRemoval = ReasonForRemoval, - ReasonForRemovalDate = DateTime.Parse(ReasonForRemovalEffectiveFromDate), + ReasonForRemovalDate = string.IsNullOrWhiteSpace(ReasonForRemovalEffectiveFromDate) ? + null : DateTime.Parse(ReasonForRemovalEffectiveFromDate), BusinessRuleVersion = BusinessRuleVersion, ExceptionFlag = short.Parse(ExceptionFlag ?? "0"), - RecordInsertDateTime = DateTime.Parse(RecordInsertDateTime), - RecordUpdateDateTime = DateTime.Parse(RecordUpdateDateTime), + RecordInsertDateTime = string.IsNullOrWhiteSpace(RecordInsertDateTime) + ? null : DateTime.Parse(RecordInsertDateTime), + RecordUpdateDateTime = string.IsNullOrWhiteSpace(RecordUpdateDateTime) + ? null : DateTime.Parse(RecordUpdateDateTime), }; return participantManagement; diff --git a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs index 1f5c1af29..d2469e701 100644 --- a/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs +++ b/application/CohortManager/src/Functions/screeningDataServices/updateParticipantDetails/updateParticipantDetails.cs @@ -54,27 +54,28 @@ public async Task Run([HttpTrigger(AuthorizationLevel.Anonymou if (response.IsFatal) { _logger.LogError("Validation Error: A fatal Rule was violated and therefore the record cannot be added to the database with Nhs number: {NhsNumber}", participantCsvRecord.Participant.NhsNumber); + System.Console.WriteLine("validation error - fatal"); return _createResponse.CreateHttpResponse(HttpStatusCode.Created, req); } if (response.CreatedException) { _logger.LogInformation("Validation Error: A Rule was violated but it was not Fatal for record with Nhs number: {NhsNumber}", participantCsvRecord.Participant.NhsNumber); + System.Console.WriteLine("validation error - not fatal"); reqParticipant.ExceptionFlag = "1"; } var isAdded = await _participantManagementClient.Update(reqParticipant.ToParticipantManagement()); if (isAdded) - { return _createResponse.CreateHttpResponse(HttpStatusCode.OK, req); - } return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req); } catch (Exception ex) { _logger.LogError(ex, ex.Message, ex); + System.Console.WriteLine(ex); await _handleException.CreateSystemExceptionLog(ex, participantCsvRecord.Participant, participantCsvRecord.FileName); return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req); } From 92d031c4a664cfc7f10608e6d266fcf01ba2c725 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:58:37 +0000 Subject: [PATCH 09/19] removing unused data service --- .../CreateCohortDistribution/Program.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs index 997c78088..80ba033d3 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/Program.cs @@ -8,9 +8,6 @@ var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() - .AddDataServicesHandler() - .AddDataService(Environment.GetEnvironmentVariable("ParticipantManagementUrl")) - .Build() .ConfigureServices(services => { services.AddSingleton(); From 55b5b207c1f5e08adf8e3a5b7021101c7a6326d5 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:35:13 +0000 Subject: [PATCH 10/19] Update RetrieveParticipantDataTests.cs --- .../RetrieveParticipantDataTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs index 2a091e64e..0f6f0d9cd 100644 --- a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs +++ b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs @@ -65,7 +65,7 @@ public async Task Run_RequestBodyInvalid_ReturnBadRequest() var result = await _sut.RunAsync(_request.Object); // Assert - Assert.AreEqual(HttpStatusCode.InternalServerError, result.StatusCode); + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); } [TestMethod] From ebde7d888560177cbd69831ee1771a48d4f9b581 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:40:36 +0000 Subject: [PATCH 11/19] Update Participant.cs --- .../CohortManager/src/Functions/Shared/Model/Participant.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/CohortManager/src/Functions/Shared/Model/Participant.cs b/application/CohortManager/src/Functions/Shared/Model/Participant.cs index 2acdd4ab2..ad8add612 100644 --- a/application/CohortManager/src/Functions/Shared/Model/Participant.cs +++ b/application/CohortManager/src/Functions/Shared/Model/Participant.cs @@ -113,9 +113,6 @@ public ParticipantDemographic ToParticipantDemographic() public ParticipantManagement ToParticipantManagement() { - // string format = "yyyy-MM-dd HH:mm:ss"; // Matches the exact format - // CultureInfo culture = CultureInfo.InvariantCulture; - var participantManagement = new ParticipantManagement { ParticipantId = long.Parse(ParticipantId), From 7e80b01f9aeb471aff5e91d1382a8584322619a2 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 09:53:58 +0000 Subject: [PATCH 12/19] Update CreateCohortDistribution.cs --- .../CreateCohortDistribution/CreateCohortDistribution.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs index 022b46fba..37cd3d3a5 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/CreateCohortDistribution/CreateCohortDistribution.cs @@ -23,7 +23,6 @@ public CreateCohortDistribution(ILogger logger, ICallFunction callFunction, ICohortDistributionHelper CohortDistributionHelper, IExceptionHandler exceptionHandler, - IDataServiceClient participantManagementClient, IAzureQueueStorageHelper azureQueueStorageHelper) { _logger = logger; From 39bd8ebce104048b5a0b50feaf2d50616fa1a0ec Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 10:06:33 +0000 Subject: [PATCH 13/19] Update CreateCohortDistributionTests.cs --- .../CreateCohortDistributionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs index 47c33b8ea..c2d3c53e0 100644 --- a/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs +++ b/tests/UnitTests/CohortDistributionTests/CreateCohortDistributionTests/CreateCohortDistributionTests.cs @@ -63,8 +63,8 @@ public CreateCohortDistributionTests() .Setup(x => x.RetrieveParticipantDataAsync(It.IsAny())) .ReturnsAsync(_cohortDistributionParticipant); - _sut = new CreateCohortDistribution(_logger.Object, _callFunction.Object, _cohortDistributionHelper.Object, _exceptionHandler.Object, - _participantManagementClientMock.Object, _azureQueueStorageHelper.Object); + _sut = new CreateCohortDistribution(_logger.Object, _callFunction.Object, _cohortDistributionHelper.Object, + _exceptionHandler.Object, _azureQueueStorageHelper.Object); } From 9e7f4058d1a9350e6972a1b8a01f6d51b9d4ecb2 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 11:05:43 +0000 Subject: [PATCH 14/19] Update RetrieveParticipantData.cs --- .../RetrieveParticipantData/RetrieveParticipantData.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index d09934ef9..c56c447b7 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -56,8 +56,10 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano try { - var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber == long.Parse(requestBody.NhsNumber) && - p.ScreeningId == long.Parse(requestBody.ScreeningService)); + var longNhsNumber = long.Parse(requestBody.NhsNumber); + var longScreeningId = long.Parse(requestBody.ScreeningService) + var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber == longNhsNumber && + p.ScreeningId == longScreeningId); _logger.LogInformation("Got the participant. ScreeningId: {ScreeningServiceId}", participantData.ScreeningId); var demographicFunctionParams = new Dictionary() From da5bc3556bb1cae7a1ba1b64aab1c16cfefba86d Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 11:09:34 +0000 Subject: [PATCH 15/19] Update RetrieveParticipantData.cs --- .../RetrieveParticipantData/RetrieveParticipantData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index c56c447b7..eb51a092a 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -57,7 +57,7 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano try { var longNhsNumber = long.Parse(requestBody.NhsNumber); - var longScreeningId = long.Parse(requestBody.ScreeningService) + var longScreeningId = long.Parse(requestBody.ScreeningService); var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber == longNhsNumber && p.ScreeningId == longScreeningId); _logger.LogInformation("Got the participant. ScreeningId: {ScreeningServiceId}", participantData.ScreeningId); From fca452a293837bd82436b6e9076ee354b10da4ed Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 12:47:25 +0000 Subject: [PATCH 16/19] fix: tests --- .../RetrieveParticipantData.cs | 13 +++++++++++-- .../RetrieveParticipantDataTests.cs | 7 +++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index eb51a092a..08709b97e 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -37,6 +37,7 @@ public RetrieveParticipantData(ICreateResponse createResponse, ILogger RunAsync([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req) { + long? screeningIdLong; RetrieveParticipantRequestBody requestBody; var participant = new CohortDistributionParticipant(); try @@ -47,6 +48,12 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano requestBodyJson = await reader.ReadToEndAsync(); } requestBody = JsonSerializer.Deserialize(requestBodyJson); + + // Temporary, will be replaced with a lookup to the SCREENING_LOOKUP table + if (requestBody.ScreeningService == "BSS") + screeningIdLong = 1; + else + throw new ArgumentNullException("Screening Service cannot be null"); } catch (Exception ex) { @@ -57,9 +64,8 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano try { var longNhsNumber = long.Parse(requestBody.NhsNumber); - var longScreeningId = long.Parse(requestBody.ScreeningService); var participantData = await _participantManagementClient.GetSingleByFilter(p => p.NHSNumber == longNhsNumber && - p.ScreeningId == longScreeningId); + p.ScreeningId == screeningIdLong); _logger.LogInformation("Got the participant. ScreeningId: {ScreeningServiceId}", participantData.ScreeningId); var demographicFunctionParams = new Dictionary() @@ -78,6 +84,8 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } participant = _createParticipant.CreateCohortDistributionParticipantModel(participantData, demographicData); + // Hardcoded for now + participant.ScreeningAcronym = "BSS"; var responseBody = JsonSerializer.Serialize(participant); _logger.LogInformation("ParticipantScreeningID: {ScreeningServiceId}", participant.ScreeningServiceId); @@ -85,6 +93,7 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } catch (Exception ex) { + System.Console.WriteLine(ex); _logger.LogError(ex, "Retrieve participant data failed.\nMessage: {Message}\nStack Trace: {StackTrace}", ex.Message, ex.StackTrace); await _exceptionHandler.CreateSystemExceptionLogFromNhsNumber(ex, requestBody.NhsNumber, "", "", JsonSerializer.Serialize(participant) ?? "N/A"); return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req); diff --git a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs index 0f6f0d9cd..f9898d45e 100644 --- a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs +++ b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs @@ -130,12 +130,15 @@ public async Task Run_ValidRequest_ReturnOk() _participantManagementClientMock .Setup(x => x.GetSingleByFilter(It.IsAny>>())) - .ReturnsAsync(new ParticipantManagement {NHSNumber = 1234567890}); - _callFunction.Setup(x => x.SendGet(It.IsAny(), It.IsAny>())).Returns(Task.FromResult(JsonSerializer.Serialize(demographic))).Verifiable(); + .ReturnsAsync(new ParticipantManagement {NHSNumber = 1234567890, ScreeningId = 1}); + _callFunction.Setup(x => x.SendGet(It.IsAny(), It.IsAny>())) + .ReturnsAsync(JsonSerializer.Serialize(demographic)) + .Verifiable(); // Act var result = await _sut.RunAsync(_request.Object); string responseBody = await AssertionHelper.ReadResponseBodyAsync(result); + System.Console.WriteLine("response body: " + responseBody); var response = JsonSerializer.Deserialize(responseBody); // Assert From a1db572ed0ef85eec1a79c6be6a46e5db040dbaf Mon Sep 17 00:00:00 2001 From: Michael Clayson Date: Fri, 7 Feb 2025 13:58:47 +0000 Subject: [PATCH 17/19] fix: temporary hardcoding of Screening Service Data --- .../RetrieveParticipantData.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index 08709b97e..37ec4e01c 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -37,7 +37,7 @@ public RetrieveParticipantData(ICreateResponse createResponse, ILogger RunAsync([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req) { - long? screeningIdLong; + long screeningIdLong; RetrieveParticipantRequestBody requestBody; var participant = new CohortDistributionParticipant(); try @@ -49,11 +49,7 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } requestBody = JsonSerializer.Deserialize(requestBodyJson); - // Temporary, will be replaced with a lookup to the SCREENING_LOOKUP table - if (requestBody.ScreeningService == "BSS") - screeningIdLong = 1; - else - throw new ArgumentNullException("Screening Service cannot be null"); + screeningIdLong = long.Parse(requestBody.ScreeningService); } catch (Exception ex) { @@ -84,8 +80,10 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } participant = _createParticipant.CreateCohortDistributionParticipantModel(participantData, demographicData); - // Hardcoded for now + //TODO, This needs to happen elsewhere Hardcoded for now + participant.ScreeningName = "Breast Screening"; participant.ScreeningAcronym = "BSS"; + var responseBody = JsonSerializer.Serialize(participant); _logger.LogInformation("ParticipantScreeningID: {ScreeningServiceId}", participant.ScreeningServiceId); From 274ccd851dc143a6ff888a27ea09cb6f5a53906d Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:15:11 +0000 Subject: [PATCH 18/19] fix: tests --- .../RetrieveParticipantDataTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs index f9898d45e..998e137aa 100644 --- a/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs +++ b/tests/UnitTests/CohortDistributionTests/RetrieveParticipantDataTests/RetrieveParticipantDataTests.cs @@ -38,7 +38,7 @@ public RetrieveParticipantDataTests() _requestBody = new RetrieveParticipantRequestBody() { NhsNumber = "1234567890", - ScreeningService = "BSS" + ScreeningService = "1" }; _request = _setupRequest.Setup(JsonSerializer.Serialize(_requestBody)); From ccffb870439d3f1521977c3b66b3d0184fd728c3 Mon Sep 17 00:00:00 2001 From: will-larkin <160748088+will-larkin-nhs@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:16:32 +0000 Subject: [PATCH 19/19] Update RetrieveParticipantData.cs --- .../RetrieveParticipantData/RetrieveParticipantData.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs index 37ec4e01c..3f548ee6e 100644 --- a/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs +++ b/application/CohortManager/src/Functions/CohortDistributionServices/RetrieveParticipantData/RetrieveParticipantData.cs @@ -91,7 +91,6 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } catch (Exception ex) { - System.Console.WriteLine(ex); _logger.LogError(ex, "Retrieve participant data failed.\nMessage: {Message}\nStack Trace: {StackTrace}", ex.Message, ex.StackTrace); await _exceptionHandler.CreateSystemExceptionLogFromNhsNumber(ex, requestBody.NhsNumber, "", "", JsonSerializer.Serialize(participant) ?? "N/A"); return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req);