Skip to content

Commit

Permalink
Merge pull request #16 from MeasureAuthoringTool/feature/mat-6835-top…
Browse files Browse the repository at this point in the history
…-level-summary

[MAT-6835] Top Level Summary Report
  • Loading branch information
jkotanchik-SB authored Jun 4, 2024
2 parents 05421c0 + d207921 commit 062ec3f
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 171 deletions.
12 changes: 6 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
source "https://rubygems.org"

gem "sinatra"
gem 'sinatra'
gem 'passenger'
gem "rest-client"
gem "cqm-reports", '4.1.0'
gem "rackup", "~> 2.1"
gem "rack-contrib", "~> 2.4"
gem 'rest-client'
gem 'cqm-reports', '4.1.0'
gem 'rackup', '~> 2.1'
gem 'rack-contrib', '~> 2.4'
gem 'jwt'

gem "cqm-models", :git => "https://github.com/projecttacoma/cqm-models", :branch => "master"
gem 'cqm-models', :git => 'https://github.com/projecttacoma/cqm-models', :branch => 'master'

group :test do
gem 'minitest'
Expand Down
2 changes: 1 addition & 1 deletion config.ru
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ require 'bundler'

Bundler.require

require './service/app'
require './service/web_controller'
run Sinatra::Application
142 changes: 80 additions & 62 deletions service/app.rb → service/web_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# frozen_string_literal: true
require "bundler/setup"
require "sinatra"
require "cqm-reports"
require "cqm/models"
require 'bundler/setup'
require 'sinatra'
require 'cqm-reports'
require 'cqm/models'
require 'rest-client'
require "rack"
require "rack/contrib"
require 'rack'
require 'rack/contrib' # Includes the JSONBodyParser middleware
require 'jwt'

puts "Loading QRDA Export Service"
Expand All @@ -26,11 +26,18 @@ def as_json(*args)

use Rack::JSONBodyParser

SCORING = {
"Proportion" => "PROPORTION",
"Ratio" => "RATIO",
"Cohort" => "COHORT",
"Continuous Variable" => "CONTINUOUS_VARIABLE"
POPULATION_ABBR = {
"initialPopulation" => "IPP",
"measurePopulation" => "MSRPOPL",
"measurePopulationExclusion" => "MSRPOPLEX",
"denominator" => "DENOM",
"numerator" => "NUMER",
"numeratorExclusion" => "NUMEX",
"denominatorException" => "DENEXCEP",
"denominatorExclusion" => "DENEX",
"stratification" => "STRAT",
"measureObservation" => "OBSERV",
"measurePopulationObservation" => "OBSERV"
}

# Implementation pre-reqs
Expand All @@ -54,59 +61,37 @@ def as_json(*args)
# 9. Log formatting

put "/api/qrda" do
# Set return type
content_type 'application/json'

#TODO probably don't need access token here, will remove after SME confirmation
# TODO probably don't need access token here, will remove after SME confirmation
access_token = request.env["HTTP_Authorization"]
measure_dto = request.params

# Parse request params
measure_dto = request.params # Uses the Rack::JSONBodyParser middleware

# Prepare CQM Measure
madie_measure = JSON.parse(measure_dto["measure"])
measure = CQM::Measure.new(madie_measure) unless madie_measure.nil?
measure = CQM::Measure.new(madie_measure) unless measure_dto["measure"].nil?
if measure.nil?
return [400, "Measure is empty."]
end

test_cases = measure_dto["testCases"]
source_data_criteria = measure_dto["sourceDataCriteria"]

data_criteria = Array.new
source_data_criteria.each do | criteria |
data_criteria.push build_source_data_criteria(criteria)
end

measure.source_data_criteria = data_criteria
measure.source_data_criteria = build_source_data_criteria(measure_dto["sourceDataCriteria"])
measure.cms_id = measure.cms_id.nil? ? 'CMS0v0' : measure.cms_id
measure.hqmf_id = madie_measure["id"]

test_cases = measure_dto["testCases"]

qrda_errors = {}
html_errors = {}
patients = Array.new
individual_reports = Array.new
generated_reports = Array.new # Array of each Patient's QRDA and HTML summary

# Generate QRDA XMLs and HTML patient summaries
test_cases.each_with_index do | test_case, idx |
qdm_patient = QDM::Patient.new(JSON.parse(test_case["json"]))

patient = CQM::Patient.new
patient.qdmPatient = qdm_patient
patient[:givenNames] = [ test_case["title"] ]
patient[:familyName] = test_case["series"]
patient = build_cqm_patient(idx, test_case)
patients.push patient # For the summary HTML

expected_values = Array.new
if test_case["groupPopulations"]
test_case["groupPopulations"].each do | groupPopulation |
groupPopulation["populationValues"].each do | populationValue |
expected_values.push(populationValue["expected"])
end
end
end
patient[:expectedValues] = expected_values

if patient.qdmPatient.get_data_elements('patient_characteristic', 'payer').empty?
payer_codes = [{ 'code' => '1', 'system' => '2.16.840.1.113883.3.221.5', 'codeSystem' => 'SOP' }]
patient.qdmPatient.dataElements.push QDM::PatientCharacteristicPayer.new(dataElementCodes: payer_codes, relevantPeriod: QDM::Interval.new(patient.qdmPatient.birthDatetime, nil))
end

filename = "#{idx+1}_#{patient[:familyName]}_#{patient[:givenNames][0]}"

# generate QRDA
Expand All @@ -122,24 +107,67 @@ def as_json(*args)
rescue Exception => e
html_errors[patient.id] = e
end
individual_reports.push << {filename:, qrda:, report:}
generated_reports.push << {filename:, qrda:, report:}
end
summary_report = measure_patients_summary(patients, nil, qrda_errors, html_errors, measure)
{ summaryReport: summary_report,individualReports: individual_reports }.to_json
summary_report = summary_report(patients,
qrda_errors,
html_errors,
measure,
measure_dto["groupDTOs"])

return { summaryReport: summary_report, individualReports: generated_reports }.to_json
end

def summary_report(patients, qrda_errors, html_errors, measure, population_results)
erb "top_level_summary".to_sym, {}, {
measure: ,
records: patients,
html_errors: ,
qrda_errors: ,
population_crit_results: population_results,
population_abbr: POPULATION_ABBR
}
end


get "/api/health" do
puts "QRDA Export Service is up"
"QRDA Export Service is up"
end

def build_source_data_criteria(source_data_criteria)
data_criteria = instantiate_model(source_data_criteria["type"])
data_criteria.codeListId = source_data_criteria["oid"]
data_criteria.description = source_data_criteria["description"]
data_criteria = Array.new
source_data_criteria.each do | criteria |
data_criteria.push map_source_data_criteria(criteria)
end
data_criteria
end

def map_source_data_criteria(criteria)
data_criteria = instantiate_model(criteria["type"])
data_criteria.codeListId = criteria["oid"]
data_criteria.description = criteria["description"]
data_criteria
end

def build_cqm_patient(idx, test_case)
qdm_patient = QDM::Patient.new(JSON.parse(test_case["json"]))

patient = CQM::Patient.new
patient[:id] = idx
patient.qdmPatient = qdm_patient
patient[:givenNames] = [test_case["title"]]
patient[:familyName] = test_case["series"]
patient[:pass] = true

if patient.qdmPatient.get_data_elements('patient_characteristic', 'payer').empty?
payer_codes = [{ 'code' => '1', 'system' => '2.16.840.1.113883.3.221.5', 'codeSystem' => 'SOP' }]
patient.qdmPatient.dataElements.push QDM::PatientCharacteristicPayer.new(dataElementCodes: payer_codes,
relevantPeriod: QDM::Interval.new(patient.qdmPatient.birthDatetime, nil))
end
patient
end

def instantiate_model(model_name)
case model_name
when "PatientEntity"
Expand Down Expand Up @@ -262,13 +290,3 @@ def instantiate_model(model_name)
raise "Unsupported data type: #{model_name}"
end
end

def measure_patients_summary(patients, results, qrda_errors, html_errors, measure)
erb "index".to_sym, {}, {
measure: measure,
results: results,
records: patients,
html_errors: html_errors,
qrda_errors: qrda_errors
}
end
11 changes: 5 additions & 6 deletions test/service/app_test.rb → test/service/web_controller_test.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
ENV['APP_ENV'] = 'test'
# $LOAD_PATH.unshift File.expand_path('../../service', __FILE__)

require_relative '../../service/app'
require_relative '../../service/web_controller'
require 'minitest/autorun'
require 'rack/test'

class AppTest < Minitest::Test
class WebControllerTest < Minitest::Test
include Rack::Test::Methods

def app
Expand All @@ -20,10 +20,10 @@ def test_has_a_health_check

def test_qrda_with_empty_payload
put 'api/qrda'

assert_equal 400, last_response.status
end

def test_build_source_data_criteria
def test_map_source_data_criteria
criteria = {
"oid" => "2.16.840.1.113762.1.4.1151.59",
"title" => "Hospital Services for Urology",
Expand All @@ -33,10 +33,9 @@ def test_build_source_data_criteria
"codeId" => nil,
"name" => "Hospital Services for Urology"
}
source_criteria = build_source_data_criteria(criteria)
source_criteria = map_source_data_criteria(criteria)
assert source_criteria.is_a?(QDM::EncounterPerformed)
assert_equal criteria["oid"], source_criteria.codeListId
assert_equal criteria["description"], source_criteria.description
end

end
96 changes: 0 additions & 96 deletions views/index.erb

This file was deleted.

Loading

0 comments on commit 062ec3f

Please sign in to comment.