-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathReceiveServiceNowMessageFunction.cs
More file actions
153 lines (131 loc) · 7.06 KB
/
ReceiveServiceNowMessageFunction.cs
File metadata and controls
153 lines (131 loc) · 7.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
namespace NHS.CohortManager.ServiceNowIntegrationService;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Common;
using System.Text.Json;
using System.ComponentModel.DataAnnotations;
using NHS.CohortManager.ServiceNowIntegrationService.Models;
using Model;
using Microsoft.Extensions.Options;
using DataServices.Client;
using Model.Enums;
public class ReceiveServiceNowMessageFunction
{
private readonly ILogger<ReceiveServiceNowMessageFunction> _logger;
private readonly ICreateResponse _createResponse;
private readonly IQueueClient _queueClient;
private readonly ServiceNowMessageHandlerConfig _config;
private readonly IDataServiceClient<ServicenowCase> _serviceNowCaseClient;
private readonly IServiceNowClient _serviceNowClient;
private readonly IAuditLogClient _auditLogClient;
public ReceiveServiceNowMessageFunction(ILogger<ReceiveServiceNowMessageFunction> logger, ICreateResponse createResponse,
IQueueClient queueClient, IOptions<ServiceNowMessageHandlerConfig> config, IDataServiceClient<ServicenowCase> serviceNowCaseClient,
IServiceNowClient serviceNowClient, IAuditLogClient auditLogClient)
{
_logger = logger;
_createResponse = createResponse;
_queueClient = queueClient;
_config = config.Value;
_auditLogClient = auditLogClient;
_serviceNowCaseClient = serviceNowCaseClient;
_serviceNowClient = serviceNowClient;
}
/// <summary>
/// Azure Function to receive and validate an incoming ServiceNow message. If the message is valid, it will be sent to an Azure Service Bus Topic.
/// </summary>
/// <param name="req">The HTTP request containing the incoming message payload.</param>
/// <returns>
/// An <see cref="HttpResponseData"/> object representing the HTTP response.
/// - Returns a 202 status code if the request is successful.
/// - Returns a 400 status code if the request is a bad request.
/// </returns>
[Function("ReceiveServiceNowMessage")]
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "servicenow/receive")] HttpRequestData req)
{
ReceiveServiceNowMessageRequestBody? requestBody;
try
{
requestBody = await JsonSerializer.DeserializeAsync<ReceiveServiceNowMessageRequestBody>(req.Body);
if (requestBody == null)
{
_logger.LogError("Request body deserialised to null");
return _createResponse.CreateHttpResponse(HttpStatusCode.BadRequest, req);
}
await _auditLogClient.AddAsync(new ParticipantAuditMessage
{
NhsNumber = requestBody.VariableData.NhsNumber,
Source = AuditSource.ManualAdd,
RecordSourceDesc = $"ServiceNow case: {requestBody.ServiceNowCaseNumber}",
CreatedBy = nameof(ReceiveServiceNowMessageFunction),
ScreeningId = (int)ServiceProvider.BSS,
RequestSnapshot = requestBody
});
var validationContext = new ValidationContext(requestBody.VariableData);
var validationResult = new List<ValidationResult>();
bool isVariableDataValid = Validator.TryValidateObject(requestBody.VariableData, validationContext, validationResult, true);
if (string.IsNullOrWhiteSpace(requestBody.ServiceNowCaseNumber) || !isVariableDataValid)
{
_logger.LogError("Request body failed validation");
return _createResponse.CreateHttpResponse(HttpStatusCode.BadRequest, req);
}
if (!ValidationHelper.ValidateNHSNumber(requestBody.VariableData.NhsNumber))
{
_logger.LogWarning("Invalid NHS Number checksum for ServiceNow case {ServiceNowCaseId}. NHS Number failed validation.", requestBody.ServiceNowCaseNumber);
var invalidNhsNumberMessage = string.Format(ServiceNowMessageTemplates.UnableToAddParticipantMessageTemplate, requestBody.ServiceNowCaseNumber);
var resolutionResponse = await _serviceNowClient.SendResolution(requestBody.ServiceNowCaseNumber, invalidNhsNumberMessage);
if (resolutionResponse == null || !resolutionResponse.IsSuccessStatusCode)
{
_logger.LogError("Failed to send resolution to ServiceNow for invalid NHS Number. CaseNumber: {ServiceNowCaseId}", requestBody.ServiceNowCaseNumber);
}
return _createResponse.CreateHttpResponse(HttpStatusCode.BadRequest, req);
}
var nhsNumber = long.Parse(requestBody.VariableData.NhsNumber);
var serviceNowCase = new ServicenowCase
{
Id = Guid.NewGuid(),
ServicenowId = requestBody.ServiceNowCaseNumber,
NhsNumber = nhsNumber,
Status = ServiceNowStatus.New,
RecordInsertDatetime = DateTime.UtcNow
};
var addSuccess = await _serviceNowCaseClient.Add(serviceNowCase);
if (!addSuccess)
{
_logger.LogError("Failed to save the ServiceNow case to the database. CaseNumber: {CaseNumber}", requestBody.ServiceNowCaseNumber);
return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req);
}
var participant = new ServiceNowParticipant
{
ScreeningId = (int)ServiceProvider.BSS,
NhsNumber = nhsNumber,
FirstName = requestBody.VariableData.FirstName,
FamilyName = requestBody.VariableData.FamilyName,
DateOfBirth = requestBody.VariableData.DateOfBirth,
ServiceNowCaseNumber = requestBody.ServiceNowCaseNumber,
BsoCode = requestBody.VariableData.BsoCode,
ReasonForAdding = requestBody.VariableData.ReasonForAdding,
RequiredGpCode = requestBody.VariableData.RequiredGpCode
};
var success = await _queueClient.AddAsync(participant, _config.ServiceNowParticipantManagementTopic);
if (!success)
{
_logger.LogError("Failed to send Participant from ServiceNow to Service Bus Topic. CaseNumber: {CaseNumber}", requestBody.ServiceNowCaseNumber);
return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req);
}
}
catch (JsonException ex)
{
_logger.LogError(ex, "Failed to deserialize json request body to type {Type}", nameof(ReceiveServiceNowMessageRequestBody));
return _createResponse.CreateHttpResponse(HttpStatusCode.BadRequest, req);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occured");
return _createResponse.CreateHttpResponse(HttpStatusCode.InternalServerError, req);
}
return _createResponse.CreateHttpResponse(HttpStatusCode.Accepted, req);
}
}