Skip to content

Commit 83bacb9

Browse files
chore: adding unit tests for PDS functionality (#1452)
* fix: pds function now maganges all responses from the 3rd party pds API * chore: creating a new class that contains all the pds constraints * chore: removing unneeded codes * chore: renaming ProcessPdsResponse to ProcessPdsNotFoundResponse * fix: making sure to add service buss to pds * chor: adding unit tests for pds functions features * chore: addressing comments on pr
1 parent b766d9a commit 83bacb9

8 files changed

Lines changed: 458 additions & 98 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace NHS.CohortManager.DemographicServices;
2+
3+
using Model;
4+
5+
public interface IPdsProcessor
6+
{
7+
Task ProcessPdsNotFoundResponse(HttpResponseMessage pdsResponse, string nhsNumber);
8+
Task ProcessRecord(Participant participant);
9+
Task<bool> UpsertDemographicRecordFromPDS(ParticipantDemographic participantDemographic);
10+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
namespace NHS.CohortManager.DemographicServices;
2+
3+
using System.Collections.Concurrent;
4+
using System.Net.Http.Json;
5+
using Common;
6+
using DataServices.Client;
7+
using Microsoft.Extensions.Logging;
8+
using Microsoft.Extensions.Options;
9+
using Model;
10+
11+
public class PdsProcessor : IPdsProcessor
12+
{
13+
private readonly ILogger<PdsProcessor> _logger;
14+
15+
private readonly IDataServiceClient<ParticipantDemographic> _participantDemographicClient;
16+
private readonly ICreateBasicParticipantData _createBasicParticipantData;
17+
private readonly RetrievePDSDemographicConfig _config;
18+
private readonly IAddBatchToQueue _addBatchToQueue;
19+
20+
21+
public PdsProcessor(
22+
ILogger<PdsProcessor> logger,
23+
ICreateBasicParticipantData createBasicParticipantData,
24+
IDataServiceClient<ParticipantDemographic> participantDemographicClient,
25+
IAddBatchToQueue addBatchToQueue,
26+
IOptions<RetrievePDSDemographicConfig> retrievePDSDemographicConfig)
27+
{
28+
_logger = logger;
29+
_participantDemographicClient = participantDemographicClient;
30+
_createBasicParticipantData = createBasicParticipantData;
31+
_addBatchToQueue = addBatchToQueue;
32+
_config = retrievePDSDemographicConfig.Value;
33+
}
34+
35+
/// <summary>
36+
/// processes pds error responses. Sends a record to distribute participant via service bus
37+
/// </summary>
38+
/// <param name="pdsResponse"></param>
39+
/// <param name="nhsNumber"></param>
40+
/// <returns></returns>
41+
public async Task ProcessPdsNotFoundResponse(HttpResponseMessage pdsResponse, string nhsNumber)
42+
{
43+
var errorResponse = await pdsResponse!.Content.ReadFromJsonAsync<PdsErrorResponse>();
44+
// we now create a record as an update record and send to the manage participant function. Reason for removal for date should be today and the reason for remove of ORR
45+
if (errorResponse!.issue!.FirstOrDefault()!.details!.coding!.FirstOrDefault()!.code == PdsConstants.InvalidatedResourceCode)
46+
{
47+
var pdsDemographic = new PdsDemographic()
48+
{
49+
NhsNumber = nhsNumber,
50+
PrimaryCareProvider = null,
51+
ReasonForRemoval = PdsConstants.OrrRemovalReason,
52+
RemovalEffectiveFromDate = DateTime.UtcNow.Date.ToString("yyyyMMdd")
53+
};
54+
var participant = new Participant(pdsDemographic);
55+
participant.RecordType = Actions.Removed;
56+
//sends record for an update
57+
await ProcessRecord(participant);
58+
return;
59+
}
60+
_logger.LogError("the PDS function has returned a 404 error. function now stopping processing");
61+
}
62+
63+
/// <summary>
64+
/// sends a participant record to the distribute service bus topic
65+
/// </summary>
66+
/// <param name="participant"></param>
67+
/// <returns></returns>
68+
public async Task ProcessRecord(Participant participant)
69+
{
70+
var updateRecord = new ConcurrentQueue<BasicParticipantCsvRecord>();
71+
participant.RecordType = Actions.Removed;
72+
73+
var basicParticipantCsvRecord = new BasicParticipantCsvRecord
74+
{
75+
BasicParticipantData = _createBasicParticipantData.BasicParticipantData(participant),
76+
FileName = PdsConstants.DefaultFileName,
77+
Participant = participant
78+
};
79+
80+
updateRecord.Enqueue(basicParticipantCsvRecord);
81+
82+
_logger.LogInformation("Sending record to the update queue.");
83+
await _addBatchToQueue.ProcessBatch(updateRecord, _config.ParticipantManagementTopic);
84+
}
85+
86+
/// <summary>
87+
/// adds or updates a demographic record depending on if an record already exists in the database
88+
/// </summary>
89+
/// <param name="participantDemographic"></param>
90+
/// <returns></returns>
91+
public async Task<bool> UpsertDemographicRecordFromPDS(ParticipantDemographic participantDemographic)
92+
{
93+
ParticipantDemographic oldParticipantDemographic = await _participantDemographicClient.GetSingleByFilter(i => i.NhsNumber == participantDemographic.NhsNumber);
94+
95+
if (oldParticipantDemographic == null)
96+
{
97+
_logger.LogInformation("Participant Demographic record not found, attemping to add Participant Demographic.");
98+
bool addSuccess = await _participantDemographicClient.Add(participantDemographic);
99+
100+
if (addSuccess)
101+
{
102+
_logger.LogInformation("Successfully added Participant Demographic.");
103+
return true;
104+
}
105+
106+
_logger.LogError("Failed to add Participant Demographic.");
107+
return false;
108+
}
109+
110+
_logger.LogInformation("Participant Demographic record found, attempting to update Participant Demographic.");
111+
participantDemographic.ParticipantId = oldParticipantDemographic.ParticipantId;
112+
bool updateSuccess = await _participantDemographicClient.Update(participantDemographic);
113+
114+
if (updateSuccess)
115+
{
116+
_logger.LogInformation("Successfully updated Participant Demographic.");
117+
return true;
118+
}
119+
120+
_logger.LogError("Failed to update Participant Demographic.");
121+
return false;
122+
}
123+
124+
}

application/CohortManager/src/Functions/DemographicServices/RetrievePDSDemographic/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
services.AddSingleton<IHttpParserHelper, HttpParserHelper>();
2020
services.AddSingleton<IFhirPatientDemographicMapper, FhirPatientDemographicMapper>();
2121
services.AddSingleton<IAddBatchToQueue, AddBatchToQueue>();
22+
services.AddSingleton<IPdsProcessor, PdsProcessor>();
2223
services.AddSingleton<ICreateBasicParticipantData, CreateBasicParticipantData>();
2324
// Register health checks
2425
services.AddBasicHealthCheck("RetrievePdsDemographic");

application/CohortManager/src/Functions/DemographicServices/RetrievePDSDemographic/RetrievePDSDemographic.cs

Lines changed: 6 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ namespace NHS.CohortManager.DemographicServices;
1212
using Microsoft.Extensions.Options;
1313
using System.Threading.Tasks;
1414
using Model;
15-
using System.Net.Http.Json;
16-
using System.Collections.Concurrent;
1715

1816
public class RetrievePdsDemographic
1917
{
@@ -22,10 +20,8 @@ public class RetrievePdsDemographic
2220
private readonly IHttpClientFunction _httpClientFunction;
2321
private readonly RetrievePDSDemographicConfig _config;
2422
private readonly IFhirPatientDemographicMapper _fhirPatientDemographicMapper;
25-
private readonly IDataServiceClient<ParticipantDemographic> _participantDemographicClient;
2623
private readonly IBearerTokenService _bearerTokenService;
27-
private readonly ICreateBasicParticipantData _createBasicParticipantData;
28-
private readonly IAddBatchToQueue _addBatchToQueue;
24+
private readonly IPdsProcessor _pdsProcessor;
2925
private const string PdsParticipantUrlFormat = "{0}/{1}";
3026

3127

@@ -35,21 +31,17 @@ public RetrievePdsDemographic(
3531
IHttpClientFunction httpClientFunction,
3632
IFhirPatientDemographicMapper fhirPatientDemographicMapper,
3733
IOptions<RetrievePDSDemographicConfig> retrievePDSDemographicConfig,
38-
IDataServiceClient<ParticipantDemographic> participantDemographicClient,
39-
ICreateBasicParticipantData createBasicParticipantData,
40-
IAddBatchToQueue addBatchToQueue,
41-
IBearerTokenService bearerTokenService
34+
IBearerTokenService bearerTokenService,
35+
IPdsProcessor pdsProcessor
4236
)
4337
{
4438
_logger = logger;
4539
_createResponse = createResponse;
4640
_httpClientFunction = httpClientFunction;
4741
_fhirPatientDemographicMapper = fhirPatientDemographicMapper;
4842
_config = retrievePDSDemographicConfig.Value;
49-
_participantDemographicClient = participantDemographicClient;
50-
_createBasicParticipantData = createBasicParticipantData;
5143
_bearerTokenService = bearerTokenService;
52-
_addBatchToQueue = addBatchToQueue;
44+
_pdsProcessor = pdsProcessor;
5345
}
5446

5547
// TODO: Need to send an exception to the EXCEPTION_MANAGEMENT table whenever this function returns a non OK status.
@@ -82,14 +74,14 @@ public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymou
8274

8375
if (response.StatusCode == HttpStatusCode.NotFound || pdsDemographic.ConfidentialityCode == "R")
8476
{
85-
await ProcessPdsNotFoundResponse(response, nhsNumber);
77+
await _pdsProcessor.ProcessPdsNotFoundResponse(response, nhsNumber);
8678
return _createResponse.CreateHttpResponse(HttpStatusCode.NotFound, req, "PDS returned a 404 please database for details");
8779
}
8880

8981
response.EnsureSuccessStatusCode();
9082

9183
var participantDemographic = pdsDemographic.ToParticipantDemographic();
92-
var upsertResult = await UpsertDemographicRecordFromPDS(participantDemographic);
84+
var upsertResult = await _pdsProcessor.UpsertDemographicRecordFromPDS(participantDemographic);
9385

9486
return upsertResult ?
9587
_createResponse.CreateHttpResponse(HttpStatusCode.OK, req, JsonSerializer.Serialize(participantDemographic)) :
@@ -101,79 +93,4 @@ public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymou
10193
return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req);
10294
}
10395
}
104-
105-
private async Task ProcessPdsNotFoundResponse(HttpResponseMessage pdsResponse, string nhsNumber)
106-
{
107-
var errorResponse = await pdsResponse!.Content.ReadFromJsonAsync<PdsErrorResponse>();
108-
// we now create a record as an update record and send to the manage participant function. Reason for removal for date should be today and the reason for remove of ORR
109-
if (errorResponse!.issue!.FirstOrDefault()!.details!.coding!.FirstOrDefault()!.code == PdsConstants.InvalidatedResourceCode)
110-
{
111-
var pdsDemographic = new PdsDemographic()
112-
{
113-
NhsNumber = nhsNumber,
114-
PrimaryCareProvider = null,
115-
ReasonForRemoval = PdsConstants.OrrRemovalReason,
116-
RemovalEffectiveFromDate = DateTime.UtcNow.Date.ToString("yyyyMMdd")
117-
};
118-
var participant = new Participant(pdsDemographic);
119-
participant.RecordType = Actions.Removed;
120-
//sends record for an update
121-
await ProcessRecord(participant);
122-
return;
123-
}
124-
_logger.LogError("the PDS function has returned a 404 error. function now stopping processing");
125-
}
126-
127-
128-
private async Task ProcessRecord(Participant participant)
129-
{
130-
var updateRecord = new ConcurrentQueue<BasicParticipantCsvRecord>();
131-
participant.RecordType = participant.RecordType = Actions.Removed;
132-
133-
var basicParticipantCsvRecord = new BasicParticipantCsvRecord
134-
{
135-
BasicParticipantData = _createBasicParticipantData.BasicParticipantData(participant),
136-
FileName = PdsConstants.DefaultFileName,
137-
Participant = participant
138-
};
139-
140-
updateRecord.Enqueue(basicParticipantCsvRecord);
141-
142-
_logger.LogInformation("Sending record to the update queue.");
143-
await _addBatchToQueue.ProcessBatch(updateRecord, _config.ParticipantManagementTopic);
144-
}
145-
146-
147-
private async Task<bool> UpsertDemographicRecordFromPDS(ParticipantDemographic participantDemographic)
148-
{
149-
ParticipantDemographic oldParticipantDemographic = await _participantDemographicClient.GetSingleByFilter(i => i.NhsNumber == participantDemographic.NhsNumber);
150-
151-
if (oldParticipantDemographic == null)
152-
{
153-
_logger.LogInformation("Participant Demographic record not found, attemping to add Participant Demographic.");
154-
bool addSuccess = await _participantDemographicClient.Add(participantDemographic);
155-
156-
if (addSuccess)
157-
{
158-
_logger.LogInformation("Successfully added Participant Demographic.");
159-
return true;
160-
}
161-
162-
_logger.LogError("Failed to add Participant Demographic.");
163-
return false;
164-
}
165-
166-
_logger.LogInformation("Participant Demographic record found, attempting to update Participant Demographic.");
167-
participantDemographic.ParticipantId = oldParticipantDemographic.ParticipantId;
168-
bool updateSuccess = await _participantDemographicClient.Update(participantDemographic);
169-
170-
if (updateSuccess)
171-
{
172-
_logger.LogInformation("Successfully updated Participant Demographic.");
173-
return true;
174-
}
175-
176-
_logger.LogError("Failed to update Participant Demographic.");
177-
return false;
178-
}
17996
}

application/CohortManager/src/Functions/Functions.sln

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JWTTokenServiceTests", "..\
229229
EndProject
230230
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuthClientCredentialsTests", "..\..\..\..\tests\UnitTests\AuthClientCredentialsTests\AuthClientCredentialsTests.csproj", "{59CBDBE5-29BE-F38C-80E6-40843F2F8AF6}"
231231
EndProject
232+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PdsProcesserTests", "PdsProcesserTests", "{5555D2A1-8C8F-5B64-9F84-08EFE0FC7CD8}"
233+
EndProject
234+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdsProcessorTests", "..\..\..\..\tests\PdsProcessorTests\PdsProcessorTests.csproj", "{FC22C311-57DD-B069-4041-AD2AC8F80B5D}"
235+
EndProject
232236
Global
233237
GlobalSection(SolutionConfigurationPlatforms) = preSolution
234238
Debug|Any CPU = Debug|Any CPU
@@ -1367,6 +1371,18 @@ Global
13671371
{59CBDBE5-29BE-F38C-80E6-40843F2F8AF6}.Release|x64.Build.0 = Release|Any CPU
13681372
{59CBDBE5-29BE-F38C-80E6-40843F2F8AF6}.Release|x86.ActiveCfg = Release|Any CPU
13691373
{59CBDBE5-29BE-F38C-80E6-40843F2F8AF6}.Release|x86.Build.0 = Release|Any CPU
1374+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1375+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
1376+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Debug|x64.ActiveCfg = Debug|Any CPU
1377+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Debug|x64.Build.0 = Debug|Any CPU
1378+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Debug|x86.ActiveCfg = Debug|Any CPU
1379+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Debug|x86.Build.0 = Debug|Any CPU
1380+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
1381+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Release|Any CPU.Build.0 = Release|Any CPU
1382+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Release|x64.ActiveCfg = Release|Any CPU
1383+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Release|x64.Build.0 = Release|Any CPU
1384+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Release|x86.ActiveCfg = Release|Any CPU
1385+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D}.Release|x86.Build.0 = Release|Any CPU
13701386
EndGlobalSection
13711387
GlobalSection(SolutionProperties) = preSolution
13721388
HideSolutionNode = FALSE
@@ -1428,5 +1444,6 @@ Global
14281444
{52C72C2E-9A76-4ECF-A210-C3F7C584C193} = {19500E0D-AAAB-6F02-E24F-82619ACA2290}
14291445
{4BD680A2-1ACB-7D6B-B2FD-8EBE9AEB5050} = {E8E33C5F-F9FB-3ACA-2B58-298ED48517C1}
14301446
{59CBDBE5-29BE-F38C-80E6-40843F2F8AF6} = {E8E33C5F-F9FB-3ACA-2B58-298ED48517C1}
1447+
{FC22C311-57DD-B069-4041-AD2AC8F80B5D} = {5555D2A1-8C8F-5B64-9F84-08EFE0FC7CD8}
14311448
EndGlobalSection
14321449
EndGlobal

0 commit comments

Comments
 (0)