From 7afa4803ec5d622c000c7926144e9ae39b158bd1 Mon Sep 17 00:00:00 2001 From: SanoferSameera Date: Thu, 25 Apr 2024 22:59:29 +0530 Subject: [PATCH 1/2] BAH-3773 | Add. link patient abha identifier after successful linking --- .github/workflows/ci.yml | 1 + .../Common/Constants.cs | 1 + .../Discovery/DiscoveryReqMap.cs | 14 ++++++++ .../Discovery/PatientController.cs | 11 +++++- .../Link/LinkPatient.cs | 34 +++++++++++++++++-- .../Link/Model/PatientAbhaIdentifier.cs | 14 ++++++++ .../OpenMrs/IOpenMrsClient.cs | 2 ++ .../OpenMrs/OpenMrsClient.cs | 18 ++++++++++ .../Discovery/PatientControllerTest.cs | 1 + .../Link/LinkControllerTest.cs | 2 +- .../Link/LinkPatientTest.cs | 16 ++++++++- 11 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs create mode 100644 src/In.ProjectEKA.HipService/Link/Model/PatientAbhaIdentifier.cs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7df9e0623..5093132cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: branches: - master - 'release-*' + - BAH-3773 tags: - '[0-9]+.[0-9]+.[0-9]+' jobs: diff --git a/src/In.ProjectEKA.HipService/Common/Constants.cs b/src/In.ProjectEKA.HipService/Common/Constants.cs index 52c4a52ce..f791e5338 100644 --- a/src/In.ProjectEKA.HipService/Common/Constants.cs +++ b/src/In.ProjectEKA.HipService/Common/Constants.cs @@ -39,6 +39,7 @@ public static class Constants public static readonly string PATH_OPENMRS_HITYPE = "ws/rest/v1/hip/"; public static readonly string CONFIG_KEY = "OpenMrs"; public static readonly string PATH_OPENMRS_LGD_CODE = "ws/rest/v1/hip/lgdCode"; + public static readonly string PATH_OPENMRS_UPDATE_IDENTIFIER = "ws/rest/v1/hip/existingPatients/update"; public const string CORRELATION_ID = "CORRELATION-ID"; public const string PATH_PATIENT_PROFILE_ON_SHARE = "/" + CURRENT_VERSION + "/patients/profile/on-share"; diff --git a/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs b/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs new file mode 100644 index 000000000..14b1ba805 --- /dev/null +++ b/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using In.ProjectEKA.HipLibrary.Patient.Model; +using In.ProjectEKA.HipService.Common.Model; +using In.ProjectEKA.HipService.Link.Model; +using In.ProjectEKA.HipService.UserAuth.Model; +using Microsoft.AspNetCore.Http; + +namespace In.ProjectEKA.HipService.Discovery +{ + public static class DiscoveryReqMap { + public static Dictionary AbhaIdentifierMap = new Dictionary(); + } +} \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Discovery/PatientController.cs b/src/In.ProjectEKA.HipService/Discovery/PatientController.cs index f65819a07..e3053c882 100644 --- a/src/In.ProjectEKA.HipService/Discovery/PatientController.cs +++ b/src/In.ProjectEKA.HipService/Discovery/PatientController.cs @@ -1,4 +1,6 @@ -namespace In.ProjectEKA.HipService.Discovery +using System.Linq; + +namespace In.ProjectEKA.HipService.Discovery { using System; using System.Net; @@ -12,6 +14,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; + using static In.ProjectEKA.HipService.Discovery.DiscoveryReqMap; using Common; @@ -71,6 +74,12 @@ public async Task GetPatientCareContext(DiscoveryRequest request, string correla new DiscoveryResponse(request.RequestId, error == null ? HttpStatusCode.OK : HttpStatusCode.NotFound, error == null ? SuccessMessage : ErrorMessage)); + var abhaNumberIdentifier = request.Patient?.VerifiedIdentifiers.FirstOrDefault(id => id.Type == IdentifierType.NDHM_HEALTH_NUMBER); + if (!AbhaIdentifierMap.ContainsKey(patientId)) + { + AbhaIdentifierMap.Add(patientId, abhaNumberIdentifier?.Value); + } + Log.Information("new GatewayDiscoveryRepresentation" + gatewayDiscoveryRepresentation); Log.Information("Sending data to gateway"); Log.Information($"Response about to be send for {request.RequestId} with {@response?.Patient}"); diff --git a/src/In.ProjectEKA.HipService/Link/LinkPatient.cs b/src/In.ProjectEKA.HipService/Link/LinkPatient.cs index 54a64a4ca..a3134fbb8 100644 --- a/src/In.ProjectEKA.HipService/Link/LinkPatient.cs +++ b/src/In.ProjectEKA.HipService/Link/LinkPatient.cs @@ -1,3 +1,7 @@ +using In.ProjectEKA.HipService.OpenMrs; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + namespace In.ProjectEKA.HipService.Link { using System; @@ -11,7 +15,8 @@ namespace In.ProjectEKA.HipService.Link using Logger; using Microsoft.Extensions.Options; using Model; - + using static In.ProjectEKA.HipService.Discovery.DiscoveryReqMap; + public class LinkPatient { private readonly IDiscoveryRequestRepository discoveryRequestRepository; @@ -20,6 +25,7 @@ public class LinkPatient private readonly IPatientRepository patientRepository; private readonly IPatientVerification patientVerification; private readonly ReferenceNumberGenerator referenceNumberGenerator; + private readonly IOpenMrsClient openMrsClient; public LinkPatient( ILinkPatientRepository linkPatientRepository, @@ -27,7 +33,8 @@ public LinkPatient( IPatientVerification patientVerification, ReferenceNumberGenerator referenceNumberGenerator, IDiscoveryRequestRepository discoveryRequestRepository, - IOptions otpService) + IOptions otpService, + IOpenMrsClient openMrsClient) { this.linkPatientRepository = linkPatientRepository; this.patientRepository = patientRepository; @@ -35,6 +42,7 @@ public LinkPatient( this.referenceNumberGenerator = referenceNumberGenerator; this.discoveryRequestRepository = discoveryRequestRepository; this.otpService = otpService; + this.openMrsClient = openMrsClient; } public virtual async Task> LinkPatients( @@ -178,7 +186,29 @@ private async Task SaveLinkedAccounts(LinkEnquires linkEnquires,string pat (patientUuid!=null?Guid.Parse(patientUuid): Guid.Empty) ) .ConfigureAwait(false); + LinkAbhaIdentifier(patientUuid, linkEnquires.ConsentManagerUserId); return linkedAccount.HasValue; + + } + + private async void LinkAbhaIdentifier(string patientUuid, string abhaAddress) + { + var abhaNumber = AbhaIdentifierMap[abhaAddress]; + var json = JsonConvert.SerializeObject(new PatientAbhaIdentifier(abhaNumber, abhaAddress), new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy() + } + }); + var resp = await openMrsClient.PostAsync( + $"{Constants.PATH_OPENMRS_UPDATE_IDENTIFIER}/{patientUuid}", + json + ) + .ConfigureAwait(false); + if (!resp.IsSuccessStatusCode) + Log.Error("Errored in linking the abha identifier to the patient"); } public async Task SaveInitiatedLinkRequest(string requestId, string transactionId, diff --git a/src/In.ProjectEKA.HipService/Link/Model/PatientAbhaIdentifier.cs b/src/In.ProjectEKA.HipService/Link/Model/PatientAbhaIdentifier.cs new file mode 100644 index 000000000..c86705329 --- /dev/null +++ b/src/In.ProjectEKA.HipService/Link/Model/PatientAbhaIdentifier.cs @@ -0,0 +1,14 @@ +namespace In.ProjectEKA.HipService.Link.Model +{ + public class PatientAbhaIdentifier + { + public string abhaNumber { get; } + public string abhaAddress { get; } + + public PatientAbhaIdentifier(string abhaNumber, string abhaAddress) + { + this.abhaNumber = abhaNumber; + this.abhaAddress = abhaAddress; + } + } +} \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/OpenMrs/IOpenMrsClient.cs b/src/In.ProjectEKA.HipService/OpenMrs/IOpenMrsClient.cs index 095955f16..c80abdb71 100644 --- a/src/In.ProjectEKA.HipService/OpenMrs/IOpenMrsClient.cs +++ b/src/In.ProjectEKA.HipService/OpenMrs/IOpenMrsClient.cs @@ -6,5 +6,7 @@ namespace In.ProjectEKA.HipService.OpenMrs public interface IOpenMrsClient { Task GetAsync(string openMrsUrl); + + Task PostAsync(string openMrsUrl, string jsonContent); } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/OpenMrs/OpenMrsClient.cs b/src/In.ProjectEKA.HipService/OpenMrs/OpenMrsClient.cs index f6c22a9f6..f629de1c3 100644 --- a/src/In.ProjectEKA.HipService/OpenMrs/OpenMrsClient.cs +++ b/src/In.ProjectEKA.HipService/OpenMrs/OpenMrsClient.cs @@ -35,6 +35,24 @@ public async Task GetAsync(string openMrsUrl) return responseMessage; } + + public async Task PostAsync(string openMrsUrl, string jsonContent) + { + var httpContent = new StringContent(jsonContent, Encoding.UTF8, "application/json"); + + var responseMessage = await httpClient.PostAsync(Path.Join(configuration.Url, openMrsUrl), httpContent); + + if (!responseMessage.IsSuccessStatusCode) + { + var error = await responseMessage.Content.ReadAsStringAsync(); + Log.Error( + $"Failure in posting the data into OpenMrs with status code {responseMessage.StatusCode}" + + $" {error}"); + throw new OpenMrsConnectionException(); + } + + return responseMessage; + } private void SettingUpHeaderAuthorization() { diff --git a/test/In.ProjectEKA.HipServiceTest/Discovery/PatientControllerTest.cs b/test/In.ProjectEKA.HipServiceTest/Discovery/PatientControllerTest.cs index 85ca2cd68..dceb076dc 100644 --- a/test/In.ProjectEKA.HipServiceTest/Discovery/PatientControllerTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/Discovery/PatientControllerTest.cs @@ -378,6 +378,7 @@ private static void GivenAPatientStartedANewDiscoveryRequest(User user, out Disc { discoveryRequest = new DiscoveryRequestPayloadBuilder() .FromUser(user) + .WithVerifiedIdentifiers(IdentifierType.NDHM_HEALTH_NUMBER, "12345678910") .WithRequestId("aRequestId") .WithTransactionId("aTransactionId") .RequestedOn(new DateTime(2020, 06, 14)) diff --git a/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs b/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs index 81f910ab7..21c5eef0e 100644 --- a/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs @@ -25,7 +25,7 @@ public class LinkControllerTest public LinkControllerTest() { - link = new Mock(MockBehavior.Strict, null, null, null, null, null, null); + link = new Mock(MockBehavior.Strict, null, null, null, null, null, null, null); discoveryRequestRepository = new Mock(); var gatewayClient = new Mock(MockBehavior.Strict, null, null); diff --git a/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs b/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs index ecada8c5f..cbd724bba 100644 --- a/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs @@ -1,3 +1,7 @@ +using System.Net; +using System.Net.Http; +using In.ProjectEKA.HipService.OpenMrs; + namespace In.ProjectEKA.HipServiceTest.Link { using System; @@ -44,6 +48,7 @@ public class LinkPatientTest private readonly Mock patientRepository = new Mock(); private readonly Mock patientVerification = new Mock(); private readonly Mock guidGenerator = new Mock(); + private readonly Mock openmrsClient = new Mock(); public LinkPatientTest() { @@ -54,7 +59,8 @@ public LinkPatientTest() patientVerification.Object, guidGenerator.Object, discoveryRequestRepository.Object, - otpServiceConfigurations); + otpServiceConfigurations, + openmrsClient.Object); } [Fact] @@ -211,6 +217,7 @@ private async void SuccessLinkPatientForValidOtp() var testLinkedAccounts = new LinkedAccounts(testLinkRequest.PatientReferenceNumber, testLinkRequest.LinkReferenceNumber, testLinkRequest.ConsentManagerUserId, It.IsAny(), new[] {programRefNo}.ToList(),It.IsAny()); + DiscoveryReqMap.AbhaIdentifierMap.Add(testLinkRequest.ConsentManagerUserId, "1234567891011" ); patientVerification.Setup(e => e.Verify(sessionId, otpToken)) .ReturnsAsync((OtpMessage) null); linkRepository.Setup(e => e.GetPatientFor(sessionId)) @@ -224,6 +231,13 @@ private async void SuccessLinkPatientForValidOtp() It.IsAny() )) .ReturnsAsync(Option.Some(testLinkedAccounts)); + openmrsClient + .Setup(x => x.PostAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK + }) + .Verifiable(); var expectedLinkResponse = new PatientLinkConfirmationRepresentation( new LinkConfirmationRepresentation( testPatient.Identifier, From 78bc1dd0dc942dc5fe3e8c1f77e8b88de9747545 Mon Sep 17 00:00:00 2001 From: SanoferSameera Date: Fri, 3 May 2024 15:58:38 +0530 Subject: [PATCH 2/2] BAH-3773 | Add. store patient demographics after linking --- .github/workflows/ci.yml | 1 - .../Discovery/DiscoveryReqMap.cs | 7 +--- .../Discovery/PatientController.cs | 5 ++- .../Link/LinkPatient.cs | 32 ++++++++++++++----- .../Link/LinkControllerTest.cs | 2 +- .../Link/LinkPatientTest.cs | 15 +++++++-- 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5093132cf..7df9e0623 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,6 @@ on: branches: - master - 'release-*' - - BAH-3773 tags: - '[0-9]+.[0-9]+.[0-9]+' jobs: diff --git a/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs b/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs index 14b1ba805..3e792a567 100644 --- a/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs +++ b/src/In.ProjectEKA.HipService/Discovery/DiscoveryReqMap.cs @@ -1,14 +1,9 @@ -using System; using System.Collections.Generic; using In.ProjectEKA.HipLibrary.Patient.Model; -using In.ProjectEKA.HipService.Common.Model; -using In.ProjectEKA.HipService.Link.Model; -using In.ProjectEKA.HipService.UserAuth.Model; -using Microsoft.AspNetCore.Http; namespace In.ProjectEKA.HipService.Discovery { public static class DiscoveryReqMap { - public static Dictionary AbhaIdentifierMap = new Dictionary(); + public static Dictionary PatientInfoMap = new Dictionary(); } } \ No newline at end of file diff --git a/src/In.ProjectEKA.HipService/Discovery/PatientController.cs b/src/In.ProjectEKA.HipService/Discovery/PatientController.cs index e3053c882..7aefbfbb8 100644 --- a/src/In.ProjectEKA.HipService/Discovery/PatientController.cs +++ b/src/In.ProjectEKA.HipService/Discovery/PatientController.cs @@ -74,10 +74,9 @@ public async Task GetPatientCareContext(DiscoveryRequest request, string correla new DiscoveryResponse(request.RequestId, error == null ? HttpStatusCode.OK : HttpStatusCode.NotFound, error == null ? SuccessMessage : ErrorMessage)); - var abhaNumberIdentifier = request.Patient?.VerifiedIdentifiers.FirstOrDefault(id => id.Type == IdentifierType.NDHM_HEALTH_NUMBER); - if (!AbhaIdentifierMap.ContainsKey(patientId)) + if (!PatientInfoMap.ContainsKey(patientId)) { - AbhaIdentifierMap.Add(patientId, abhaNumberIdentifier?.Value); + PatientInfoMap.Add(patientId, request.Patient); } Log.Information("new GatewayDiscoveryRepresentation" + gatewayDiscoveryRepresentation); diff --git a/src/In.ProjectEKA.HipService/Link/LinkPatient.cs b/src/In.ProjectEKA.HipService/Link/LinkPatient.cs index a3134fbb8..0186b4054 100644 --- a/src/In.ProjectEKA.HipService/Link/LinkPatient.cs +++ b/src/In.ProjectEKA.HipService/Link/LinkPatient.cs @@ -1,4 +1,6 @@ using In.ProjectEKA.HipService.OpenMrs; +using In.ProjectEKA.HipService.UserAuth; +using In.ProjectEKA.HipService.UserAuth.Model; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -26,6 +28,7 @@ public class LinkPatient private readonly IPatientVerification patientVerification; private readonly ReferenceNumberGenerator referenceNumberGenerator; private readonly IOpenMrsClient openMrsClient; + private readonly IUserAuthService userAuthService; public LinkPatient( ILinkPatientRepository linkPatientRepository, @@ -34,7 +37,7 @@ public LinkPatient( ReferenceNumberGenerator referenceNumberGenerator, IDiscoveryRequestRepository discoveryRequestRepository, IOptions otpService, - IOpenMrsClient openMrsClient) + IOpenMrsClient openMrsClient, IUserAuthService userAuthService) { this.linkPatientRepository = linkPatientRepository; this.patientRepository = patientRepository; @@ -43,6 +46,7 @@ public LinkPatient( this.discoveryRequestRepository = discoveryRequestRepository; this.otpService = otpService; this.openMrsClient = openMrsClient; + this.userAuthService = userAuthService; } public virtual async Task> LinkPatients( @@ -165,9 +169,13 @@ public virtual async Task SaveLinkedAccounts(LinkEnquires linkEnquires,string pat (patientUuid!=null?Guid.Parse(patientUuid): Guid.Empty) ) .ConfigureAwait(false); - LinkAbhaIdentifier(patientUuid, linkEnquires.ConsentManagerUserId); + return linkedAccount.HasValue; } private async void LinkAbhaIdentifier(string patientUuid, string abhaAddress) { - var abhaNumber = AbhaIdentifierMap[abhaAddress]; - var json = JsonConvert.SerializeObject(new PatientAbhaIdentifier(abhaNumber, abhaAddress), new JsonSerializerSettings + var patient = PatientInfoMap[abhaAddress]; + var abhaNumberIdentifier = patient?.VerifiedIdentifiers.FirstOrDefault(id => id.Type == IdentifierType.NDHM_HEALTH_NUMBER); + var json = JsonConvert.SerializeObject(new PatientAbhaIdentifier(abhaNumberIdentifier?.Value, abhaAddress), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, ContractResolver = new DefaultContractResolver @@ -207,8 +216,15 @@ private async void LinkAbhaIdentifier(string patientUuid, string abhaAddress) json ) .ConfigureAwait(false); - if (!resp.IsSuccessStatusCode) + if (resp.IsSuccessStatusCode) + { + var ndhmDemographics = new NdhmDemographics(abhaAddress, patient.Name, patient.Gender.ToString(), patient.YearOfBirth.ToString(), patient.VerifiedIdentifiers.FirstOrDefault(id => id.Type == IdentifierType.MOBILE)?.Value); + await userAuthService.Dump(ndhmDemographics); + } + else + { Log.Error("Errored in linking the abha identifier to the patient"); + } } public async Task SaveInitiatedLinkRequest(string requestId, string transactionId, diff --git a/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs b/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs index 21c5eef0e..19aea6e60 100644 --- a/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/Link/LinkControllerTest.cs @@ -25,7 +25,7 @@ public class LinkControllerTest public LinkControllerTest() { - link = new Mock(MockBehavior.Strict, null, null, null, null, null, null, null); + link = new Mock(MockBehavior.Strict, null, null, null, null, null, null, null, null); discoveryRequestRepository = new Mock(); var gatewayClient = new Mock(MockBehavior.Strict, null, null); diff --git a/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs b/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs index cbd724bba..d27b69564 100644 --- a/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs +++ b/test/In.ProjectEKA.HipServiceTest/Link/LinkPatientTest.cs @@ -1,6 +1,7 @@ using System.Net; using System.Net.Http; using In.ProjectEKA.HipService.OpenMrs; +using In.ProjectEKA.HipService.UserAuth; namespace In.ProjectEKA.HipServiceTest.Link { @@ -49,6 +50,7 @@ public class LinkPatientTest private readonly Mock patientVerification = new Mock(); private readonly Mock guidGenerator = new Mock(); private readonly Mock openmrsClient = new Mock(); + private readonly Mock userAuthService = new Mock(); public LinkPatientTest() { @@ -60,7 +62,8 @@ public LinkPatientTest() guidGenerator.Object, discoveryRequestRepository.Object, otpServiceConfigurations, - openmrsClient.Object); + openmrsClient.Object, + userAuthService.Object); } [Fact] @@ -217,7 +220,15 @@ private async void SuccessLinkPatientForValidOtp() var testLinkedAccounts = new LinkedAccounts(testLinkRequest.PatientReferenceNumber, testLinkRequest.LinkReferenceNumber, testLinkRequest.ConsentManagerUserId, It.IsAny(), new[] {programRefNo}.ToList(),It.IsAny()); - DiscoveryReqMap.AbhaIdentifierMap.Add(testLinkRequest.ConsentManagerUserId, "1234567891011" ); + var patientEnquiry = + new PatientEnquiry( + "id", verifiedIdentifiers: new List() + { + new Identifier(IdentifierType.MOBILE, "9999999999"), + new Identifier(IdentifierType.NDHM_HEALTH_NUMBER, "123456718910") + }, unverifiedIdentifiers: null, + "name", HipLibrary.Patient.Model.Gender.M, 2000); + DiscoveryReqMap.PatientInfoMap.Add(testLinkRequest.ConsentManagerUserId, patientEnquiry); patientVerification.Setup(e => e.Verify(sessionId, otpToken)) .ReturnsAsync((OtpMessage) null); linkRepository.Setup(e => e.GetPatientFor(sessionId))