Skip to content

Commit

Permalink
Report operation spec update (#663)
Browse files Browse the repository at this point in the history
* #660: added author to composition, renamed operation, removed codingGapType extension, updated tests

* #660: added composition author to config properties, added author and title to composition, updated tests

* Update RA report requstType extension name

Co-authored-by: rob-reynolds <rob@alphora.com>
  • Loading branch information
c-schuler and rob-reynolds authored Nov 10, 2022
1 parent 2d47c1b commit 2a8102f
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 56 deletions.
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

0 comments on commit 2a8102f

Please sign in to comment.