diff --git a/hub-prime/src/main/java/org/techbd/orchestrate/csv/CsvOrchestrationEngine.java b/hub-prime/src/main/java/org/techbd/orchestrate/csv/CsvOrchestrationEngine.java index 3daa13434f6..0431db2070c 100644 --- a/hub-prime/src/main/java/org/techbd/orchestrate/csv/CsvOrchestrationEngine.java +++ b/hub-prime/src/main/java/org/techbd/orchestrate/csv/CsvOrchestrationEngine.java @@ -296,6 +296,10 @@ private void saveScreeningGroup(final String groupInteractionId, final HttpServl initRIHR.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE); initRIHR.setCsvZipFileName(file.getOriginalFilename()); initRIHR.setSourceHubInteractionId(interactionId); + final InetAddress localHost = InetAddress.getLocalHost(); + final String ipAddress = localHost.getHostAddress(); + initRIHR.setClientIpAddress(ipAddress); + initRIHR.setUserAgent(request.getHeader("User-Agent")); for (final FileDetail fileDetail : fileDetailList) { switch (fileDetail.fileType()) { case FileType.DEMOGRAPHIC_DATA -> { @@ -384,7 +388,8 @@ private void saveValidationResults(final Map validationResults, final var initRIHR = new RegisterInteractionHttpRequest(); try { initRIHR.setInteractionId(groupInteractionId); - initRIHR.setGroupHubInteractionId(masterInteractionId); + initRIHR.setGroupHubInteractionId(groupInteractionId); + initRIHR.setSourceHubInteractionId(masterInteractionId); initRIHR.setInteractionKey(request.getRequestURI()); initRIHR.setNature((JsonNode) Configuration.objectMapper.valueToTree( Map.of("nature", "CSV Validation Result", "tenant_id", diff --git a/hub-prime/src/main/java/org/techbd/service/CsvBundleProcessorService.java b/hub-prime/src/main/java/org/techbd/service/CsvBundleProcessorService.java index f34c0bc7a05..57c39e05a20 100644 --- a/hub-prime/src/main/java/org/techbd/service/CsvBundleProcessorService.java +++ b/hub-prime/src/main/java/org/techbd/service/CsvBundleProcessorService.java @@ -23,6 +23,7 @@ import org.techbd.model.csv.QeAdminData; import org.techbd.model.csv.ScreeningObservationData; import org.techbd.model.csv.ScreeningProfileData; +import org.techbd.service.constants.SourceType; import org.techbd.service.converters.csv.CsvToFhirConverter; import org.techbd.service.http.hub.prime.api.FHIRService; import org.techbd.udi.UdiPrimeJpaConfig; @@ -134,7 +135,7 @@ private void saveConvertedFHIR(boolean isValid, String masterInteractionId, Stri initRIHR.setCreatedAt(forwardedAt); initRIHR.setCreatedBy(CsvService.class.getName()); initRIHR.setFromState(isValid ? "VALIDATION SUCCESS" : "VALIDATION FAILED"); - initRIHR.setFromState(isPayloadInstanceOfBundle(payload) ? "CONVERTED_TO_FHIR" : "FHIR_CONVERSION_FAILED"); + initRIHR.setToState(isPayloadInstanceOfBundle(payload) ? "CONVERTED_TO_FHIR" : "FHIR_CONVERSION_FAILED"); final var provenance = "%s.saveConvertedFHIR".formatted(CsvBundleProcessorService.class.getName()); initRIHR.setProvenance(provenance); initRIHR.setCsvGroupId(groupKey); @@ -246,7 +247,7 @@ private List processScreeningProfileData(String groupKey, results.add(fhirService.processBundle( bundle, tenantId, null, null, null, null, null, Boolean.toString(false), false, - false, false, request, response, null, true, null,interactionId,groupInteractionId,masterInteractionId)); + false, false, request, response, null, true, null,interactionId,groupInteractionId,masterInteractionId,SourceType.CSV.name())); } else { results.add(createOperationOutcomeForError(masterInteractionId, interactionId, profile.getPatientMrIdValue(), new Exception("Bundle not created"))); diff --git a/hub-prime/src/main/java/org/techbd/service/CsvService.java b/hub-prime/src/main/java/org/techbd/service/CsvService.java index eea2d3b7fe9..2bb04d2d4a8 100644 --- a/hub-prime/src/main/java/org/techbd/service/CsvService.java +++ b/hub-prime/src/main/java/org/techbd/service/CsvService.java @@ -16,6 +16,7 @@ import org.springframework.web.multipart.MultipartFile; import org.techbd.conf.Configuration; import org.techbd.orchestrate.csv.CsvOrchestrationEngine; +import org.techbd.service.constants.Origin; import org.techbd.service.http.Interactions; import org.techbd.service.http.InteractionsFilter; import org.techbd.udi.UdiPrimeJpaConfig; @@ -83,7 +84,7 @@ private void saveArchiveInteraction(final org.jooq.Configuration jooqCfg, final final var forwardedAt = OffsetDateTime.now(); final var initRIHR = new RegisterInteractionHttpRequest(); try { - initRIHR.setOrigin("http"); + initRIHR.setOrigin(Origin.HTTP.name()); initRIHR.setInteractionId(interactionId); initRIHR.setInteractionKey(request.getRequestURI()); initRIHR.setNature((JsonNode) Configuration.objectMapper.valueToTree( @@ -94,7 +95,7 @@ private void saveArchiveInteraction(final org.jooq.Configuration jooqCfg, final initRIHR.setCsvZipFileName(file.getOriginalFilename()); initRIHR.setCreatedAt(forwardedAt); final InetAddress localHost = InetAddress.getLocalHost(); - final String ipAddress = localHost.getHostAddress(); + final String ipAddress = localHost.getHostAddress(); initRIHR.setClientIpAddress(ipAddress); initRIHR.setUserAgent(request.getHeader("User-Agent")); initRIHR.setCreatedBy(CsvService.class.getName()); diff --git a/hub-prime/src/main/java/org/techbd/service/constants/Origin.java b/hub-prime/src/main/java/org/techbd/service/constants/Origin.java new file mode 100644 index 00000000000..be4361fce1b --- /dev/null +++ b/hub-prime/src/main/java/org/techbd/service/constants/Origin.java @@ -0,0 +1,7 @@ +package org.techbd.service.constants; + +public enum Origin { + HTTP, + SFTP + +} diff --git a/hub-prime/src/main/java/org/techbd/service/constants/SourceType.java b/hub-prime/src/main/java/org/techbd/service/constants/SourceType.java new file mode 100644 index 00000000000..8266c0dfefb --- /dev/null +++ b/hub-prime/src/main/java/org/techbd/service/constants/SourceType.java @@ -0,0 +1,7 @@ +package org.techbd.service.constants; + +public enum SourceType { + FHIR, + CSV, + HL7 +} \ No newline at end of file diff --git a/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FHIRService.java b/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FHIRService.java index 8c1742ea31b..9b336322804 100644 --- a/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FHIRService.java +++ b/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FHIRService.java @@ -46,6 +46,7 @@ import org.techbd.orchestrate.fhir.OrchestrationEngine; import org.techbd.orchestrate.fhir.OrchestrationEngine.Device; import org.techbd.service.constants.ErrorCode; +import org.techbd.service.constants.SourceType; import org.techbd.service.exception.JsonValidationException; import org.techbd.service.http.GitHubUserAuthorizationFilter; import org.techbd.service.http.Helpers; @@ -112,7 +113,7 @@ public Object processBundle(final @RequestBody @Nonnull String payload, boolean includeRequestInOutcome, boolean includeIncomingPayloadInDB, HttpServletRequest request, HttpServletResponse response, String provenance, - boolean includeOperationOutcome, String mtlsStrategy, String interactionId,String groupInteractionId,String masterInteractionId) + boolean includeOperationOutcome, String mtlsStrategy, String interactionId,String groupInteractionId,String masterInteractionId,String sourceType) throws IOException { final var start = Instant.now(); LOG.info("Bundle processing start at {} for interaction id {}.", @@ -142,7 +143,7 @@ public Object processBundle(final @RequestBody @Nonnull String payload, } addObservabilityHeadersToResponse(request, response); payloadWithDisposition = registerBundleInteraction(jooqCfg, request, - response, payload, result,interactionId,groupInteractionId,masterInteractionId); + response, payload, result,interactionId,groupInteractionId,masterInteractionId,sourceType); if (isActionDiscard(payloadWithDisposition)) { return payloadWithDisposition; } @@ -151,7 +152,7 @@ public Object processBundle(final @RequestBody @Nonnull String payload, getBundleInteractionId(request)); sendToScoringEngine(jooqCfg, request, customDataLakeApi, dataLakeApiContentType, includeIncomingPayloadInDB, tenantId, payload, - provenance, null, includeOperationOutcome, mtlsStrategy,interactionId,groupInteractionId,masterInteractionId); + provenance, null, includeOperationOutcome, mtlsStrategy,interactionId,groupInteractionId,masterInteractionId,sourceType); Instant end = Instant.now(); Duration timeElapsed = Duration.between(start, end); LOG.info("Bundle processing end for interaction id: {} Time Taken : {} milliseconds", @@ -163,7 +164,7 @@ public Object processBundle(final @RequestBody @Nonnull String payload, sendToScoringEngine(jooqCfg, request, customDataLakeApi, dataLakeApiContentType, includeIncomingPayloadInDB, tenantId, payload, provenance, payloadWithDisposition, includeOperationOutcome, - mtlsStrategy,interactionId,groupInteractionId,masterInteractionId); + mtlsStrategy,interactionId,groupInteractionId,masterInteractionId,sourceType); Instant end = Instant.now(); Duration timeElapsed = Duration.between(start, end); LOG.info("Bundle processing end for interaction id: {} Time Taken : {} milliseconds", @@ -172,7 +173,7 @@ public Object processBundle(final @RequestBody @Nonnull String payload, } } catch (JsonValidationException ex) { payloadWithDisposition = registerBundleInteraction(jooqCfg, request, - response, payload, buildOperationOutcome(ex, interactionId),interactionId,groupInteractionId,masterInteractionId); + response, payload, buildOperationOutcome(ex, interactionId),interactionId,groupInteractionId,masterInteractionId,sourceType); } Instant end = Instant.now(); Duration timeElapsed = Duration.between(start, end); @@ -253,7 +254,7 @@ private void addObservabilityHeadersToResponse(HttpServletRequest request, HttpS private Map registerBundleInteraction(org.jooq.Configuration jooqCfg, HttpServletRequest request, HttpServletResponse response, - String payload, Map> validationResult,String interactionId,String groupInteractionId,String masterInteractionId) + String payload, Map> validationResult,String interactionId,String groupInteractionId,String masterInteractionId,String sourceType) throws IOException { final Interactions interactions = new Interactions(); final var mutatableReq = new ContentCachingRequestWrapper(request); @@ -286,7 +287,7 @@ private Map registerBundleInteraction(org.jooq.Configuration joo final var rihr = new RegisterInteractionHttpRequest(); try { - prepareRequest(rihr, rre, provenance, request,interactionId,groupInteractionId,masterInteractionId); + prepareRequest(rihr, rre, provenance, request,interactionId,groupInteractionId,masterInteractionId,sourceType); final var start = Instant.now(); rihr.execute(jooqCfg); final var end = Instant.now(); @@ -308,7 +309,7 @@ private Map registerBundleInteraction(org.jooq.Configuration joo } private void prepareRequest(RegisterInteractionHttpRequest rihr, RequestResponseEncountered rre, - String provenance, HttpServletRequest request,String interactionId,String groupInteractionId,String masterInteractionId) { + String provenance, HttpServletRequest request,String interactionId,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.info("REGISTER State None, Accept, Disposition: BEGIN for interaction id: {} tenant id: {}", rre.interactionId().toString(), rre.tenant()); rihr.setInteractionId(interactionId!=null ? interactionId : rre.interactionId().toString()); @@ -325,6 +326,7 @@ private void prepareRequest(RegisterInteractionHttpRequest rihr, RequestResponse rihr.setPayload((JsonNode) Configuration.objectMapper.valueToTree(rre)); rihr.setCreatedAt(OffsetDateTime.now()); rihr.setCreatedBy(InteractionsFilter.class.getName()); + rihr.setSourceType(sourceType); rihr.setProvenance(provenance); if (saveUserDataToInteractions) { setUserDetails(rihr, request); @@ -446,7 +448,7 @@ private void sendToScoringEngine(org.jooq.Configuration jooqCfg, HttpServletRequ String payload, String provenance, Map validationPayloadWithDisposition, boolean includeOperationOutcome, - String mtlsStrategy,String interactionId,String groupInteractionId,String masterInteractionId) { + String mtlsStrategy,String interactionId,String groupInteractionId,String masterInteractionId,String sourceType) { interactionId = null != interactionId? interactionId :getBundleInteractionId(request); LOG.info("FHIRService:: sendToScoringEngine BEGIN for interaction id: {} for", interactionId); @@ -479,14 +481,14 @@ private void sendToScoringEngine(org.jooq.Configuration jooqCfg, HttpServletRequ handleNoMtls(MTlsStrategy.NO_MTLS, interactionId, tenantId, dataLakeApiBaseURL, jooqCfg, request, bundlePayloadWithDisposition, payload, dataLakeApiContentType, - provenance, includeIncomingPayloadInDB,groupInteractionId,masterInteractionId); + provenance, includeIncomingPayloadInDB,groupInteractionId,masterInteractionId,sourceType); } else { handleMTlsStrategy(defaultDatalakeApiAuthn, interactionId, tenantId, dataLakeApiBaseURL, jooqCfg, request, bundlePayloadWithDisposition, payload, dataLakeApiContentType, provenance, includeIncomingPayloadInDB, - mtlsStrategy,groupInteractionId,masterInteractionId); + mtlsStrategy,groupInteractionId,masterInteractionId,sourceType); } } catch ( @@ -502,7 +504,8 @@ public void handleMTlsStrategy(DefaultDataLakeApiAuthn defaultDatalakeApiAuthn, String tenantId, String dataLakeApiBaseURL, org.jooq.Configuration jooqCfg, HttpServletRequest request, Map bundlePayloadWithDisposition, String payload, String dataLakeApiContentType, - String provenance, boolean includeIncomingPayloadInDB, String mtlsStrategyStr,String groupInteractionId,String masterInteractionId) { + String provenance, boolean includeIncomingPayloadInDB, String mtlsStrategyStr,String groupInteractionId, + String masterInteractionId,String sourceType) { MTlsStrategy mTlsStrategy = null; LOG.info("FHIRService:: handleMTlsStrategy MTLS strategy from application.yml :{} for interaction id: {}", @@ -518,23 +521,23 @@ public void handleMTlsStrategy(DefaultDataLakeApiAuthn defaultDatalakeApiAuthn, case AWS_SECRETS -> handleAwsSecrets(defaultDatalakeApiAuthn.mTlsAwsSecrets(), interactionId, tenantId, dataLakeApiBaseURL, dataLakeApiContentType, bundlePayloadWithDisposition, jooqCfg, provenance, - request.getRequestURI(), includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId); + request.getRequestURI(), includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId,sourceType); case POST_STDOUT_PAYLOAD_TO_NYEC_DATA_LAKE_EXTERNAL -> handlePostStdoutPayload(interactionId, tenantId, jooqCfg, dataLakeApiBaseURL, bundlePayloadWithDisposition, includeIncomingPayloadInDB, payload, provenance, request, - defaultDatalakeApiAuthn.postStdinPayloadToNyecDataLakeExternal(),groupInteractionId,masterInteractionId); + defaultDatalakeApiAuthn.postStdinPayloadToNyecDataLakeExternal(),groupInteractionId,masterInteractionId,sourceType); case MTLS_RESOURCES -> handleMtlsResources(interactionId, tenantId, jooqCfg, bundlePayloadWithDisposition, includeIncomingPayloadInDB, payload, provenance, request, dataLakeApiContentType, dataLakeApiBaseURL, - defaultDatalakeApiAuthn.mTlsResources(),groupInteractionId,masterInteractionId); + defaultDatalakeApiAuthn.mTlsResources(),groupInteractionId,masterInteractionId,sourceType); default -> handleNoMtls(mTlsStrategy, interactionId, tenantId, dataLakeApiBaseURL, jooqCfg, request, bundlePayloadWithDisposition, payload, dataLakeApiContentType, - provenance, includeIncomingPayloadInDB,groupInteractionId,masterInteractionId); + provenance, includeIncomingPayloadInDB,groupInteractionId,masterInteractionId,sourceType); } } @@ -542,7 +545,7 @@ private void handleMtlsResources(String interactionId, String tenantId, org.jooq Map bundlePayloadWithDisposition, boolean includeIncomingPayloadInDB, String payload, String provenance, HttpServletRequest request, String dataLakeApiContentType, String dataLakeApiBaseURL, - MTlsResources mTlsResources,String groupInteractionId,String masterInteractionId) { + MTlsResources mTlsResources,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.info("FHIRService:: handleMtlsResources BEGIN for interaction id: {} tenantid :{} scoring", interactionId, tenantId); @@ -551,7 +554,7 @@ private void handleMtlsResources(String interactionId, String tenantId, org.jooq request.getRequestURI(), tenantId, Optional.ofNullable(bundlePayloadWithDisposition) .orElse(new HashMap<>()), - null, includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId); + null, includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId,sourceType); if (null == mTlsResources.mTlsKeyResourceName()) { LOG.error("ERROR:: FHIRService:: handleMtlsResources Key location `mTlsKeyResourceName` is not configured in application.yml for interaction id : {} tenant id :{} ", @@ -629,7 +632,7 @@ private void handleMtlsResources(String interactionId, String tenantId, org.jooq tenantId); sendPostRequest(webClient, tenantId, bundlePayloadWithDisposition, payload, dataLakeApiContentType, interactionId, - jooqCfg, provenance, request.getRequestURI(), dataLakeApiBaseURL,groupInteractionId,masterInteractionId); + jooqCfg, provenance, request.getRequestURI(), dataLakeApiBaseURL,groupInteractionId,masterInteractionId,sourceType); LOG.debug("FHIRService:: handleMtlsResources Build WebClient with MTLS Enabled ReactorClientHttpConnector -END for interaction Id :{}", interactionId); LOG.info("FHIRService:: handleMtlsResources END for interaction id: {} tenantid :{} ", @@ -639,7 +642,7 @@ private void handleMtlsResources(String interactionId, String tenantId, org.jooq LOG.error("ERROR:: handleMtlsResources Exception while posting to scoring engine with MTLS enabled for interactionId : {}", interactionId, ex); registerStateFailed(jooqCfg, interactionId, - request.getRequestURI(), tenantId, ex.getMessage(), provenance,groupInteractionId,masterInteractionId); + request.getRequestURI(), tenantId, ex.getMessage(), provenance,groupInteractionId,masterInteractionId,sourceType); } } @@ -648,7 +651,7 @@ private void handleNoMtls(MTlsStrategy mTlsStrategy, String interactionId, Strin String dataLakeApiBaseURL, org.jooq.Configuration jooqCfg, HttpServletRequest request, Map bundlePayloadWithDisposition, String payload, String dataLakeApiContentType, - String provenance, boolean includeIncomingPayloadInDB,String groupInteractionId,String masterInteractionId) { + String provenance, boolean includeIncomingPayloadInDB,String groupInteractionId,String masterInteractionId,String sourceType) { if (!MTlsStrategy.NO_MTLS.value.equals(mTlsStrategy.value)) { LOG.info("#########Invalid MTLS Strategy defined #############: Allowed values are {} .Hence proceeding with post to scoring engine without mTls for interaction id :{}", MTlsStrategy.getAllValues(), interactionId); @@ -669,14 +672,14 @@ private void handleNoMtls(MTlsStrategy mTlsStrategy, String interactionId, Strin var webClient = createWebClient(dataLakeApiBaseURL, jooqCfg, request, tenantId, payload, bundlePayloadWithDisposition, provenance, includeIncomingPayloadInDB, - interactionId,groupInteractionId,masterInteractionId); + interactionId,groupInteractionId,masterInteractionId,sourceType); LOG.debug("FHIRService:: createWebClient END for interaction id: {} tenant id :{} ", interactionId, tenantId); LOG.debug("FHIRService:: sendPostRequest BEGIN for interaction id: {} tenantid :{} ", interactionId, tenantId); sendPostRequest(webClient, tenantId, bundlePayloadWithDisposition, payload, dataLakeApiContentType, interactionId, - jooqCfg, provenance, request.getRequestURI(), dataLakeApiBaseURL,groupInteractionId,masterInteractionId); + jooqCfg, provenance, request.getRequestURI(), dataLakeApiBaseURL,groupInteractionId,masterInteractionId,sourceType); LOG.debug("FHIRService:: sendPostRequest END for interaction id: {} tenantid :{} ", interactionId, tenantId); } @@ -685,14 +688,15 @@ private void handleAwsSecrets(MTlsAwsSecrets mTlsAwsSecrets, String interactionI String dataLakeApiBaseURL, String dataLakeApiContentType, Map bundlePayloadWithDisposition, org.jooq.Configuration jooqCfg, String provenance, String requestURI, - boolean includeIncomingPayloadInDB, String payload,String groupInteractionId,String masterInteractionId) { + boolean includeIncomingPayloadInDB, String payload,String groupInteractionId,String masterInteractionId, + String sourceType) { try { LOG.info("FHIRService :: handleAwsSecrets -BEGIN for interactionId : {}", interactionId); registerStateForward(jooqCfg, provenance, interactionId, requestURI, tenantId, bundlePayloadWithDisposition, null, includeIncomingPayloadInDB, - payload,groupInteractionId,masterInteractionId); + payload,groupInteractionId,masterInteractionId,sourceType); if (null == mTlsAwsSecrets || null == mTlsAwsSecrets.mTlsKeySecretName() || null == mTlsAwsSecrets.mTlsCertSecretName()) { throw new IllegalArgumentException( @@ -764,7 +768,7 @@ private void handleAwsSecrets(MTlsAwsSecrets mTlsAwsSecrets, String interactionI tenantId); sendPostRequest(webClient, tenantId, bundlePayloadWithDisposition, payload, dataLakeApiContentType, interactionId, - jooqCfg, provenance, requestURI, dataLakeApiBaseURL,groupInteractionId,masterInteractionId); + jooqCfg, provenance, requestURI, dataLakeApiBaseURL,groupInteractionId,masterInteractionId,sourceType); LOG.debug("FHIRService:: handleAwsSecrets -sendPostRequest END for interaction id: {} tenantid :{} ", interactionId, tenantId); @@ -775,7 +779,7 @@ private void handleAwsSecrets(MTlsAwsSecrets mTlsAwsSecrets, String interactionI ex.getMessage(), interactionId, tenantId, ex); registerStateFailed(jooqCfg, interactionId, requestURI, tenantId, ex.getMessage(), - provenance,groupInteractionId,masterInteractionId); + provenance,groupInteractionId,masterInteractionId,sourceType); } LOG.info("FHIRService :: handleAwsSecrets -END for interactionId : {}", interactionId); @@ -786,7 +790,8 @@ private void handlePostStdoutPayload(String interactionId, String tenantId, org. Map bundlePayloadWithDisposition, boolean includeIncomingPayloadInDB, String payload, String provenance, HttpServletRequest request, - PostStdinPayloadToNyecDataLakeExternal postStdinPayloadToNyecDataLakeExternal,String groupInteractionId,String masterInteractionId) { + PostStdinPayloadToNyecDataLakeExternal postStdinPayloadToNyecDataLakeExternal, + String groupInteractionId,String masterInteractionId,String sourceType) { LOG.info("Proceed with posting payload via external process BEGIN forinteractionId : {}", interactionId); try { @@ -794,7 +799,7 @@ private void handlePostStdoutPayload(String interactionId, String tenantId, org. request.getRequestURI(), tenantId, Optional.ofNullable(bundlePayloadWithDisposition) .orElse(new HashMap<>()), - null, includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId); + null, includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId,sourceType); var postToNyecExternalResponse = postStdinPayloadToNyecDataLakeExternal(dataLakeApiBaseURL, tenantId, interactionId, bundlePayloadWithDisposition, @@ -815,17 +820,17 @@ private void handlePostStdoutPayload(String interactionId, String tenantId, org. .contains("{\"status\": \"Success\"")) { registerStateComplete(jooqCfg, interactionId, request.getRequestURI(), tenantId, responsePayload, - provenance,groupInteractionId,masterInteractionId); + provenance,groupInteractionId,masterInteractionId,sourceType); } else { registerStateFailed(jooqCfg, interactionId, request.getRequestURI(), tenantId, responsePayload, - provenance,groupInteractionId,masterInteractionId); + provenance,groupInteractionId,masterInteractionId,sourceType); } } catch (Exception ex) { LOG.error("Exception while postStdinPayloadToNyecDataLakeExternal forinteractionId : {}", interactionId, ex); registerStateFailed(jooqCfg, interactionId, - request.getRequestURI(), tenantId, ex.getMessage(), provenance,groupInteractionId,masterInteractionId); + request.getRequestURI(), tenantId, ex.getMessage(), provenance,groupInteractionId,masterInteractionId,sourceType); } LOG.info("Proceed with posting payload via external process END for interactionId : {}", interactionId); @@ -918,13 +923,13 @@ private WebClient createWebClient(String scoringEngineApiURL, String payload, Map bundlePayloadWithDisposition, String provenance, - boolean includeIncomingPayloadInDB, String interactionId,String groupInteractionId,String masterInteractionId) { + boolean includeIncomingPayloadInDB, String interactionId,String groupInteractionId,String masterInteractionId,String sourceType) { return WebClient.builder() .baseUrl(scoringEngineApiURL) .filter(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { filter(clientRequest, request, jooqCfg, provenance, tenantId, payload, bundlePayloadWithDisposition, - includeIncomingPayloadInDB,groupInteractionId,masterInteractionId); + includeIncomingPayloadInDB,groupInteractionId,masterInteractionId,sourceType); return Mono.just(clientRequest); })) .build(); @@ -977,7 +982,7 @@ private void filter(ClientRequest clientRequest, String tenantId, String payload, Map bundlePayloadWithDisposition, - boolean includeIncomingPayloadInDB,String groupInteractionId,String masterInteractionId) { + boolean includeIncomingPayloadInDB,String groupInteractionId,String masterInteractionId,String sourceType) { final var interactionId = getBundleInteractionId(request); LOG.debug("FHIRService:: sendToScoringEngine Filter request before post - BEGIN interaction id: {}", @@ -994,7 +999,7 @@ private void filter(ClientRequest clientRequest, registerStateForward(jooqCfg, provenance, getBundleInteractionId(request), requestURI, tenantId, Optional.ofNullable(bundlePayloadWithDisposition).orElse(new HashMap<>()), - outboundHttpMessage, includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId); + outboundHttpMessage, includeIncomingPayloadInDB, payload,groupInteractionId,masterInteractionId,sourceType); LOG.debug("FHIRService:: sendToScoringEngine Filter request before post - END interaction id: {}", interactionId); @@ -1008,7 +1013,7 @@ private void sendPostRequest(WebClient webClient, String interactionId, org.jooq.Configuration jooqCfg, String provenance, - String requestURI, String scoringEngineApiURL,String groupInteractionId,String masterInteractionId) { + String requestURI, String scoringEngineApiURL,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.debug("FHIRService:: sendToScoringEngine Post to scoring engine - BEGIN interaction id: {} tenantID :{}", interactionId, tenantId); @@ -1023,10 +1028,10 @@ private void sendPostRequest(WebClient webClient, .bodyToMono(String.class) .subscribe(response -> { handleResponse(response, jooqCfg, interactionId, requestURI, tenantId, - provenance, scoringEngineApiURL,groupInteractionId,masterInteractionId); + provenance, scoringEngineApiURL,groupInteractionId,masterInteractionId,sourceType); }, error -> { registerStateFailure(jooqCfg, scoringEngineApiURL, interactionId, error, - requestURI, tenantId, provenance,groupInteractionId,masterInteractionId); + requestURI, tenantId, provenance,groupInteractionId,masterInteractionId,sourceType); }); LOG.info("FHIRService:: sendToScoringEngine Post to scoring engine - END interaction id: {} tenantid: {}", @@ -1039,7 +1044,7 @@ private void handleResponse(String response, String requestURI, String tenantId, String provenance, - String scoringEngineApiURL,String groupInteractionId,String masterInteractionId) { + String scoringEngineApiURL,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.debug("FHIRService:: handleResponse BEGIN for interaction id: {}", interactionId); try { @@ -1053,18 +1058,18 @@ private void handleResponse(String response, LOG.info("FHIRService:: handleResponse SUCCESS for interaction id: {}", interactionId); registerStateComplete(jooqCfg, interactionId, requestURI, tenantId, response, - provenance,groupInteractionId,masterInteractionId); + provenance,groupInteractionId,masterInteractionId,sourceType); } else { LOG.warn("FHIRService:: handleResponse FAILURE for interaction id: {}", interactionId); registerStateFailed(jooqCfg, interactionId, requestURI, tenantId, response, - provenance,groupInteractionId,masterInteractionId); + provenance,groupInteractionId,masterInteractionId,sourceType); } } catch (Exception e) { LOG.error("FHIRService:: handleResponse unexpected error for interaction id : {}, response: {}", interactionId, response, e); registerStateFailed(jooqCfg, interactionId, requestURI, tenantId, e.getMessage(), - provenance,groupInteractionId,masterInteractionId); + provenance,groupInteractionId,masterInteractionId,sourceType); } LOG.info("FHIRService:: handleResponse END for interaction id: {}", interactionId); } @@ -1209,7 +1214,8 @@ private void registerStateForward(org.jooq.Configuration jooqCfg, String provena String bundleAsyncInteractionId, String requestURI, String tenantId, Map payloadWithDisposition, - String outboundHttpMessage, boolean includeIncomingPayloadInDB, String payload,String groupInteractionId,String masterInteractionId) { + String outboundHttpMessage, boolean includeIncomingPayloadInDB, String payload, + String groupInteractionId,String masterInteractionId,String sourceType) { LOG.info("REGISTER State Forward : BEGIN for inteaction id : {} tenant id : {}", bundleAsyncInteractionId, tenantId); final var forwardedAt = OffsetDateTime.now(); @@ -1236,6 +1242,7 @@ private void registerStateForward(org.jooq.Configuration jooqCfg, String provena .valueToTree(payloadWithDisposition)); initRIHR.setFromState("DISPOSITION"); initRIHR.setToState("FORWARD"); + initRIHR.setSourceType(sourceType); initRIHR.setCreatedAt(forwardedAt); // don't let DB set this, use app // time initRIHR.setCreatedBy(FHIRService.class.getName()); @@ -1257,7 +1264,7 @@ private void registerStateForward(org.jooq.Configuration jooqCfg, String provena private void registerStateComplete(org.jooq.Configuration jooqCfg, String bundleAsyncInteractionId, String requestURI, String tenantId, - String response, String provenance,String groupInteractionId,String masterInteractionId) { + String response, String provenance,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.info("REGISTER State Complete : BEGIN for interaction id : {} tenant id : {}", bundleAsyncInteractionId, tenantId); final var forwardRIHR = new RegisterInteractionHttpRequest(); @@ -1282,6 +1289,7 @@ private void registerStateComplete(org.jooq.Configuration jooqCfg, String bundle } forwardRIHR.setFromState("FORWARD"); forwardRIHR.setToState("COMPLETE"); + forwardRIHR.setSourceType(sourceType); forwardRIHR.setCreatedAt(OffsetDateTime.now()); // don't let DB forwardRIHR.setCreatedBy(FHIRService.class.getName()); forwardRIHR.setProvenance(provenance); @@ -1301,7 +1309,7 @@ private void registerStateComplete(org.jooq.Configuration jooqCfg, String bundle private void registerStateFailed(org.jooq.Configuration jooqCfg, String bundleAsyncInteractionId, String requestURI, String tenantId, - String response, String provenance,String groupInteractionId,String masterInteractionId) { + String response, String provenance,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.info("REGISTER State Fail : BEGIN for interaction id : {} tenant id : {}", bundleAsyncInteractionId, tenantId); final var forwardRIHR = new RegisterInteractionHttpRequest(); @@ -1326,6 +1334,7 @@ private void registerStateFailed(org.jooq.Configuration jooqCfg, String bundleAs } forwardRIHR.setFromState("FORWARD"); forwardRIHR.setToState("FAIL"); + forwardRIHR.setSourceType(sourceType); forwardRIHR.setCreatedAt(OffsetDateTime.now()); // don't let DB // set this, use // app time @@ -1348,7 +1357,7 @@ private void registerStateFailed(org.jooq.Configuration jooqCfg, String bundleAs private void registerStateFailure(org.jooq.Configuration jooqCfg, String dataLakeApiBaseURL, String bundleAsyncInteractionId, Throwable error, String requestURI, String tenantId, - String provenance,String groupInteractionId,String masterInteractionId) { + String provenance,String groupInteractionId,String masterInteractionId,String sourceType) { LOG.error("Register State Failure - Exception while sending FHIR payload to datalake URL {} for interaction id {}", dataLakeApiBaseURL, bundleAsyncInteractionId, error); final var errorRIHR = new RegisterInteractionHttpRequest(); @@ -1361,6 +1370,7 @@ private void registerStateFailure(org.jooq.Configuration jooqCfg, String dataLak Map.of("nature", "Forwarded HTTP Response Error", "tenant_id", tenantId))); errorRIHR.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE); + errorRIHR.setSourceType(sourceType); final var rootCauseThrowable = NestedExceptionUtils .getRootCause(error); final var rootCause = rootCauseThrowable != null diff --git a/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FhirController.java b/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FhirController.java index 4a4f78dbbd9..a78810709b1 100644 --- a/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FhirController.java +++ b/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/FhirController.java @@ -31,6 +31,7 @@ import org.techbd.orchestrate.fhir.OrchestrationEngine; import org.techbd.orchestrate.fhir.OrchestrationEngine.Device; import org.techbd.orchestrate.sftp.SftpManager; +import org.techbd.service.constants.SourceType; import org.techbd.service.http.Helpers; import org.techbd.service.http.InteractionsFilter; import org.techbd.service.http.SandboxHelpers; @@ -201,7 +202,7 @@ public Object validateBundleAndForward( uaValidationStrategyJson, customDataLakeApi, dataLakeApiContentType, healthCheck, isSync, includeRequestInOutcome, includeIncomingPayloadInDB, - request, response, provenance, includeOperationOutcome, mtlsStrategy,null, null,null); + request, response, provenance, includeOperationOutcome, mtlsStrategy,null, null,null,SourceType.FHIR.name()); } @PostMapping(value = { "/Bundle/$validate", "/Bundle/$validate/" }, consumes = { diff --git a/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/Hl7Service.java b/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/Hl7Service.java index d2d07f8c9e6..0c1b68bae5d 100644 --- a/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/Hl7Service.java +++ b/hub-prime/src/main/java/org/techbd/service/http/hub/prime/api/Hl7Service.java @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.MimeTypeUtils; import org.techbd.conf.Configuration; +import org.techbd.service.constants.SourceType; import org.techbd.service.converters.shinny.Hl7FHIRToShinnyFHIRConverter; import org.techbd.service.http.GitHubUserAuthorizationFilter; import org.techbd.service.http.InteractionsFilter; @@ -76,7 +77,7 @@ public Object processHl7Message(String hl7Payload, String tenantId, HttpServletR return fhirService.processBundle(shinnyFhirJson, tenantId, null, null, null, null, null, Boolean.toString(false), false, false, - false, request, response, null, true,null,null, null,null); + false, request, response, null, true,null,null, null,null,SourceType.HL7.name()); } } } catch (Exception ex) { diff --git a/hub-prime/src/test/java/org/techbd/service/CsvBundleProcessorServiceTest.java b/hub-prime/src/test/java/org/techbd/service/CsvBundleProcessorServiceTest.java index 138f5d919b7..9162e516b2f 100644 --- a/hub-prime/src/test/java/org/techbd/service/CsvBundleProcessorServiceTest.java +++ b/hub-prime/src/test/java/org/techbd/service/CsvBundleProcessorServiceTest.java @@ -116,7 +116,7 @@ void shouldProcessPayloadAndPopulatePatients() throws Exception { OperationOutcome mockOutcome = new OperationOutcome(); when(fhirService.processBundle(eq(mockBundle), anyString(), any(), any(), any(), any(), any(), anyString(), - eq(false), eq(false), eq(false), eq(request), eq(response), any(), eq(true), any(), anyString(), anyString(),anyString())) + eq(false), eq(false), eq(false), eq(request), eq(response), any(), eq(true), any(), anyString(), anyString(),anyString(),anyString())) .thenReturn(mockOutcome); List result = csvBundleProcessorService.processPayload(masterInteractionId, payloadAndValidationOutcomes, @@ -130,7 +130,7 @@ void shouldProcessPayloadAndPopulatePatients() throws Exception { verify(fhirService, times(2)).processBundle(eq(mockBundle), anyString(), any(), any(), any(), any(), any(), anyString(), eq(false), eq(false), eq(false), eq(request), eq(response), any(), - eq(true), any(), anyString(), anyString(),anyString()); + eq(true), any(), anyString(), anyString(),anyString(),anyString()); } @Test @@ -185,7 +185,7 @@ void shouldProcessPayloadAndPopulatePatientsWithMultipleEncounters() throws Exce OperationOutcome mockOutcome = new OperationOutcome(); when(fhirService.processBundle(eq(mockBundle), anyString(), any(), any(), any(), any(), any(), anyString(), - eq(false), eq(false), eq(false), eq(request), eq(response), any(), eq(true), any(), anyString(), anyString(),anyString())) + eq(false), eq(false), eq(false), eq(request), eq(response), any(), eq(true), any(), anyString(), anyString(),anyString(),anyString())) .thenReturn(mockOutcome); List result = csvBundleProcessorService.processPayload(masterInteractionId, @@ -199,7 +199,7 @@ void shouldProcessPayloadAndPopulatePatientsWithMultipleEncounters() throws Exce verify(fhirService, times(2)).processBundle(eq(mockBundle), anyString(), any(), any(), any(), any(), any(), anyString(), eq(false), eq(false), eq(false), eq(request), eq(response), any(), - eq(true), any(), anyString(), anyString(),anyString()); + eq(true), any(), anyString(), anyString(),anyString(),anyString()); } @Test @@ -245,7 +245,7 @@ void shouldProcessPayloadAndHandleFutureFailures() throws Exception { OperationOutcome successfulOutcome = new OperationOutcome(); when(fhirService.processBundle(eq(mockBundle), anyString(), any(), any(), any(), any(), any(), anyString(), - eq(false), eq(false), eq(false), eq(request), eq(response), any(), eq(true), any(), anyString(), anyString(),anyString())) + eq(false), eq(false), eq(false), eq(request), eq(response), any(), eq(true), any(), anyString(), anyString(),anyString(),anyString())) .thenReturn(successfulOutcome) .thenThrow(new RuntimeException("Mock failure")); List result = csvBundleProcessorService.processPayload(masterInteractionId, @@ -274,7 +274,7 @@ void shouldProcessPayloadAndHandleFutureFailures() throws Exception { verify(fhirService, times(2)).processBundle(eq(mockBundle), anyString(), any(), any(), any(), any(), any(), anyString(), eq(false), eq(false), eq(false), eq(request), eq(response), any(), - eq(true), any(), anyString(), anyString(),anyString()); + eq(true), any(), anyString(), anyString(),anyString(),anyString()); } private String getMockBundleJson() {