cqm-models 1.1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8466e14ed7d3500909a79c6efba50d1213ae2682defbb4ba43f74748bfe0328a
4
- data.tar.gz: 48a6f30ce90a0937fdbe904380596bf33ecda6d404342f24df1f13e1b02a9227
3
+ metadata.gz: 453a6d2a2d21dbbccbf15183693d0961004c6d2dc5d6e29cef52dbdeec81d0c9
4
+ data.tar.gz: 0c8a483ca5cc294cb67c98790010e3eb1821a40a4a4f613cdf143bc5d1443122
5
5
  SHA512:
6
- metadata.gz: 0f41eb728b0b7134729f1a02ce4687cc297c22f8aede293c2b0cc292af53a11fe73dc4cd56fe9fcbbb1572c92d5e7a39af2f1c369d0aee07b8fa1eac82356aee
7
- data.tar.gz: 3fe0418d0f56139048524f27af04e04774af8e13ddae2a2b930d4ff5f80ed018b5deb6c9bf5aea026840ded58f716815895dc707211ecbbdb7b9be3a2fcd2d94
6
+ metadata.gz: 4c7776a8b071aea930ea925c36b8074b5bcf25ab30e9ca208020dfb94d6d9c77540e5a437b0b82331ea27949ead287842f36fad20ee94ee5a0b055e60a108a1b
7
+ data.tar.gz: 63eca8a60d51e17c611c85408fc5446670b70b410c74829a5d95af3c4ab3937ea3a4db8736c502f8603d794ee328da5a82f79d402ca5ef31491d90f1f2509ff0
@@ -3,7 +3,7 @@ matrix:
3
3
  - language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.4.1
6
+ - 2.4.6
7
7
  services:
8
8
  - mongodb
9
9
  before_install:
@@ -10,20 +10,19 @@ function RecursiveCast(any) {
10
10
  if (any && any.value && any.unit) {
11
11
  return new cql.Quantity(any);
12
12
  }
13
- if (any && any.code && any.codeSystem) {
13
+ if (any && any.code && (any.codeSystemOid || any.system)) {
14
14
  if (typeof any.code === 'undefined') {
15
15
  throw new Error(`Code: ${any} does not have a code`);
16
- } else if (typeof any.codeSystem === 'undefined') {
17
- throw new Error(`Code: ${any} does not have a codeSystem`);
16
+ } else if (typeof any.codeSystemOid === 'undefined' && typeof any.system === 'undefined') {
17
+ throw new Error(`Code: ${any} does not have a code system oid`);
18
18
  }
19
19
 
20
- const val = { code: any.code, codeSystem: any.codeSystem };
20
+ const val = { code: any.code, codeSystemOid: any.codeSystemOid || any.system };
21
21
 
22
22
  val.descriptor = (typeof any.descriptor !== 'undefined') ? any.descriptor : null;
23
- val.codeSystemOid = (typeof any.codeSystemOid !== 'undefined') ? any.codeSystemOid : null;
24
23
  val.version = (typeof any.version !== 'undefined') ? any.version : null;
25
24
 
26
- return new cql.Code(val.code, val.codeSystem, val.version, val.descriptor);
25
+ return new cql.Code(val.code, val.codeSystemOid, val.version, val.descriptor);
27
26
  }
28
27
  if (any && any.low) {
29
28
  const casted = new cql.Interval(any.low, any.high, any.lowClosed, any.highClosed);
@@ -9,20 +9,19 @@ Code.prototype = Object.create(mongoose.SchemaType.prototype);
9
9
  Code.prototype.cast = (code) => {
10
10
  if (code != null) {
11
11
  // handles codes that have not yet been cast to a code and those that have already been cast to a code
12
- if (code.code && (code.codeSystem || code.system)) {
12
+ if (code.code && (code.codeSystemOid || code.system)) {
13
13
  if (typeof code.code === 'undefined') {
14
14
  throw new Error(`Code: ${code} does not have a code`);
15
- } else if (typeof code.codeSystem === 'undefined' && typeof code.system === 'undefined') {
16
- throw new Error(`Code: ${code} does not have a system`);
15
+ } else if (typeof code.codeSystemOid === 'undefined' && typeof code.system === 'undefined') {
16
+ throw new Error(`Code: ${code} does not have a system oid`);
17
17
  }
18
18
 
19
- const val = { code: code.code, codeSystem: code.codeSystem || code.system };
19
+ const val = { code: code.code, codeSystemOid: code.codeSystemOid || code.system };
20
20
 
21
21
  val.descriptor = (typeof code.descriptor !== 'undefined') ? code.descriptor : null;
22
- val.codeSystemOid = (typeof code.codeSystemOid !== 'undefined') ? code.codeSystemOid : null;
23
22
  val.version = (typeof code.version !== 'undefined') ? code.version : null;
24
23
 
25
- return new cql.Code(val.code, val.codeSystem, val.version, val.descriptor);
24
+ return new cql.Code(val.code, val.codeSystemOid, val.version, val.descriptor);
26
25
  }
27
26
  throw new Error(`Expected a code. Received ${code}.`);
28
27
  } else {
@@ -25,7 +25,7 @@ function DataElementSchema(add, options) {
25
25
  // Returns all of the codes on this data element in a format usable by
26
26
  // the cql-execution framework.
27
27
  extended.methods.getCode = function getCode() {
28
- return this.dataElementCodes.map(code => new cql.Code(code.code, code.codeSystem, code.version, code.descriptor));
28
+ return this.dataElementCodes.map(code => new cql.Code(code.code, code.codeSystemOid, code.version, code.descriptor));
29
29
  };
30
30
 
31
31
  // Return the first code on this data element in a format usable by
@@ -33,7 +33,7 @@ function DataElementSchema(add, options) {
33
33
  extended.methods.code = function code() {
34
34
  if (this.dataElementCodes && this.dataElementCodes[0]) {
35
35
  const qdmCode = this.dataElementCodes[0];
36
- return new cql.Code(qdmCode.code, qdmCode.codeSystem, qdmCode.version, qdmCode.descriptor);
36
+ return new cql.Code(qdmCode.code, qdmCode.codeSystemOid, qdmCode.version, qdmCode.descriptor);
37
37
  }
38
38
  return null;
39
39
  };
@@ -1,5 +1,6 @@
1
1
  const mongoose = require('mongoose/browser');
2
2
  const cql = require('cql-execution');
3
+ const DateTime = require('./DateTime');
3
4
 
4
5
  function Interval(key, options) {
5
6
  mongoose.SchemaType.call(this, key, options, 'Interval');
@@ -7,8 +8,8 @@ function Interval(key, options) {
7
8
  Interval.prototype = Object.create(mongoose.SchemaType.prototype);
8
9
 
9
10
  Interval.prototype.cast = (interval) => {
10
- if (typeof interval.low === 'undefined' || interval.low === null) {
11
- throw new Error(`Interval: ${interval} does not have a low value`);
11
+ if (interval.isInterval) {
12
+ return interval;
12
13
  }
13
14
  const casted = new cql.Interval(interval.low, interval.high, interval.lowClosed, interval.highClosed);
14
15
 
@@ -22,11 +23,12 @@ Interval.prototype.cast = (interval) => {
22
23
  }
23
24
 
24
25
  // Cast to DateTime if it is a string representing a DateTime
25
- if (casted.low && Date.parse(casted.low)) {
26
- casted.low = cql.DateTime.fromJSDate(new Date(casted.low), 0);
26
+ if (casted.low) {
27
+ casted.low = DateTime.prototype.cast(casted.low);
27
28
  }
28
- if (casted.high && Date.parse(casted.high)) {
29
- casted.high = cql.DateTime.fromJSDate(new Date(casted.high), 0);
29
+
30
+ if (casted.high) {
31
+ casted.high = DateTime.prototype.cast(casted.high);
30
32
  }
31
33
  return casted;
32
34
  };
@@ -22,3 +22,5 @@ module.exports.Patient = require('./Patient.js').Patient;
22
22
  module.exports.PatientSchema = require('./Patient.js').PatientSchema;
23
23
  module.exports.Provider = require('./Provider.js').Provider;
24
24
  module.exports.ProviderSchema = require('./Provider.js').ProviderSchema;
25
+ module.exports.IndividualResult = require('./IndividualResult.js').IndividualResult;
26
+ module.exports.IndividualResultSchema = require('./IndividualResult.js').IndividualResultSchema;
@@ -0,0 +1,28 @@
1
+ const mongoose = require('mongoose/browser');
2
+
3
+ const [String, Mixed] = [
4
+ mongoose.Schema.Types.String,
5
+ mongoose.Schema.Types.Mixed,
6
+ ];
7
+
8
+ const ClauseResultSchema = mongoose.Schema({
9
+ // Library the clause this result is for is in
10
+ library_name: String,
11
+ // Statement the clause this result is for is in
12
+ statement_name: String,
13
+ // LocalId of the clause this result is for
14
+ localId: String,
15
+ // Final, processed result of raw calculation
16
+ final: String,
17
+ // Raw result of clause calculation
18
+ raw: Mixed,
19
+ });
20
+
21
+
22
+ module.exports.ClauseResultSchema = ClauseResultSchema;
23
+ class ClauseResult extends mongoose.Document {
24
+ constructor(object) {
25
+ super(object, ClauseResultSchema);
26
+ }
27
+ }
28
+ module.exports.ClauseResult = ClauseResult;
@@ -1,4 +1,6 @@
1
1
  const mongoose = require('mongoose/browser');
2
+ const { ClauseResultSchema } = require('./ClauseResult');
3
+ const { StatementResultSchema } = require('./StatementResult');
2
4
 
3
5
  const [Number, String, Mixed, ObjectId] = [
4
6
  mongoose.Schema.Types.Number,
@@ -22,9 +24,11 @@ const IndividualResultSchema = mongoose.Schema(
22
24
  MSRPOPLEX: Number,
23
25
 
24
26
  // Result Attributes
25
- clause_results: Mixed,
27
+ clause_results: [ClauseResultSchema],
28
+ statement_results: [StatementResultSchema],
29
+ population_relevance: Mixed,
26
30
  episode_results: Mixed,
27
- statement_results: Mixed,
31
+ observation_values: [Number],
28
32
 
29
33
  // This field is for application specific information only. If both Bonnie and
30
34
  // Cypress use a common field, it should be made a field on this model,
@@ -53,6 +57,28 @@ const IndividualResultSchema = mongoose.Schema(
53
57
  }
54
58
  );
55
59
 
60
+ IndividualResultSchema.methods.clause_results_by_clause = function clause_results_by_clause() {
61
+ const clause_results_hash = {};
62
+ this.clause_results.forEach((result) => {
63
+ if (!clause_results_hash[result.library_name]) {
64
+ clause_results_hash[result.library_name] = {};
65
+ }
66
+ clause_results_hash[result.library_name][result.localId] = result;
67
+ });
68
+ return clause_results_hash;
69
+ };
70
+
71
+ IndividualResultSchema.methods.statement_results_by_statement = function statement_results_by_statement() {
72
+ const statement_results_hash = {};
73
+ this.statement_results.forEach((result) => {
74
+ if (!statement_results_hash[result.library_name]) {
75
+ statement_results_hash[result.library_name] = {};
76
+ }
77
+ statement_results_hash[result.library_name][result.statement_name] = result;
78
+ });
79
+ return statement_results_hash;
80
+ };
81
+
56
82
  module.exports.IndividualResultSchema = IndividualResultSchema;
57
83
  class IndividualResult extends mongoose.Document {
58
84
  constructor(object) {
@@ -64,7 +64,7 @@ const MeasureSchema = new mongoose.Schema(
64
64
  // HQMF/Tacoma-specific Measure-logic related data
65
65
  population_criteria: Mixed,
66
66
  source_data_criteria: [],
67
- measure_period: Interval,
67
+ measure_period: Mixed,
68
68
  measure_attributes: [],
69
69
 
70
70
  population_sets: [PopulationSetSchema],
@@ -0,0 +1,41 @@
1
+ const mongoose = require('mongoose/browser');
2
+
3
+ const [String, Mixed] = [
4
+ mongoose.Schema.Types.String,
5
+ mongoose.Schema.Types.Mixed,
6
+ ];
7
+
8
+ const StatementResultSchema = mongoose.Schema({
9
+ // Library the statement this result is for is in
10
+ library_name: String,
11
+ // Statement this result is for is in
12
+ statement_name: String,
13
+ // Result, processed for display, of the statement this result is for
14
+ pretty: String,
15
+ // Final, processed result of raw calculation
16
+ final: String,
17
+ // Raw result of clause calculation
18
+ raw: Mixed,
19
+ /*
20
+ * 'NA' - Not applicable. This statement is not relevant to any population calculation in this population_set. Common
21
+ * for unused library statements or statements only used for other population sets.
22
+ *
23
+ * 'FALSE' - This statement is not relevant to any of this patient's population inclusion calculations.
24
+ *
25
+ * 'TRUE' - This statement is relevant for one or more of the population inclusion calculations.
26
+ */
27
+ relevance: {
28
+ type: String,
29
+ enum: ['NA', 'TRUE', 'FALSE'],
30
+ default: 'NA',
31
+ },
32
+ });
33
+
34
+
35
+ module.exports.StatementResultSchema = StatementResultSchema;
36
+ class StatementResult extends mongoose.Document {
37
+ constructor(object) {
38
+ super(object, StatementResultSchema);
39
+ }
40
+ }
41
+ module.exports.StatementResult = StatementResult;
@@ -20,5 +20,9 @@ module.exports.ValueSet = require('./cqm/ValueSet.js').ValueSet;
20
20
  module.exports.ValueSetSchema = require('./cqm/ValueSet.js').ValueSetSchema;
21
21
  module.exports.Concept = require('./cqm/Concept.js').Concept;
22
22
  module.exports.ConceptSchema = require('./cqm/Concept.js').ConceptSchema;
23
- module.exports.IndividualResult = require('./IndividualResult').IndividualResult;
24
- module.exports.IndividualResultSchema = require('./IndividualResult').IndividualResultSchema;
23
+ module.exports.IndividualResult = require('./cqm/IndividualResult.js').IndividualResult;
24
+ module.exports.IndividualResultSchema = require('./cqm/IndividualResult.js').IndividualResultSchema;
25
+ module.exports.ClauseResult = require('./cqm/ClauseResult.js').ClauseResult;
26
+ module.exports.ClauseResultSchema = require('./cqm/ClauseResult.js').ClauseResultSchema;
27
+ module.exports.StatementResult = require('./cqm/StatementResult.js').StatementResult;
28
+ module.exports.StatementResultSchema = require('./cqm/StatementResult.js').StatementResultchema;
@@ -0,0 +1,21 @@
1
+ module CQM
2
+ # ClauseResult is used to store clause result information in IndividualResult
3
+ class ClauseResult
4
+ include Mongoid::Document
5
+ include Mongoid::Timestamps
6
+
7
+ # Library the clause this result is for is in
8
+ field :library_name, type: String
9
+ # Statment the clause this result is for is in
10
+ field :statement_name, type: String
11
+ # LocalId of the clause this result is for
12
+ field :localId, type: String
13
+ # Final, processed result of raw calculation
14
+ field :final, type: String
15
+ # Raw result of clause calculation
16
+ field :raw
17
+
18
+ # Relations to other model classes
19
+ embedded_in :individual_result
20
+ end
21
+ end
@@ -1,4 +1,4 @@
1
- module QDM
1
+ module CQM
2
2
  # IndividualResult stores the patient-level (population/clause) results for a patient/measure combination
3
3
  class IndividualResult
4
4
  include Mongoid::Document
@@ -20,9 +20,11 @@ module QDM
20
20
  field :MSRPOPLEX, type: Integer
21
21
 
22
22
  # Result Attributes
23
- field :clause_results, type: Hash
23
+ embeds_many :clause_results
24
+ embeds_many :statement_results
24
25
  field :episode_results, type: Hash
25
- field :statement_results, type: Hash
26
+ field :observation_values, type: Array, default: []
27
+ field :population_relevance, type: Hash
26
28
 
27
29
  # This field is for application specific information only. If both Bonnie and
28
30
  # Cypress use a common field, it should be made a field on this model,
@@ -35,5 +37,28 @@ module QDM
35
37
  # Relations to other model classes
36
38
  belongs_to :measure
37
39
  belongs_to :patient
40
+
41
+ # Convert the stored array into a hash between clause and result
42
+ def clause_results_by_clause
43
+ clause_results_hash = {}
44
+ clause_results.each do |result|
45
+ unless clause_results_hash[result['library_name']]
46
+ clause_results_hash[result['library_name']] = {}
47
+ end
48
+ clause_results_hash[result['library_name']][result['localId']] = result
49
+ end
50
+ return clause_results_hash
51
+ end
52
+
53
+ def statement_results_by_statement
54
+ statement_results_hash = {}
55
+ statement_results.each do |result|
56
+ unless statement_results_hash[result['library_name']]
57
+ statement_results_hash[result['library_name']] = {}
58
+ end
59
+ statement_results_hash[result['library_name']][result['statement_name']] = result
60
+ end
61
+ return statement_results_hash
62
+ end
38
63
  end
39
64
  end
@@ -73,6 +73,8 @@ module CQM
73
73
  # hence the 'inverse_of: nil')
74
74
  has_and_belongs_to_many :value_sets, inverse_of: nil
75
75
 
76
+ has_many :calculation_results, class_name: 'CQM::IndividualResult'
77
+
76
78
  def all_stratifications
77
79
  population_sets.flat_map(&:stratifications)
78
80
  end
@@ -11,6 +11,7 @@ module CQM
11
11
 
12
12
  has_and_belongs_to_many :providers, class_name: 'CQM::Provider'
13
13
  embeds_one :qdmPatient, class_name: 'QDM::Patient', autobuild: true
14
+ has_many :calculation_results, class_name: 'CQM::IndividualResult'
14
15
 
15
16
  # Include '_type' in any JSON output. This is necessary for deserialization.
16
17
  def to_json(options = nil)
@@ -0,0 +1,27 @@
1
+ module CQM
2
+ # StatementResult is used to store statement result information in IndividualResult
3
+ class StatementResult
4
+ include Mongoid::Document
5
+ include Mongoid::Timestamps
6
+
7
+ # These are the Mongoid equivalent of the Mongoose "enum" attribute for the respective fields.
8
+ # They throw an error if you try to assign a value that's not in the array.
9
+ validates_inclusion_of :relevance, in: %w[NA TRUE FALSE]
10
+
11
+ # Library the clause this result is for is in
12
+ field :library_name, type: String
13
+ # Statment the clause this result is for is in
14
+ field :statement_name, type: String
15
+ # LocalId of the clause this result is for
16
+ field :pretty, type: String
17
+ # Final, processed result of raw calculation
18
+ field :final, type: String
19
+ # Raw result of clause calculation
20
+ field :raw
21
+
22
+ field :relevance, type: String
23
+
24
+ # Relations to other model classes
25
+ embedded_in :individual_result
26
+ end
27
+ end
@@ -29,7 +29,9 @@ require_relative 'cqm/cql_library'
29
29
  require_relative 'cqm/population_set'
30
30
  require_relative 'cqm/patient'
31
31
  require_relative 'cqm/provider'
32
- require_relative 'qdm/tacoma/individual_result'
32
+ require_relative 'cqm/individual_result'
33
+ require_relative 'cqm/statement_result'
34
+ require_relative 'cqm/clause_result'
33
35
 
34
36
  # Make Patient Generation Available
35
37
  require_relative '../../lib/generate_patients'
@@ -4,7 +4,7 @@ module QDM
4
4
  attr_accessor :code, :codeSystem, :descriptor, :codeSystemOid, :version
5
5
 
6
6
  # Code and code system are required (at minimum).
7
- def initialize(code, codeSystem, descriptor = nil, codeSystemOid = nil, version = nil)
7
+ def initialize(code, codeSystemOid, descriptor = nil, codeSystem = nil, version = nil)
8
8
  @code = code
9
9
  @codeSystem = codeSystem
10
10
  @descriptor = descriptor
@@ -14,7 +14,7 @@ module QDM
14
14
 
15
15
  # Converts an object of this instance into a database friendly value.
16
16
  def mongoize
17
- { code: @code, codeSystem: @codeSystem, descriptor: @descriptor, codeSystemOid: @codeSystemOid, version: @version, _type: 'QDM::Code' }
17
+ { code: @code, codeSystemOid: @codeSystemOid, descriptor: @descriptor, codeSystem: @codeSystem, version: @version, _type: 'QDM::Code' }
18
18
  end
19
19
 
20
20
  class << self
@@ -26,7 +26,7 @@ module QDM
26
26
  def demongoize(object)
27
27
  return nil unless object
28
28
  object = object.symbolize_keys
29
- QDM::Code.new(object[:code], object[:codeSystem], object[:descriptor], object[:codeSystemOid], object[:version])
29
+ QDM::Code.new(object[:code], object[:codeSystemOid], object[:descriptor], object[:codeSystem], object[:version])
30
30
  end
31
31
 
32
32
  # Takes any possible object and converts it to how it would be
@@ -37,8 +37,8 @@ module QDM
37
37
  when QDM::Code then object.mongoize
38
38
  when Hash
39
39
  object = object.symbolize_keys
40
- codeSystem = object[:system] ? object[:system] : object[:codeSystem]
41
- QDM::Code.new(object[:code], codeSystem, object[:descriptor], object[:codeSystemOid], object[:version]).mongoize
40
+ codeSystemOid = object[:system] ? object[:system] : object[:codeSystemOid]
41
+ QDM::Code.new(object[:code], codeSystemOid, object[:descriptor], object[:codeSystem], object[:version]).mongoize
42
42
  else object
43
43
  end
44
44
  end