use of org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest in project CRD by HL7-DaVinci.
the class OrderSelectService method createCqlExecutionContexts.
@Override
public List<CoverageRequirementRuleResult> createCqlExecutionContexts(OrderSelectRequest orderSelectRequest, FileStore fileStore, String baseUrl) {
List<String> selections = Arrays.asList(orderSelectRequest.getContext().getSelections());
FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(fileStore, baseUrl, selections);
CrdPrefetch prefetch = orderSelectRequest.getPrefetch();
fhirBundleProcessor.processOrderSelectMedicationStatements(prefetch.getMedicationRequestBundle(), prefetch.getMedicationStatementBundle());
List<CoverageRequirementRuleResult> results = fhirBundleProcessor.getResults();
if (results.isEmpty()) {
throw RequestIncompleteException.NoSupportedBundlesFound();
}
return results;
}
use of org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest in project CRD by HL7-DaVinci.
the class OrderSelectServiceTest method testHandleRequestWithMatch.
@Test
public void testHandleRequestWithMatch() {
URL applicationBase;
try {
applicationBase = new URL("http", "localhost", "/");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
Calendar cal = Calendar.getInstance();
cal.set(1970, Calendar.JULY, 4);
// make sure azathioprine comes back with an interaction with methotrexate
OrderSelectRequest request = CrdRequestCreator.createOrderSelectRequest(Enumerations.AdministrativeGender.MALE, cal.getTime(), "MA", "MA", getAzathioprineCode(), getMethotrexateCode());
CdsResponse response = service.handleRequest(request, applicationBase);
assertNotNull(response);
assertEquals(1, response.getCards().size());
assertTrue(response.getCards().get(0).getSummary().contains("Drug Interaction Found"));
assertEquals(Card.IndicatorEnum.WARNING, response.getCards().get(0).getIndicator());
// make sure methotrexate comes back with an interaction with azathioprine
request = CrdRequestCreator.createOrderSelectRequest(Enumerations.AdministrativeGender.MALE, cal.getTime(), "MA", "MA", getMethotrexateCode(), getAzathioprineCode());
response = service.handleRequest(request, applicationBase);
assertNotNull(response);
assertEquals(1, response.getCards().size());
assertTrue(response.getCards().get(0).getSummary().contains("Drug Interaction Found"));
assertEquals(Card.IndicatorEnum.WARNING, response.getCards().get(0).getIndicator());
}
use of org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest in project CRD by HL7-DaVinci.
the class OrderSelectServiceTest method testHandleRequestWithNoMatch.
@Test
public void testHandleRequestWithNoMatch() {
URL applicationBase;
try {
applicationBase = new URL("http", "localhost", "/");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
Calendar cal = Calendar.getInstance();
cal.set(1970, Calendar.JULY, 4);
// make sure azathioprine does not come back with an interaction with tylenol
OrderSelectRequest request = CrdRequestCreator.createOrderSelectRequest(Enumerations.AdministrativeGender.MALE, cal.getTime(), "MA", "MA", getAzathioprineCode(), getTylenolCode());
CdsResponse response = service.handleRequest(request, applicationBase);
assertNotNull(response);
assertEquals(0, response.getCards().size());
assertTrue(response.getCards().isEmpty());
}
use of org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest in project CRD by HL7-DaVinci.
the class CdsService method handleRequest.
/**
* Performs generic operations for incoming requests of any type.
*
* @param request the generically typed incoming request
* @return The response from the server
*/
public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL applicationBaseUrl) {
// create the RequestLog
RequestLog requestLog = new RequestLog(request, new Date().getTime(), this.fhirComponents.getFhirVersion().toString(), this.id, requestService, 5);
// Parsed request
requestLog.advanceTimeline(requestService);
PrefetchHydrator prefetchHydrator = new PrefetchHydrator(this, request, this.fhirComponents);
prefetchHydrator.hydrate();
// hydrated
requestLog.advanceTimeline(requestService);
// Attempt a Query Batch Request to backfill missing attributes.
if (myConfig.isQueryBatchRequest()) {
QueryBatchRequest qbr = new QueryBatchRequest(this.fhirComponents);
this.attempQueryBatchRequest(request, qbr);
}
logger.info("***** ***** request from requestLog: " + requestLog.toString());
CdsResponse response = new CdsResponse();
Gson gson = new Gson();
final String jsonObject = gson.toJson(request.getPrefetch());
logger.info("Final populated CRDPrefetch: " + jsonObject);
// CQL Fetched
List<CoverageRequirementRuleResult> lookupResults;
try {
lookupResults = this.createCqlExecutionContexts(request, fileStore, applicationBaseUrl.toString() + "/");
requestLog.advanceTimeline(requestService);
} catch (RequestIncompleteException e) {
logger.warn("RequestIncompleteException " + request);
logger.warn(e.getMessage() + "; summary card sent to client");
response.addCard(CardBuilder.summaryCard(CardTypes.COVERAGE, e.getMessage()));
requestLog.setCardListFromCards(response.getCards());
requestLog.setResults(e.getMessage());
requestService.edit(requestLog);
return response;
}
// process the extension for the configuration
// load hook configuration with default values
Configuration hookConfiguration = new Configuration();
Extension extension = request.getExtension();
if (extension != null) {
if (extension.getConfiguration() != null) {
hookConfiguration = extension.getConfiguration();
}
}
boolean errorCardOnEmpty = !(request instanceof OrderSelectRequest);
// no error cards on empty when order-select request
boolean foundApplicableRule = false;
for (CoverageRequirementRuleResult lookupResult : lookupResults) {
requestLog.addTopic(requestService, lookupResult.getTopic());
CqlResultsForCard results = executeCqlAndGetRelevantResults(lookupResult.getContext(), lookupResult.getTopic());
CoverageRequirements coverageRequirements = results.getCoverageRequirements();
if (results.ruleApplies()) {
foundApplicableRule = true;
if (results.getCoverageRequirements().getApplies()) {
// if prior auth already approved
if (coverageRequirements.isPriorAuthApproved()) {
response.addCard(CardBuilder.priorAuthCard(results, results.getRequest(), fhirComponents, coverageRequirements.getPriorAuthId(), request.getContext().getPatientId(), lookupResult.getCriteria().getPayorId(), request.getContext().getUserId(), applicationBaseUrl.toString() + "/fhir/" + fhirComponents.getFhirVersion().toString(), fhirResourceRepository));
} else if (coverageRequirements.isDocumentationRequired() || coverageRequirements.isPriorAuthRequired()) {
if (StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireOrderUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireFaceToFaceUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireLabUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireProgressNoteUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnairePARequestUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnairePlanOfCareUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireDispenseUri()) || StringUtils.isNotEmpty(coverageRequirements.getQuestionnaireAdditionalUri())) {
List<Link> smartAppLinks = createQuestionnaireLinks(request, applicationBaseUrl, lookupResult, results);
if (coverageRequirements.isPriorAuthRequired()) {
Card card = CardBuilder.transform(CardTypes.PRIOR_AUTH, results, smartAppLinks);
card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents, "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note", true, CoverageGuidance.ADMIN));
response.addCard(card);
} else if (coverageRequirements.isDocumentationRequired()) {
Card card = CardBuilder.transform(CardTypes.DTR_CLIN, results, smartAppLinks);
card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents, "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note", true, CoverageGuidance.CLINICAL));
response.addCard(card);
}
// add a card for an alternative therapy if there is one
if (results.getAlternativeTherapy().getApplies() && hookConfiguration.getAlternativeTherapy()) {
try {
response.addCard(CardBuilder.alternativeTherapyCard(results.getAlternativeTherapy(), results.getRequest(), fhirComponents));
} catch (RuntimeException e) {
logger.warn("Failed to process alternative therapy: " + e.getMessage());
}
}
} else {
logger.warn("Unspecified Questionnaire URI; summary card sent to client");
response.addCard(CardBuilder.transform(CardTypes.COVERAGE, results));
}
} else {
// no prior auth or documentation required
logger.info("Add the no doc or prior auth required card");
Card card = CardBuilder.transform(CardTypes.COVERAGE, results);
card.addSuggestionsItem(CardBuilder.createSuggestionWithNote(card, results.getRequest(), fhirComponents, "Save Update To EHR", "Update original " + results.getRequest().fhirType() + " to add note", true, CoverageGuidance.COVERED));
card.setSelectionBehavior(Card.SelectionBehaviorEnum.ANY);
response.addCard(card);
}
}
// apply the DrugInteractions
if (results.getDrugInteraction().getApplies()) {
response.addCard(CardBuilder.drugInteractionCard(results.getDrugInteraction(), results.getRequest()));
}
}
}
// CQL Executed
requestLog.advanceTimeline(requestService);
if (errorCardOnEmpty) {
if (!foundApplicableRule) {
String msg = "No documentation rules found";
logger.warn(msg + "; summary card sent to client");
response.addCard(CardBuilder.summaryCard(CardTypes.COVERAGE, msg));
}
CardBuilder.errorCardIfNonePresent(CardTypes.COVERAGE, response);
}
// Ading card to requestLog
requestLog.setCardListFromCards(response.getCards());
requestService.edit(requestLog);
return response;
}
use of org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest in project CRD by HL7-DaVinci.
the class CrdRequestCreator method createOrderSelectRequest.
/**
* Generate a order select request that contains a DeviceRequest.
*
* @param patientGender Desired gender of the patient in the request
* @param patientBirthdate Desired birth date of the patient in the request
* @return Fully populated CdsRequest
*/
public static OrderSelectRequest createOrderSelectRequest(Enumerations.AdministrativeGender patientGender, Date patientBirthdate, String patientAddressState, String providerAddressState, Coding requestCoding, Coding statementCoding) {
OrderSelectRequest request = new OrderSelectRequest();
request.setHook(Hook.ORDER_SELECT);
request.setHookInstance(UUID.randomUUID().toString());
OrderSelectContext context = new OrderSelectContext();
request.setContext(context);
context.setUserId("Practitioner/1234");
Patient patient = createPatient(patientGender, patientBirthdate, patientAddressState);
context.setPatientId(patient.getId());
// create and build MedicationRequest
MedicationRequest mr = new MedicationRequest();
mr.setStatus(MedicationRequest.MedicationRequestStatus.DRAFT);
mr.setId("MedicationRequest/123");
mr.setIntent(MedicationRequest.MedicationRequestIntent.ORDER);
PrefetchCallback callback = (p, c) -> {
mr.setPerformer(new Reference(p));
mr.addInsurance(new Reference(c));
};
mr.setSubject(new Reference(patient));
Practitioner provider = createPractitioner();
Bundle prefetchBundle = createPrefetchBundle(patient, provider, callback, providerAddressState);
mr.setMedication(new CodeableConcept().addCoding(requestCoding));
Bundle orderBundle = new Bundle();
Bundle.BundleEntryComponent bec = new Bundle.BundleEntryComponent();
bec.setResource(mr);
orderBundle.addEntry(bec);
Bundle.BundleEntryComponent pfDrBec = new Bundle.BundleEntryComponent();
pfDrBec.setResource(mr);
prefetchBundle.addEntry(pfDrBec);
context.setDraftOrders(orderBundle);
context.setSelections(new String[] { "123" });
Bundle prefetchMedicationStatementBundle = new Bundle();
bec = new Bundle.BundleEntryComponent();
bec.setResource(patient);
prefetchMedicationStatementBundle.addEntry(bec);
bec = new Bundle.BundleEntryComponent();
MedicationStatement ms = new MedicationStatement();
ms.setId("MedciationStatement/12345");
ms.setMedication(new CodeableConcept().addCoding(statementCoding));
bec.setResource(ms);
prefetchMedicationStatementBundle.addEntry(bec);
// add the prefetch into the request
CrdPrefetch prefetch = new CrdPrefetch();
prefetch.setMedicationRequestBundle(prefetchBundle);
prefetch.setMedicationStatementBundle(prefetchMedicationStatementBundle);
request.setPrefetch(prefetch);
return request;
}
Aggregations