Skip to content

Commit

Permalink
Merge pull request #692 from lantanagroup/LNK-1828
Browse files Browse the repository at this point in the history
Lnk 1828
  • Loading branch information
arianamihailescu committed Feb 2, 2024
2 parents 43a4a76 + 5d5a510 commit 367d893
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.lantanagroup.link.Constants;
import com.lantanagroup.link.FhirDataProvider;
import com.lantanagroup.link.Helper;
import com.lantanagroup.link.ReportIdHelper;
import com.lantanagroup.link.config.api.ApiConfig;
import com.lantanagroup.link.db.TenantService;
Expand Down Expand Up @@ -62,6 +63,12 @@ private MeasureReport generateMeasureReport() {
patientBundle = PatientData.asBundle(tenantService.findPatientData(reportContext.getMasterIdentifierValue(), patientId));
}

// if patient is in the debugPatients list or debugPatients = "*" then write the patient data bundle to the file system
if (reportContext.getDebugPatients().contains("Patient/" + patientId) || reportContext.getDebugPatients().contains("*")) {
String fileName = ReportIdHelper.getPatientBundleFileName(reportContext.getMasterIdentifierValue(), patientId) + ".json";
Helper.dumpToFile(patientBundle, config.getDebugPath(), fileName);
}

logger.info("Executing $evaluate-measure for measure: {}, start: {}, end: {}, patient: {}, resources: {}", measureId, start, end, patientId, patientBundle.getEntry().size());

Parameters parameters = new Parameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public Report generateReport(
}

TenantService tenantService = TenantService.create(this.sharedService, tenantId);
return generateResponse(tenantService, user, request, input.getPackageId(), input.getBundleIds(), input.getPeriodStart(), input.getPeriodEnd(), input.isRegenerate(), input.isValidate(), input.isSkipQuery());
return generateResponse(tenantService, user, request, input.getPackageId(), input.getBundleIds(), input.getPeriodStart(), input.getPeriodEnd(), input.isRegenerate(), input.isValidate(), input.isSkipQuery(), input.getDebugPatients());
}

/**
Expand All @@ -185,7 +185,8 @@ public Report generateReport(
@PathVariable String tenantId,
@RequestParam boolean regenerate,
@RequestParam(defaultValue = "true") boolean validate,
@RequestParam(defaultValue = "false") boolean skipQuery)
@RequestParam(defaultValue = "false") boolean skipQuery,
@RequestParam(required = false, defaultValue = "") List<String> debugPatients)
throws Exception {
List<String> singleMeasureBundleIds;

Expand All @@ -198,6 +199,8 @@ public Report generateReport(
}
}

Optional<List<String>> debugPatientList = Optional.of(debugPatients);

// get the associated bundle-ids
if (!apiMeasurePackage.isPresent()) {
throw new IllegalStateException(String.format("Multimeasure %s is not set-up.", multiMeasureBundleId));
Expand All @@ -206,7 +209,7 @@ public Report generateReport(
TenantService tenantService = TenantService.create(this.sharedService, tenantId);

singleMeasureBundleIds = apiMeasurePackage.get().getMeasureIds();
return generateResponse(tenantService, user, request, multiMeasureBundleId, singleMeasureBundleIds, periodStart, periodEnd, regenerate, validate, skipQuery);
return generateResponse(tenantService, user, request, multiMeasureBundleId, singleMeasureBundleIds, periodStart, periodEnd, regenerate, validate, skipQuery, debugPatients);
}

private void checkReportingPlan(TenantService tenantService, String periodStart, List<String> measureIds) throws ParseException, URISyntaxException, IOException {
Expand Down Expand Up @@ -244,7 +247,7 @@ private void checkReportingPlan(TenantService tenantService, String periodStart,
/**
* generates a response with one or multiple reports
*/
private Report generateResponse(TenantService tenantService, LinkCredentials user, HttpServletRequest request, String packageId, List<String> measureIds, String periodStart, String periodEnd, boolean regenerate, boolean validate, boolean skipQuery) throws Exception {
private Report generateResponse(TenantService tenantService, LinkCredentials user, HttpServletRequest request, String packageId, List<String> measureIds, String periodStart, String periodEnd, boolean regenerate, boolean validate, boolean skipQuery, List<String> debugPatients) throws Exception {
Report report = null;
try(var stopwatch = stopwatchManager.start(Constants.REPORT_GENERATION_TASK, Constants.CATEGORY_REPORT)) {
this.checkReportingPlan(tenantService, periodStart, measureIds);
Expand Down Expand Up @@ -299,6 +302,17 @@ private Report generateResponse(TenantService tenantService, LinkCredentials use
}
reportContext.setQueryPlan(queryPlan);

// Validate the debug patients against the patient of interest list
if(!debugPatients.isEmpty() && !debugPatients.contains("*")) {
List<String> invalidDebugPatientsList = debugPatients.stream().filter(dp -> !reportContext.getPatientsOfInterest().stream().map(PatientOfInterestModel::getReference).collect(Collectors.toList()).contains(dp)).collect(Collectors.toList());
if (!invalidDebugPatientsList.isEmpty()) {
String msg = String.format("Debugging patients: %s do not exist", invalidDebugPatientsList);
logger.error(msg);
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, msg);
}
}
reportContext.setDebugPatients(debugPatients);

report = new Report();
report.setId(masterIdentifierValue);
report.setPeriodStart(criteria.getPeriodStart());
Expand Down
3 changes: 2 additions & 1 deletion api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ api:
sender: com.lantanagroup.link.sender.FileSystemSender
patient-id-resolver: com.lantanagroup.link.nhsn.StoredListProvider
report-aggregator: com.lantanagroup.link.nhsn.ReportAggregator
debugPath: '%TEMP%'
data-processor:
csv: com.lantanagroup.link.thsa.GenericCSVProcessor
xlsx: com.lantanagroup.link.thsa.GenericXLSXProcessor
Expand Down Expand Up @@ -92,4 +93,4 @@ data-governance:
report-retention:
sender:
file:
path: '%TEMP%'
path: '%TEMP%'
26 changes: 21 additions & 5 deletions core/src/main/java/com/lantanagroup/link/Helper.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.lantanagroup.link;

import ca.uhn.fhir.parser.IParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.lantanagroup.link.config.api.ApiConfig;
import com.lantanagroup.link.db.TenantService;
import com.lantanagroup.link.db.model.Aggregate;
import com.lantanagroup.link.db.model.Report;
Expand All @@ -13,14 +13,14 @@
import org.apache.commons.text.StringEscapeUtils;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.CapabilityStatement;
import org.hl7.fhir.r4.model.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.sql.Driver;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
Expand Down Expand Up @@ -192,6 +192,22 @@ public static String expandEnvVars(String text) {
return text;
}

public static void dumpToFile(Resource resource, String path, String fileName) {

IParser parser = FhirContextProvider.getFhirContext().newJsonParser();
String folderPath = Helper.expandEnvVars(path);
String filePath = Paths.get(folderPath, fileName).toString();
try (Writer writer = new FileWriter(filePath, StandardCharsets.UTF_8)) {
parser.encodeResourceToWriter(resource, writer);
}
catch (Exception e) {
logger.error("Error writing resource {} to file system", resource.getId(), e);
}
finally {
logger.info("Done writing resource {} to file system {}", resource.getId(), filePath);
}
}

public static Bundle generateBundle(TenantService tenantService, Report report, EventService eventService) {
FhirBundler bundler = new FhirBundler(eventService, tenantService);
logger.info("Building Bundle for MeasureReport to send...");
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/com/lantanagroup/link/ReportIdHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ public static String getPatientMeasureReportId(String masterMeasureReportId, Str
public static String getPatientDataBundleId(String masterIdentifierValue, String patientId) {
return combine(masterIdentifierValue, hash(patientId));
}

public static String getPatientBundleFileName(String masterIdentifierValue, String patientId) {
return combine("patient-bundle-for-cqf-", masterIdentifierValue, "-" + patientId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ public class ApiConfig {
@Getter
private String socketTimeout;

@Getter
@NotNull
private String debugPath;

/**
* <strong>api.measure-evaluation-threads</strong><br>The number of threads to use for patient measure report generation.
*/
Expand All @@ -177,4 +181,5 @@ public class ApiConfig {
private boolean allowQaEndpoints = false;

private List<ApiInfoGroup> infoGroups = new ArrayList<>();

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public class GenerateRequest {
private String periodEnd;
boolean validate = true;
boolean skipQuery = false;
private List<String> debugPatients = new ArrayList<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class ReportContext {
private List<PatientOfInterestModel> patientsOfInterest = new ArrayList<>();
private List<MeasureContext> measureContexts = new ArrayList<>();
private QueryPlan queryPlan;
private List<String> debugPatients = new ArrayList<>();

public ReportContext() {
}
Expand Down

0 comments on commit 367d893

Please sign in to comment.