Skip to content

Commit 2f239fe

Browse files
Merge branch 'main' into Fix/retrieve-pds-demographic-service-bus-connection-string-explicit
2 parents 15d1e91 + e0f7e3d commit 2f239fe

36 files changed

Lines changed: 1610 additions & 354 deletions

File tree

application/CohortManager/compose.core.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ services:
140140
- ParticipantManagementUrl=http://participant-management-data-service:7994/api/ParticipantManagementDataService
141141
- ParticipantDemographicDataServiceURL=http://participant-demographic-data-service:7993/api/ParticipantDemographicDataService/
142142
- ExceptionFunctionURL=http://create-exception:7070/api/CreateException
143+
- ManageNemsSubscriptionUnsubscribeURL=http://manage-nems-subscription:9081/api/Unsubscribe
144+
- ManageNemsSubscriptionSubscribeURL=http://manage-nems-subscription:9081/api/ManageNemsSubscriptionSubscribeURL
145+
- RetrievePdsDemographicURL=http://etrieve-pds-demographic:8082/api/RetrievePdsDemographic
143146

144147
delete-participant:
145148
container_name: delete-participant

application/CohortManager/src/Functions/CaasIntegration/receiveCaasFile/receiveCaasFileConfig.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ public class ReceiveCaasFileConfig
1919
public string caasfolder_STORAGE { get; set; }
2020
[Required]
2121
public string inboundBlobName { get; set; }
22+
[Required]
2223
public string ServiceBusConnectionString_client_internal { get; set; }
2324
public string GetOrchestrationStatusURL { get; set; }
25+
[Required]
2426
public string ParticipantManagementTopic { get; set; }
2527
}

application/CohortManager/src/Functions/DemographicServices/ManageNemsSubscription/Extensions/CertificateExtensions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
namespace NHS.CohortManager.DemographicServices;
2+
13
using System.Security.Cryptography.X509Certificates;
24
using Azure.Identity;
35
using Azure.Security.KeyVault.Certificates;
46
using Microsoft.Extensions.Logging;
57

6-
namespace NHS.CohortManager.DemographicServices;
8+
79

810
public static class CertificateExtensions
911
{
@@ -26,15 +28,16 @@ public static async Task<X509Certificate2> LoadNemsCertificateAsync(this ManageN
2628
var certResult = await certClient.DownloadCertificateAsync(config.NemsKeyName);
2729
return certResult.Value;
2830
}
29-
31+
3032
if (!string.IsNullOrEmpty(config.NemsLocalCertPath))
3133
{
3234
logger.LogInformation("Loading NEMS certificate from local file");
3335
return !string.IsNullOrEmpty(config.NemsLocalCertPassword)
3436
? new X509Certificate2(config.NemsLocalCertPath, config.NemsLocalCertPassword)
3537
: new X509Certificate2(config.NemsLocalCertPath);
38+
3639
}
37-
40+
3841
throw new InvalidOperationException("No certificate configuration found. Please configure either KeyVaultConnectionString or NemsLocalCertPath.");
3942
}
40-
}
43+
}

application/CohortManager/src/Functions/DemographicServices/ManageNemsSubscription/ManageNemsSubscriptionConfig.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,6 @@ public class ManageNemsSubscriptionConfig
8383
/// </summary>
8484
public bool NemsBypassServerCertificateValidation { get; set; } = false;
8585

86-
/// <summary>
87-
/// Default event types to subscribe to
88-
/// </summary>
89-
public string[] NemsDefaultEventTypes { get; set; } = new[]
90-
{
91-
"pds-record-change-1"
92-
};
93-
9486
/// <summary>
9587
/// HTTP client timeout in seconds for NEMS API requests
9688
/// Default: 300 seconds (5 minutes)
@@ -101,5 +93,9 @@ public class ManageNemsSubscriptionConfig
10193
/// Custom validation to ensure either KeyVault or local cert is configured
10294
/// </summary>
10395
public bool IsValid => !string.IsNullOrEmpty(KeyVaultConnectionString) || !string.IsNullOrEmpty(NemsLocalCertPath);
96+
/// <summary>
97+
/// Bool to set the function to be in stubbed mode. Simulated responses from NEMS
98+
/// </summary>
99+
public bool IsStubbed { get; set; } = false;
104100
}
105101

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,37 @@
66
using NHS.CohortManager.DemographicServices;
77
using DataServices.Database;
88
using Microsoft.Extensions.Logging;
9+
using System.Security.Cryptography.X509Certificates;
910

1011
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
1112
var logger = loggerFactory.CreateLogger("Program");
1213

1314
var host = new HostBuilder();
1415

16+
17+
logger.LogInformation("Application Has Started");
1518
// Load configuration
1619
host.AddConfiguration<ManageNemsSubscriptionConfig>(out ManageNemsSubscriptionConfig config);
1720

1821
var nemsConfig = config;
1922

23+
X509Certificate2 nemsCertificate;
24+
25+
2026
// Load NEMS certificate up-front and inject into DI
21-
var nemsCertificate = await nemsConfig.LoadNemsCertificateAsync(logger);
27+
28+
nemsCertificate = await nemsConfig.LoadNemsCertificateAsync(logger);
29+
2230

2331
host.ConfigureFunctionsWebApplication();
2432
host.AddHttpClient()
25-
.AddNemsHttpClient()
33+
.AddNemsHttpClient(nemsConfig.IsStubbed)
2634
.ConfigureServices(services =>
2735
{
2836
// Register NEMS certificate
2937
services.AddSingleton(nemsCertificate);
3038

39+
3140
// Register NEMS subscription manager
3241
services.AddScoped<NemsSubscriptionManager>();
3342

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");

0 commit comments

Comments
 (0)