Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report operation spec update #663

Merged
merged 3 commits into from
Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.opencds.cqf.ruler.api.OperationProvider;
import org.opencds.cqf.ruler.cr.CrConfig;
import org.opencds.cqf.ruler.ra.r4.AssistedServlet;
import org.opencds.cqf.ruler.ra.r4.RACodingGapsProvider;
import org.opencds.cqf.ruler.ra.r4.RemediateProvider;
import org.opencds.cqf.ruler.ra.r4.RiskAdjustmentProvider;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
Expand All @@ -27,7 +28,7 @@ public RAProperties RAProperties() {
@Bean
@Conditional(OnR4Condition.class)
public OperationProvider r4ReportProvider() {
return new org.opencds.cqf.ruler.ra.r4.ReportProvider();
return new RACodingGapsProvider();
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ private RAConstants() {
}

// DaVinci IG constants
public static final String REPORT_ID_PREFIX = "condition-category-report-";
public static final String REPORT_ID_PREFIX = "coding-gaps-";
public static final String REMEDIATE_ID_PREFIX = "remediate-cc-gaps-";
public static final String PATIENT_REPORT_PROFILE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-measurereport-bundle";
public static final String CODING_GAP_BUNDLE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-coding-gap-bundle";
Expand All @@ -28,15 +28,16 @@ private RAConstants() {
public static final String ORIGINAL_ISSUE_PROFILE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-coding-gap-original-detectedissue";
public static final String CLINICAL_EVALUATION_ISSUE_PROFILE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-coding-gap-clinical-evaluation-detectedissue";
public static final String GROUP_REFERENCE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference";
public static final String CODING_GAP_TYPE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/extension-ra-codingGapType";
public static final Extension CODING_GAP_TYPE_EXTENSION = new Extension().addExtension().setUrl(CODING_GAP_TYPE_URL)
public static final String CODING_GAP_REQUEST_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-codingGapRequest";
public static final Extension CODING_GAP_TYPE_EXTENSION = new Extension().addExtension()
.setUrl(CODING_GAP_REQUEST_URL)
.setValue(
new CodeableConcept().addCoding(
new Coding().setSystem("http://hl7.org/fhir/us/davinci-ra/CodeSystem/coding-gap-type")
.setCode("payer-generated")));
public static final CodeableConcept CODING_GAP_CODE = new CodeableConcept().addCoding(
new Coding().setSystem("http://terminology.hl7.org/CodeSystem/v3-ActCode").setCode("CODINGGAP")
.setDisplay("Coding Gaps"));
.setDisplay("Codinggap"));

// Parameter validation constants
public static final String INVALID_PARAMETERS_NAME = "Invalid parameters";
Expand Down
22 changes: 22 additions & 0 deletions plugin/ra/src/main/java/org/opencds/cqf/ruler/ra/RAProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public void setReport(Report report) {
this.report = report;
}

private CompositionConfiguration compositionConfiguration;

public CompositionConfiguration getComposition() {
return compositionConfiguration;
}

public void setComposition(CompositionConfiguration compositionConfiguration) {
this.compositionConfiguration = compositionConfiguration;
}

public static class Report {

private String endpoint;
Expand All @@ -41,4 +51,16 @@ public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
}

public static class CompositionConfiguration {
private String ra_composition_section_author;

public String getCompositionSectionAuthor() {
return ra_composition_section_author;
}

public void setRaCompositionSectionAuthor(String raCompositionSectionAuthor) {
this.ra_composition_section_author = raCompositionSectionAuthor;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
package org.opencds.cqf.ruler.ra.r4;

import static com.google.common.base.Preconditions.checkArgument;
import static org.opencds.cqf.ruler.utility.r4.Parameters.parameters;
import static org.opencds.cqf.ruler.utility.r4.Parameters.part;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import com.google.common.base.Strings;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Composition;
import org.hl7.fhir.r4.model.DetectedIssue;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.MeasureReport;
import org.hl7.fhir.r4.model.Parameters;
import org.opencds.cqf.ruler.behavior.ConfigurationUser;
import org.opencds.cqf.ruler.behavior.ResourceCreator;
import org.opencds.cqf.ruler.behavior.r4.MeasureReportUser;
import org.opencds.cqf.ruler.behavior.r4.ParameterUser;
import org.opencds.cqf.ruler.provider.DaoRegistryOperationProvider;
import org.opencds.cqf.ruler.ra.RAConstants;
import org.opencds.cqf.ruler.ra.RAProperties;
import org.opencds.cqf.ruler.utility.Operations;

import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

public class ReportProvider extends DaoRegistryOperationProvider
implements ParameterUser, ResourceCreator, MeasureReportUser, RiskAdjustmentUser {
@Configurable
public class RACodingGapsProvider extends DaoRegistryOperationProvider
implements ParameterUser, ConfigurationUser, ResourceCreator, MeasureReportUser, RiskAdjustmentUser {

@Autowired
private RAProperties raProperties;

private IdType compositionSectionAuthor;

/**
* Implements the <a href=
* "https://build.fhir.org/ig/HL7/davinci-ra/OperationDefinition-report.html">$ra.report</a>
* "https://build.fhir.org/ig/HL7/davinci-ra/OperationDefinition-ra.coding-gaps.html">$ra.coding-gaps</a>
* operation found in the
* <a href="https://build.fhir.org/ig/HL7/davinci-ra/index.html">Da Vinci Risk
* Adjustment IG</a>.
Expand All @@ -45,9 +58,9 @@ public class ReportProvider extends DaoRegistryOperationProvider
* @return a Parameters with Bundles of MeasureReports and evaluatedResource
* Resources
*/
@Description(shortDefinition = "$ra.report operation", value = "Implements the <a href=\"https://build.fhir.org/ig/HL7/davinci-ra/OperationDefinition-davinci-ra.report.html\">$ra.report</a> operation found in the <a href=\"https://build.fhir.org/ig/HL7/davinci-ra/index.html\">Da Vinci Risk Adjustment IG</a>.")
@Operation(name = "$ra.report", idempotent = true, type = MeasureReport.class)
public Parameters report(
@Description(shortDefinition = "$ra.coding-gaps operation", value = "Implements the <a href=\"https://build.fhir.org/ig/HL7/davinci-ra/OperationDefinition-ra.coding-gaps.html\">$ra.coding-gaps</a> operation found in the <a href=\"https://build.fhir.org/ig/HL7/davinci-ra/index.html\">Da Vinci Risk Adjustment IG</a>.")
@Operation(name = "$ra.coding-gaps", idempotent = true, type = MeasureReport.class)
public Parameters raCodingGaps(
RequestDetails requestDetails,
@OperationParam(name = RAConstants.PERIOD_START, typeName = "date") IPrimitiveType<Date> periodStart,
@OperationParam(name = RAConstants.PERIOD_END, typeName = "date") IPrimitiveType<Date> periodEnd,
Expand All @@ -59,6 +72,11 @@ public Parameters report(
return parameters(part(RAConstants.INVALID_PARAMETERS_NAME,
generateIssue(RAConstants.INVALID_PARAMETERS_SEVERITY, e.getMessage())));
}
try {
validateConfiguration(requestDetails);
} catch (Exception e) {
return parameters(part("Invalid configuration", generateIssue("error", e.getMessage())));
}

ensureSupplementalDataElementSearchParameter(requestDetails);

Expand All @@ -75,7 +93,7 @@ public Parameters report(
} else {
reports.forEach(report -> {
List<DetectedIssue> issues = buildOriginalIssues(report);
Composition composition = buildComposition(subject, report, issues);
Composition composition = buildComposition(subject, report, issues, compositionSectionAuthor);
Bundle bundle = buildCodingGapReportBundle(composition, issues, report);
result.addParameter(part(RAConstants.RETURN_PARAM_NAME,
bundle.setId(UUID.randomUUID().toString())));
Expand All @@ -94,4 +112,13 @@ public void validateParameters(RequestDetails requestDetails) {
Operations.validateSingularPattern(requestDetails, RAConstants.SUBJECT,
Operations.PATIENT_OR_GROUP_REFERENCE);
}

@Override
public void validateConfiguration(RequestDetails theRequestDetails) {
checkArgument(!Strings.isNullOrEmpty(raProperties.getComposition().getCompositionSectionAuthor()),
"The composition.ra_composition_section_author setting is required for the $ra.coding-gaps operation.");
compositionSectionAuthor = new IdType(raProperties.getComposition().getCompositionSectionAuthor());
// This will throw a ResourceNotFound exception if the Organization resource is not loaded in the server
read(compositionSectionAuthor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ default DetectedIssue buildOriginalIssueStart(MeasureReport report, String group
originalIssue.setMeta(new Meta().addProfile(
RAConstants.ORIGINAL_ISSUE_PROFILE_URL).setLastUpdated(new Date()));
originalIssue.addExtension().setUrl(RAConstants.GROUP_REFERENCE_URL).setValue(new StringType(groupId));
originalIssue.addModifierExtension(RAConstants.CODING_GAP_TYPE_EXTENSION);
originalIssue.setStatus(DetectedIssue.DetectedIssueStatus.PRELIMINARY);
originalIssue.setCode(RAConstants.CODING_GAP_CODE);
if (report.getSubject().getReference().startsWith("Patient/")) {
Expand All @@ -188,11 +187,13 @@ default List<DetectedIssue> buildOriginalIssues(MeasureReport report) {
return issues;
}

default List<Bundle> buildCompositionsAndBundles(String subject, Map<MeasureReport, List<DetectedIssue>> issues) {
default List<Bundle> buildCompositionsAndBundles(String subject, Map<MeasureReport, List<DetectedIssue>> issues,
IdType compositionSectionAuthor) {
List<Bundle> raBundles = new ArrayList<>();
for (Map.Entry<MeasureReport, List<DetectedIssue>> issuesSet : issues.entrySet()) {
raBundles.add(buildCodingGapReportBundle(buildComposition(
subject, issuesSet.getKey(), issuesSet.getValue()), issuesSet.getValue(), issuesSet.getKey()));
subject, issuesSet.getKey(), issuesSet.getValue(), compositionSectionAuthor),
issuesSet.getValue(), issuesSet.getKey()));
}

return raBundles;
Expand Down Expand Up @@ -232,14 +233,17 @@ default void resolveIssues(Composition composition, MeasureReport report, List<D
);
}

default Composition buildComposition(String subject, MeasureReport report, List<DetectedIssue> issues) {
default Composition buildComposition(String subject, MeasureReport report,
List<DetectedIssue> issues, IdType compositionSectionAuthor) {
Composition composition = new Composition();
composition.setMeta(RAConstants.COMPOSITION_META);
composition.setIdentifier(
new Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:uuid:" + UUID.randomUUID()));
composition.setStatus(Composition.CompositionStatus.PRELIMINARY)
.setType(RAConstants.COMPOSITION_TYPE).setSubject(new Reference(subject))
.setDate(Date.from(Instant.now()));
.setDate(Date.from(Instant.now()))
.setAuthor(Collections.singletonList(new Reference(compositionSectionAuthor)))
.setTitle("Risk Adjustment Coding Gaps Report for " + subject);
resolveIssues(composition, report, issues);
return composition;
}
Expand Down
12 changes: 7 additions & 5 deletions plugin/ra/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
hapi:
fhir:
ra:
enabled: true
report:
endpoint: ''
fhir:
ra:
enabled: true
report:
endpoint: ''
composition:
ra_composition_section_author: Organization/alphora-author
Loading