diff --git a/src/In.ProjectEKA.HipLibrary/Patient/Model/HiType.cs b/src/In.ProjectEKA.HipLibrary/Patient/Model/HiType.cs index 27e0a8bb3..740244a47 100644 --- a/src/In.ProjectEKA.HipLibrary/Patient/Model/HiType.cs +++ b/src/In.ProjectEKA.HipLibrary/Patient/Model/HiType.cs @@ -8,6 +8,7 @@ public enum HiType DischargeSummary, OPConsultation, WellnessRecord, - HealthDocumentRecord + HealthDocumentRecord, + Invoice } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Common/Constants.cs b/src/In.ProjectEKA.HipService/Common/Constants.cs index ffc801e79..3408da7e0 100644 --- a/src/In.ProjectEKA.HipService/Common/Constants.cs +++ b/src/In.ProjectEKA.HipService/Common/Constants.cs @@ -47,12 +47,10 @@ public static class Constants public static readonly string PATH_ON_LINK_CONFIRM = "/api/hiecm/user-initiated-linking/"+VERSION_V3+"/link/care-context/on-confirm"; public static readonly string PATH_CONSENT_ON_NOTIFY = "/" + CURRENT_VERSION + "/consents/hip/on-notify"; - public static readonly string PATH_HEALTH_INFORMATION_ON_REQUEST = "/" + CURRENT_VERSION + - "/health-information/hip/on-request"; - - public static readonly string PATH_HEALTH_INFORMATION_NOTIFY_GATEWAY = "/" + CURRENT_VERSION + - "/health-information/notify"; + public static readonly string PATH_HEALTH_INFORMATION_ON_REQUEST = + "/api/hiecm/data-flow/" + VERSION_V3 + "/health-information/hip/on-request"; + public static readonly string PATH_HEALTH_INFORMATION_NOTIFY_GATEWAY = "/api/hiecm/data-flow/"+ VERSION_V3 +"/health-information/notify"; public static readonly string PATH_AUTH_CONFIRM = "/" + CURRENT_VERSION + "/users/auth/confirm"; public static readonly string PATH_OPENMRS_FHIR = "ws/fhir2/R4/metadata"; diff --git a/src/In.ProjectEKA.HipService/Common/HttpRequestHelper.cs b/src/In.ProjectEKA.HipService/Common/HttpRequestHelper.cs index 9367fe740..acb900191 100644 --- a/src/In.ProjectEKA.HipService/Common/HttpRequestHelper.cs +++ b/src/In.ProjectEKA.HipService/Common/HttpRequestHelper.cs @@ -1,3 +1,6 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Converters; + namespace In.ProjectEKA.HipService.Common { using System; @@ -32,6 +35,10 @@ public static HttpRequestMessage CreateHttpRequest( ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() + }, + Converters = new List + { + new StringEnumConverter() } }); httpRequestMessage.Content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json); diff --git a/src/In.ProjectEKA.HipService/Consent/ConsentArtefactRepresentation.cs b/src/In.ProjectEKA.HipService/Consent/ConsentArtefactRepresentation.cs index e4fb4a559..379bffd84 100644 --- a/src/In.ProjectEKA.HipService/Consent/ConsentArtefactRepresentation.cs +++ b/src/In.ProjectEKA.HipService/Consent/ConsentArtefactRepresentation.cs @@ -5,17 +5,11 @@ namespace In.ProjectEKA.HipService.Consent public class ConsentArtefactRepresentation { - public ConsentArtefactRepresentation(Notification notification, DateTime timestamp, string requestId) + public ConsentArtefactRepresentation(Notification notification) { Notification = notification; - Timestamp = timestamp; - RequestId = requestId; } public Notification Notification { get; } - - public DateTime Timestamp { get; } - - public string RequestId { get; } } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Consent/ConsentNotificationController.cs b/src/In.ProjectEKA.HipService/Consent/ConsentNotificationController.cs index df775040a..75f21b462 100644 --- a/src/In.ProjectEKA.HipService/Consent/ConsentNotificationController.cs +++ b/src/In.ProjectEKA.HipService/Consent/ConsentNotificationController.cs @@ -1,5 +1,6 @@ // ReSharper disable MemberCanBePrivate.Global +using System.ComponentModel.DataAnnotations; using In.ProjectEKA.HipService.Common; namespace In.ProjectEKA.HipService.Consent @@ -34,15 +35,17 @@ public ConsentNotificationController( [HttpPost(PATH_CONSENTS_HIP)] public AcceptedResult ConsentNotification( - [FromHeader(Name = CORRELATION_ID)] string correlationId, + [FromHeader(Name = CORRELATION_ID)] string correlationId, + [FromHeader(Name = REQUEST_ID), Required] string requestId, + [FromHeader(Name = TIMESTAMP)] string timestamp, [FromBody] ConsentArtefactRepresentation consentArtefact) { - backgroundJob.Enqueue(() => StoreConsent(consentArtefact, correlationId)); + backgroundJob.Enqueue(() => StoreConsent(consentArtefact, correlationId, requestId)); return Accepted(); } [NonAction] - public async Task StoreConsent(ConsentArtefactRepresentation consentArtefact, String correlationId) + public async Task StoreConsent(ConsentArtefactRepresentation consentArtefact, String correlationId, String requestId) { var notification = consentArtefact.Notification; @@ -56,11 +59,9 @@ public async Task StoreConsent(ConsentArtefactRepresentation consentArtefact, St await consentRepository.AddAsync(consent); var cmSuffix = consent.ConsentArtefact.ConsentManager.Id; var gatewayResponse = new GatewayConsentRepresentation( - Guid.NewGuid(), - DateTime.Now.ToUniversalTime().ToString(DateTimeFormat), new ConsentUpdateResponse(ConsentUpdateStatus.OK.ToString(), notification.ConsentId), null, - new Resp(consentArtefact.RequestId)); + new Resp(requestId)); await gatewayClient.SendDataToGateway(PATH_CONSENT_ON_NOTIFY, gatewayResponse, cmSuffix, correlationId); } else @@ -71,11 +72,9 @@ public async Task StoreConsent(ConsentArtefactRepresentation consentArtefact, St var consent = await consentRepository.GetFor(notification.ConsentId); var cmSuffix = consent.ConsentArtefact.ConsentManager.Id; var gatewayResponse = new GatewayConsentRepresentation( - Guid.NewGuid(), - DateTime.Now.ToUniversalTime().ToString(DateTimeFormat), new ConsentUpdateResponse(ConsentUpdateStatus.OK.ToString(), notification.ConsentId), null, - new Resp(consentArtefact.RequestId)); + new Resp(requestId)); await gatewayClient.SendDataToGateway(PATH_CONSENT_ON_NOTIFY, gatewayResponse, cmSuffix, correlationId); } } diff --git a/src/In.ProjectEKA.HipService/Consent/Model/Notification.cs b/src/In.ProjectEKA.HipService/Consent/Model/Notification.cs index 51c91d783..a2077ad33 100644 --- a/src/In.ProjectEKA.HipService/Consent/Model/Notification.cs +++ b/src/In.ProjectEKA.HipService/Consent/Model/Notification.cs @@ -4,12 +4,13 @@ namespace In.ProjectEKA.HipService.Consent.Model public class Notification { - public Notification(ConsentArtefact consentDetail, string consentId, string signature, ConsentStatus status) + public Notification(ConsentArtefact consentDetail, string consentId, string signature, ConsentStatus status, bool grantAcknowledgement) { ConsentDetail = consentDetail; ConsentId = consentId; Signature = signature; Status = status; + GrantAcknowledgement = grantAcknowledgement; } public ConsentArtefact ConsentDetail { get; } @@ -19,5 +20,7 @@ public Notification(ConsentArtefact consentDetail, string consentId, string sign public string Signature { get; } public ConsentStatus Status { get; } + + public bool GrantAcknowledgement { get; } } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/DataFlow/DataFlowController.cs b/src/In.ProjectEKA.HipService/DataFlow/DataFlowController.cs index efefc6e2c..3fa99103f 100644 --- a/src/In.ProjectEKA.HipService/DataFlow/DataFlowController.cs +++ b/src/In.ProjectEKA.HipService/DataFlow/DataFlowController.cs @@ -1,3 +1,5 @@ +using System.ComponentModel.DataAnnotations; + namespace In.ProjectEKA.HipService.DataFlow { using System; @@ -87,16 +89,19 @@ GatewayConfiguration gatewayConfiguration [HttpPost(PATH_HEALTH_INFORMATION_HIP_REQUEST)] public AcceptedResult HealthInformationRequestFor(PatientHealthInformationRequest healthInformationRequest, [FromHeader(Name = CORRELATION_ID)] string correlationId, - [FromHeader(Name = "X-GatewayID")] string gatewayId) + [FromHeader(Name = "X-GatewayID")] string gatewayId, + [FromHeader(Name = REQUEST_ID), Required] string requestId, + [FromHeader(Name = TIMESTAMP)] string timestamp) + { logger.Log(LogLevel.Information, LogEvents.DataFlow, "Data request received"); - backgroundJob.Enqueue(() => HealthInformationOf(healthInformationRequest, gatewayId, correlationId)); + backgroundJob.Enqueue(() => HealthInformationOf(healthInformationRequest, gatewayId, correlationId, requestId)); return Accepted(); } [NonAction] public async Task HealthInformationOf(PatientHealthInformationRequest healthInformationRequest, - string gatewayId, string correlationId) + string gatewayId, string correlationId, string requestId) { try { @@ -112,12 +117,10 @@ public async Task HealthInformationOf(PatientHealthInformationRequest healthInfo if (error != null) { gatewayResponse = new GatewayDataFlowRequestResponse( - Guid.NewGuid(), - DateTime.Now.ToUniversalTime().ToString(DateTimeFormat), new DataFlowRequestResponse(healthInformationRequest.TransactionId, DataFlowRequestStatus.ERRORED.ToString()), error.Error, - new Resp(healthInformationRequest.RequestId)); + new Resp(requestId)); logger.Log(LogLevel.Error, LogEvents.DataFlow, "Response for data request {@GatewayResponse}", @@ -126,12 +129,10 @@ public async Task HealthInformationOf(PatientHealthInformationRequest healthInfo else { gatewayResponse = new GatewayDataFlowRequestResponse( - Guid.NewGuid(), - DateTime.Now.ToUniversalTime().ToString(DateTimeFormat), new DataFlowRequestResponse(healthInformationRequest.TransactionId, DataFlowRequestStatus.ACKNOWLEDGED.ToString()), null, - new Resp(healthInformationRequest.RequestId)); + new Resp(requestId)); logger.Log(LogLevel.Information, LogEvents.DataFlow, "Response for data request {@GatewayResponse}", diff --git a/src/In.ProjectEKA.HipService/DataFlow/DataFlowNotificationClient.cs b/src/In.ProjectEKA.HipService/DataFlow/DataFlowNotificationClient.cs index 35c84eb5b..8bca9da15 100644 --- a/src/In.ProjectEKA.HipService/DataFlow/DataFlowNotificationClient.cs +++ b/src/In.ProjectEKA.HipService/DataFlow/DataFlowNotificationClient.cs @@ -21,8 +21,7 @@ public DataFlowNotificationClient(GatewayClient gatewayClient) public virtual async Task NotifyGateway(string cmSuffix, DataNotificationRequest dataNotificationRequest, string correlationId) { - var notificationRequest = new GatewayDataNotificationRequest(Guid.NewGuid(), - DateTime.Now.ToUniversalTime().ToString(DateTimeFormat), + var notificationRequest = new GatewayDataNotificationRequest( new DataFlowNotificationRequest( dataNotificationRequest.TransactionId, dataNotificationRequest.ConsentId, diff --git a/src/In.ProjectEKA.HipService/DataFlow/PatientHealthInformationRequest.cs b/src/In.ProjectEKA.HipService/DataFlow/PatientHealthInformationRequest.cs index 996150cbf..2995bc5e1 100644 --- a/src/In.ProjectEKA.HipService/DataFlow/PatientHealthInformationRequest.cs +++ b/src/In.ProjectEKA.HipService/DataFlow/PatientHealthInformationRequest.cs @@ -5,19 +5,13 @@ namespace In.ProjectEKA.HipService.DataFlow public class PatientHealthInformationRequest { public PatientHealthInformationRequest(string transactionId, - string requestId, - DateTime timestamp, HIRequest hiRequest) { TransactionId = transactionId; - RequestId = requestId; - Timestamp = timestamp; HiRequest = hiRequest; } public string TransactionId { get; } - public string RequestId { get; } - public DateTime Timestamp { get; } public HIRequest HiRequest { get; } } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Gateway/Model/GatewayConsentRepresentation.cs b/src/In.ProjectEKA.HipService/Gateway/Model/GatewayConsentRepresentation.cs index e9c651ac7..b32909ce2 100644 --- a/src/In.ProjectEKA.HipService/Gateway/Model/GatewayConsentRepresentation.cs +++ b/src/In.ProjectEKA.HipService/Gateway/Model/GatewayConsentRepresentation.cs @@ -6,20 +6,15 @@ namespace In.ProjectEKA.HipService.Gateway.Model public class GatewayConsentRepresentation { - public GatewayConsentRepresentation(Guid requestId, string timestamp, - ConsentUpdateResponse acknowledgement, Error error, Resp resp) + public GatewayConsentRepresentation(ConsentUpdateResponse acknowledgement, Error error, Resp response) { - RequestId = requestId; - Timestamp = timestamp; Acknowledgement = acknowledgement; - Resp = resp; + Response = response; Error = error; } - public Guid RequestId { get; } - public string Timestamp { get; } public ConsentUpdateResponse Acknowledgement { get; } - public Resp Resp { get; } + public Resp Response { get; } public Error Error { get; } } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataFlowRequestResponse.cs b/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataFlowRequestResponse.cs index 33bbe78ab..3baa76183 100644 --- a/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataFlowRequestResponse.cs +++ b/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataFlowRequestResponse.cs @@ -7,23 +7,17 @@ namespace In.ProjectEKA.HipService.Gateway.Model public class GatewayDataFlowRequestResponse { public GatewayDataFlowRequestResponse( - Guid requestId, - string timestamp, DataFlowRequestResponse hiRequest, Error error, - Resp resp) + Resp response) { - RequestId = requestId; - Timestamp = timestamp; HiRequest = hiRequest; Error = error; - Resp = resp; + Response = response; } - - public Guid RequestId { get; } - public string Timestamp { get; } + public DataFlowRequestResponse HiRequest { get; } public Error Error { get; } - public Resp Resp { get; } + public Resp Response { get; } } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataNotificationRequest.cs b/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataNotificationRequest.cs index b31a4fdfe..6aab5d4fe 100644 --- a/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataNotificationRequest.cs +++ b/src/In.ProjectEKA.HipService/Gateway/Model/GatewayDataNotificationRequest.cs @@ -5,16 +5,11 @@ namespace In.ProjectEKA.HipService.Gateway.Model public class GatewayDataNotificationRequest { - public GatewayDataNotificationRequest(Guid requestId, string timestamp, - DataFlowNotificationRequest notification) + public GatewayDataNotificationRequest(DataFlowNotificationRequest notification) { - RequestId = requestId; - Timestamp = timestamp; Notification = notification; } - - public Guid RequestId { get; } - public string Timestamp { get; } + public DataFlowNotificationRequest Notification { get; } } } \ No newline at end of file diff --git a/test/In.ProjectEKA.HipServiceTest/Consent/Builder/TestBuilder.cs b/test/In.ProjectEKA.HipServiceTest/Consent/Builder/TestBuilder.cs index 0bb59aedb..30cda558d 100644 --- a/test/In.ProjectEKA.HipServiceTest/Consent/Builder/TestBuilder.cs +++ b/test/In.ProjectEKA.HipServiceTest/Consent/Builder/TestBuilder.cs @@ -16,7 +16,7 @@ internal static Notification Notification( return new Notification(ConsentArtefact().Generate().Build(), faker.Random.Hash(), faker.Random.Hash(), - consentStatus); + consentStatus, false); } internal static Notification RevokedNotification(string patientId) @@ -26,7 +26,7 @@ internal static Notification RevokedNotification(string patientId) return new Notification(consentArtefactBuilder.Build(), faker.Random.Hash(), faker.Random.Hash(), - ConsentStatus.REVOKED); + ConsentStatus.REVOKED, false); } diff --git a/test/In.ProjectEKA.HipServiceTest/Consent/ConsentNotificationControllerTest.cs b/test/In.ProjectEKA.HipServiceTest/Consent/ConsentNotificationControllerTest.cs index 41626532e..e09bb248e 100644 --- a/test/In.ProjectEKA.HipServiceTest/Consent/ConsentNotificationControllerTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/Consent/ConsentNotificationControllerTest.cs @@ -1,4 +1,5 @@ using Hl7.Fhir.Model; +using In.ProjectEKA.HipService.Common; using In.ProjectEKA.HipService.Gateway; namespace In.ProjectEKA.HipServiceTest.Consent @@ -68,9 +69,7 @@ private void SetupConsentNotification(ConsentStatus consentStatus) const string consentMangerId = "consentMangerId"; var notification = TestBuilder.Notification(consentStatus); var faker = new Faker(); - consentNotification = new ConsentArtefactRepresentation(notification, - DateTime.Now, - faker.Random.Hash()); + consentNotification = new ConsentArtefactRepresentation(notification); var consent = new Consent(notification.ConsentDetail.ConsentId, notification.ConsentDetail, @@ -87,7 +86,9 @@ private void SetupConsentNotification(ConsentStatus consentStatus) private void ShouldEnqueueConsentNotificationAndReturnAccepted() { var correlationId = Uuid.Generate().ToString(); - var result = consentNotificationController.ConsentNotification(correlationId, consentNotification); + var requestId = Uuid.Generate().ToString(); + var timestamp = DateTime.Now.ToString(); + var result = consentNotificationController.ConsentNotification(correlationId, requestId, timestamp, consentNotification); backgroundJobClient.Verify(client => client.Create( It.Is(job => job.Method.Name == "StoreConsent" && job.Args[0] == consentNotification), @@ -100,7 +101,8 @@ private void ShouldEnqueueConsentNotificationAndReturnAccepted() async void ShouldStoreConsentArtefact() { var correlationId = Uuid.Generate().ToString(); - await consentNotificationController.StoreConsent(consentNotification,correlationId); + var requestId = Uuid.Generate().ToString(); + await consentNotificationController.StoreConsent(consentNotification,correlationId,requestId); consentRepository.Verify(cr => cr.AddAsync( It.Is(c => verifyActualConsentEqualsExpected(c))), @@ -117,9 +119,10 @@ async void ShouldStoreConsentArtefact() async void ShouldUpdateConsentArtefact(ConsentStatus consentStatus) { var correlationId = Uuid.Generate().ToString(); + var requestId = Uuid.Generate().ToString(); SetupConsentNotification(consentStatus); - await consentNotificationController.StoreConsent(consentNotification,correlationId); + await consentNotificationController.StoreConsent(consentNotification,correlationId,requestId); consentRepository.Verify(cr => cr.UpdateAsync( consentNotification.Notification.ConsentId, @@ -132,16 +135,17 @@ async void ShouldUpdateConsentArtefact(ConsentStatus consentStatus) async void ShouldInvokeGatewayWhenRevokingConsent() { var correlationId = Uuid.Generate().ToString(); + var requestId = Uuid.Generate().ToString(); SetupConsentNotification(ConsentStatus.REVOKED); - await consentNotificationController.StoreConsent(consentNotification,correlationId); + await consentNotificationController.StoreConsent(consentNotification,correlationId,requestId); gatewayClient.Verify(g => g.SendDataToGateway( - "/v0.5/consents/hip/on-notify", + Constants.PATH_CONSENT_ON_NOTIFY, It.Is( c => c.Acknowledgement.ConsentId == consentNotification.Notification.ConsentId - && c.Resp.RequestId == consentNotification.RequestId), + && c.Response.RequestId == requestId), consentNotification.Notification.ConsentDetail.ConsentManager.Id, correlationId), Times.Once); diff --git a/test/In.ProjectEKA.HipServiceTest/DataFlow/PatientDataFlowControllerTest.cs b/test/In.ProjectEKA.HipServiceTest/DataFlow/PatientDataFlowControllerTest.cs index 97431369d..598ebcef8 100644 --- a/test/In.ProjectEKA.HipServiceTest/DataFlow/PatientDataFlowControllerTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/DataFlow/PatientDataFlowControllerTest.cs @@ -55,14 +55,14 @@ private void ShouldEnqueueDataFlowRequestAndReturnAccepted() healthInformationRequest.DateRange, healthInformationRequest.DataPushUrl, healthInformationRequest.KeyMaterial); - var request = new PatientHealthInformationRequest(transactionId, requestId, It.IsAny(), hiRequest); + var request = new PatientHealthInformationRequest(transactionId, hiRequest); var expectedResponse = new HealthInformationTransactionResponse(transactionId); var correlationId = Uuid.Generate().ToString(); dataFlow.Setup(d => d.HealthInformationRequestFor(healthInformationRequest, gatewayId, correlationId)) .ReturnsAsync( new Tuple(expectedResponse, null)); - var response = patientDataFlowController.HealthInformationRequestFor(request, gatewayId, correlationId ); + var response = patientDataFlowController.HealthInformationRequestFor(request, gatewayId, correlationId, requestId, It.IsAny().ToString() ); backgroundJobClient.Verify(client => client.Create( It.Is(job => job.Method.Name == "HealthInformationOf" && job.Args[0] == request), It.IsAny())); @@ -81,7 +81,7 @@ private async void ShouldSendDataFlowRequestToGateway() healthInformationRequest.DateRange, healthInformationRequest.DataPushUrl, healthInformationRequest.KeyMaterial); - var request = new PatientHealthInformationRequest(transactionId, requestId, It.IsAny(), hiRequest); + var request = new PatientHealthInformationRequest(transactionId, hiRequest); var expectedResponse = new HealthInformationTransactionResponse(transactionId); var correlationId = Uuid.Generate().ToString(); dataFlow.Setup(d => d.HealthInformationRequestFor(healthInformationRequest, gatewayId, correlationId)) @@ -92,7 +92,7 @@ private async void ShouldSendDataFlowRequestToGateway() client.SendDataToGateway(PATH_HEALTH_INFORMATION_ON_REQUEST, It.IsAny(), "ncg", correlationId)); - await patientDataFlowController.HealthInformationOf(request, correlationId, gatewayId); + await patientDataFlowController.HealthInformationOf(request, correlationId, gatewayId, requestId); gatewayClient.Verify(); dataFlow.Verify();