Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
653f9ad
feat: Add PDS Stub
Joseph2910 Jul 23, 2025
d3e24bf
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Jul 30, 2025
c960229
block participant refactor
MWClayson-NHS Jul 31, 2025
2c82910
Stubbing Nems API
MWClayson-NHS Aug 4, 2025
fc9c802
Update Logging and returning body
MWClayson-NHS Aug 4, 2025
b067b34
get participant and bug fixes
MWClayson-NHS Aug 5, 2025
00a155c
unblock participant
MWClayson-NHS Aug 5, 2025
cd08964
tidying
MWClayson-NHS Aug 5, 2025
897f940
Eligbility flag logic
MWClayson-NHS Aug 5, 2025
f68f937
Logging and remove rule
MWClayson-NHS Aug 6, 2025
45c1f94
intial tests
MWClayson-NHS Aug 6, 2025
b4b2277
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Aug 6, 2025
b1f4114
tfvars and compose
MWClayson-NHS Aug 6, 2025
22c8b84
function signature overlap
MWClayson-NHS Aug 6, 2025
6dba115
some sonar qube fixes
MWClayson-NHS Aug 6, 2025
a6f0328
more sonar qube fixes
MWClayson-NHS Aug 6, 2025
1536ba8
more sonar qube fixes
MWClayson-NHS Aug 6, 2025
52ee103
more sonar qube
MWClayson-NHS Aug 6, 2025
05b2d87
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Aug 6, 2025
bdd0ddd
tests part one
MWClayson-NHS Aug 6, 2025
b8cb0f1
Correct Logging from PR Comment
MWClayson-NHS Aug 6, 2025
2379d50
Addressing comments
MWClayson-NHS Aug 6, 2025
d32e4df
Incorrect Logic comment
MWClayson-NHS Aug 6, 2025
973ed23
Block Participant Tests
MWClayson-NHS Aug 6, 2025
7e79391
Addressing Comments
MWClayson-NHS Aug 6, 2025
d22b07d
Sonar Qube
MWClayson-NHS Aug 6, 2025
801ea55
Tests
MWClayson-NHS Aug 7, 2025
6ace84b
remove duplicate test
MWClayson-NHS Aug 7, 2025
1c09833
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Aug 7, 2025
0f80b54
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Aug 7, 2025
1078949
Addressing Comments
MWClayson-NHS Aug 7, 2025
f53c8ef
using const for cannot parse message
MWClayson-NHS Aug 7, 2025
227b73c
unused usings
MWClayson-NHS Aug 7, 2025
cc85893
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Aug 7, 2025
efaf6b6
Merge branch 'main' into Block-Phase-2-PDS
MWClayson-NHS Aug 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace NHS.CohortManager.ParticipantManagementService;
using System.Text.Json;
using Common;
using DataServices.Client;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
Comment thread
SamAinsworth-NHS marked this conversation as resolved.
Outdated
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Model;
Expand Down Expand Up @@ -70,17 +71,12 @@ public async Task<BlockParticipantResult> BlockParticipant(BlockParticipantDto b

public async Task<BlockParticipantResult> UnblockParticipant(long nhsNumber)
{
if (!ValidationHelper.ValidateNHSNumber(nhsNumber.ToString()))
{
_logger.LogWarning("Invalid NHS Number and cannot be unblocked");
return new BlockParticipantResult(false, "Invalid NHS Number");
}

var participantManagementRecord = await _participantManagementDataService.GetSingleByFilter(x => x.NHSNumber == nhsNumber);

if (participantManagementRecord == null)
{
return new BlockParticipantResult(false, "Participant couldn't be found");
return new BlockParticipantResult(false, "Participant Couldn't be found");
}

if (participantManagementRecord.BlockedFlag != 1)
Comment thread
SamAinsworth-NHS marked this conversation as resolved.
Expand Down Expand Up @@ -227,6 +223,12 @@ private async Task<bool> SetBlockedFlag(ParticipantManagement participant, bool
private async Task<ParticipantDemographic> GetPDSParticipant(long nhsNumber)
{
var pdsResponse = await _httpClient.SendGet(_config.RetrievePdsDemographicURL, CreateNhsNumberQueryParams(nhsNumber));
if (string.IsNullOrEmpty(pdsResponse))
{
_logger.LogWarning("RetrievePDSDemographic Didn't return a valid response");
return null!;
}

var pdsDemographic = JsonSerializer.Deserialize<ParticipantDemographic>(pdsResponse);

return pdsDemographic!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace NHS.CohortManager.ParticipantManagementService;
using Common;
using System.Net;
using System.Text.Json;
using Azure.Messaging.EventGrid.SystemEvents;

public class UpdateBlockedFlag
{
Expand Down Expand Up @@ -91,16 +92,35 @@ public async Task<HttpResponseData> GetParticipantDetails([HttpTrigger(Authoriza
_logger.LogInformation("Get Participant Details Called");
try
{
var blockParticipantDTO = await req.ReadFromJsonAsync<BlockParticipantDto>();
var blockParticipantDTOJson = await req.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(blockParticipantDTOJson))
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, "Unable to parse request");
}

var blockParticipantDTO = JsonSerializer.Deserialize<BlockParticipantDto>(blockParticipantDTOJson);
if (blockParticipantDTO == null)
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, "Unable to parse request");
}

var getParticipantResult = await _blockParticipantHandler.GetParticipant(blockParticipantDTO);

return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.OK, req, getParticipantResult.ResponseMessage!);
if (getParticipantResult.Success)
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.OK, req, getParticipantResult.ResponseMessage!);
}

if (getParticipantResult.ResponseMessage == "Participant Couldn't be found")
Comment thread
MWClayson-NHS marked this conversation as resolved.
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.NotFound, req, "Participant Not found");
Comment thread
alex-clayton-1 marked this conversation as resolved.
Outdated
}
if (getParticipantResult.ResponseMessage == "Invalid NHS Number")
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, getParticipantResult.ResponseMessage);
}

return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.InternalServerError, req, getParticipantResult.ResponseMessage!);

}
catch (JsonException jex)
Expand Down Expand Up @@ -149,12 +169,18 @@ public async Task<HttpResponseData> UnblockParticipant([HttpTrigger(Authorizatio

var unBlockParticipantResult = await _blockParticipantHandler.UnblockParticipant(nhsNumberParsed);

if (!unBlockParticipantResult.Success)
if (unBlockParticipantResult.Success)
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, unBlockParticipantResult.ResponseMessage!);
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.OK, req, "Participant successfully unblocked");
}
if (unBlockParticipantResult.ResponseMessage == "Participant Couldn't be found")
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.NotFound, req, "Participant Not found");
}

return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, unBlockParticipantResult.ResponseMessage!);


return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.OK, req, "Participant successfully unblocked");

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public async Task BlockParticipant_ExistingParticipantFailsThreePointCheck_Retur
_mockParticipantDemographicClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()), Times.Once);
_mockParticipantDemographicClient.VerifyNoOtherCalls();
}
[TestMethod]
[TestMethod]
public async Task BlockParticipant_NonExistentParticipantFailsThreePointCheck_ReturnsFailure()
{
//arrange
Expand Down Expand Up @@ -280,6 +280,270 @@ public async Task BlockParticipant_NonExistentParticipantFailsThreePointCheck_Re
_mockParticipantManagementClient.VerifyNoOtherCalls();
_mockHttpClient.VerifyNoOtherCalls();
}
[TestMethod]
public async Task GetParticipant_ParticipantExistsInCM_ReturnsSuccess()
{
//arrange
var requestBody = new BlockParticipantDto
{
NhsNumber = 6427635034,
FamilyName = "Jones",
DateOfBirth = "1923-10-12"
};

_request = _setupRequest.Setup(JsonSerializer.Serialize(requestBody));

_mockParticipantDemographicClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()))
.ReturnsAsync(new ParticipantDemographic
{
NhsNumber = 6427635034,
FamilyName = "Jones",
DateOfBirth = "19231012"
});



//act
var result = await _sut.GetParticipantDetails(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
_mockParticipantDemographicClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()));
_mockParticipantManagementClient.VerifyNoOtherCalls();
_mockHttpClient.VerifyNoOtherCalls();
}
[TestMethod]
public async Task GetParticipant_ParticipantOnlyInPDS_ReturnsSuccess()
{
//arrange
var requestBody = new BlockParticipantDto
{
NhsNumber = 6427635034,
FamilyName = "Jones",
DateOfBirth = "1923-10-12"
};

_request = _setupRequest.Setup(JsonSerializer.Serialize(requestBody));

_mockParticipantDemographicClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()))
.Returns(Task.FromResult<ParticipantDemographic>(null!));

var pdsDemoResponse = JsonSerializer.Serialize(
new ParticipantDemographic
{
NhsNumber = 6427635034,
FamilyName = "Jones",
DateOfBirth = "19231012"
});

_mockHttpClient.Setup(x => x.SendGet("RetrievePdsDemographicUrl", It.IsAny<Dictionary<string, string>>()))
.ReturnsAsync(pdsDemoResponse);


//act
var result = await _sut.GetParticipantDetails(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
_mockHttpClient.Verify(x => x.SendGet("RetrievePdsDemographicUrl", It.IsAny<Dictionary<string, string>>()), Times.Once);
_mockParticipantDemographicClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()));
_mockParticipantManagementClient.VerifyNoOtherCalls();
_mockHttpClient.VerifyNoOtherCalls();
}
[TestMethod]
public async Task GetParticipant_ParticipantNotExists_ReturnsFailure()
{
//arrange
var requestBody = new BlockParticipantDto
{
NhsNumber = 6427635034,
FamilyName = "Jones",
DateOfBirth = "1923-10-12"
};

_request = _setupRequest.Setup(JsonSerializer.Serialize(requestBody));

_mockParticipantDemographicClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()))
.Returns(Task.FromResult<ParticipantDemographic>(null!));

var pdsDemoResponse = JsonSerializer.Serialize(
new ParticipantDemographic
{
NhsNumber = 6427635034,
FamilyName = "Jones",
DateOfBirth = "19231012"
});

_mockHttpClient.Setup(x => x.SendGet("RetrievePdsDemographicUrl", It.IsAny<Dictionary<string, string>>()))
.Returns(Task.FromResult<string?>("")!);


//act
var result = await _sut.GetParticipantDetails(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode);
_mockHttpClient.Verify(x => x.SendGet("RetrievePdsDemographicUrl", It.IsAny<Dictionary<string, string>>()), Times.Once);
_mockParticipantDemographicClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantDemographic, bool>>>()), Times.Once);
_mockParticipantManagementClient.VerifyNoOtherCalls();
_mockHttpClient.VerifyNoOtherCalls();
}
[TestMethod]
public async Task GetParticipant_InvalidNhsNumber_ReturnsFailure()
{
//arrange
var requestBody = new BlockParticipantDto
{
NhsNumber = 6427635035,
FamilyName = "Jones",
DateOfBirth = "1923-10-12"
};

_request = _setupRequest.Setup(JsonSerializer.Serialize(requestBody));

//act
var result = await _sut.GetParticipantDetails(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode);
}
[TestMethod]
public async Task UnblockParticipant_ParticipantIsBlocked_ReturnsSuccess()
{
//arrange
var queryParams = new NameValueCollection
{
{"nhsNumber","6427635034"}
};
_request = _setupRequest.Setup("", queryParams, HttpMethod.Post);

_mockParticipantManagementClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()))
.ReturnsAsync(new ParticipantManagement
{
NHSNumber = 6427635034,
BlockedFlag = 1,
EligibilityFlag = 1
});

_mockParticipantManagementClient.Setup(x => x.Update(It.IsAny<ParticipantManagement>()))
.ReturnsAsync(true);

_mockHttpClient.Setup(x => x.SendPost("NemsSubscribeUrl", It.IsAny<Dictionary<string, string>>()))
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK
});


//act
var result = await _sut.UnblockParticipant(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
_mockHttpClient.Verify(x => x.SendPost("NemsSubscribeUrl", It.IsAny<Dictionary<string, string>>()), Times.Once);
_mockParticipantManagementClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()), Times.Once);
_mockParticipantManagementClient.Verify(x => x.Update(It.IsAny<ParticipantManagement>()), Times.Once);
_mockParticipantManagementClient.VerifyNoOtherCalls();
_mockHttpClient.VerifyNoOtherCalls();
}

[TestMethod]
[DataRow("6427635035")]
[DataRow("642763")]
[DataRow("abs7635035")]
public async Task UnblockParticipant_InvalidNhsNumber_ReturnsFailure(string nhsNumber)
{
//arrange
var queryParams = new NameValueCollection
{
{"nhsNumber",nhsNumber}
};
_request = _setupRequest.Setup("", queryParams, HttpMethod.Post);

//act
var result = await _sut.UnblockParticipant(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode);
}
[TestMethod]
public async Task UnblockParticipant_ParticipantNotFound_ReturnsFailure()
{
//arrange
var queryParams = new NameValueCollection
{
{"nhsNumber","6427635034"}
};
_request = _setupRequest.Setup("", queryParams, HttpMethod.Post);

_mockParticipantManagementClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()))
.Returns(Task.FromResult<ParticipantManagement>(null!));

//act
var result = await _sut.UnblockParticipant(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode);
_mockParticipantManagementClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()), Times.Once);
_mockHttpClient.VerifyNoOtherCalls();
}
[TestMethod]
public async Task UnblockParticipant_ParticipantNotBlocked_ReturnBadRequest()
{
//arrange
var queryParams = new NameValueCollection
{
{"nhsNumber","6427635034"}
};
_request = _setupRequest.Setup("", queryParams, HttpMethod.Post);

_mockParticipantManagementClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()))
.ReturnsAsync(new ParticipantManagement
{
NHSNumber = 6427635034,
BlockedFlag = 0,
EligibilityFlag = 1
});


//act
var result = await _sut.UnblockParticipant(_request.Object);

//asset
Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode);
_mockParticipantManagementClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()), Times.Once);
_mockParticipantManagementClient.VerifyNoOtherCalls();
_mockHttpClient.VerifyNoOtherCalls();
}
// [TestMethod]
// public async Task UnblockParticipant_ParticipantNotBlocked_ReturnBadRequest()
// {
// //arrange
// var queryParams = new NameValueCollection
// {
// {"nhsNumber","6427635034"}
// };
// _request = _setupRequest.Setup("", queryParams, HttpMethod.Post);

// _mockParticipantManagementClient.Setup(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()))
// .ReturnsAsync(new ParticipantManagement
// {
// NHSNumber = 6427635034,
// BlockedFlag = 0,
// EligibilityFlag = 1
// });


// //act
// var result = await _sut.UnblockParticipant(_request.Object);

// //asset
// Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode);
// _mockParticipantManagementClient.Verify(x => x.GetSingleByFilter(It.IsAny<Expression<Func<ParticipantManagement, bool>>>()), Times.Once);
// _mockParticipantManagementClient.VerifyNoOtherCalls();
// _mockHttpClient.VerifyNoOtherCalls();
// }




Expand Down