cqm-models 4.1.0 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +7 -8
- data/app/assets/javascripts/QDMPatient.js +25 -2
- data/app/assets/javascripts/attributes/Component.js +17 -0
- data/app/assets/javascripts/attributes/Entity.js +17 -0
- data/app/assets/javascripts/basetypes/Any.js +1 -1
- data/app/assets/javascripts/basetypes/AnyEntity.js +1 -1
- data/app/models/cqm/individual_result.rb +2 -2
- data/app/models/cqm/measure.rb +1 -1
- data/app/models/cqm/patient.rb +1 -1
- data/app/models/cqm/provider.rb +0 -2
- data/app/models/qdm/attributes/identifier.rb +2 -0
- data/app/models/qdm/basetypes/data_element.rb +3 -1
- data/cqm-models.gemspec +5 -5
- data/dist/browser.js +3437 -1168
- data/dist/index.js +3437 -1168
- data/jest.config.js +16 -0
- data/package-lock.json +12937 -0
- data/package.json +15 -11
- data/templates/mongoose_template.js.erb +17 -0
- data/templates/patient_template.js.erb +25 -2
- data/yarn.lock +2636 -1375
- metadata +25 -24
- data/.github/workflows/gitleaks_github_actions.yml +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b776247323332ba61b8df7b85393f9cc69e8388d15dc3d55a4d7bfcfd3d2be2
|
4
|
+
data.tar.gz: 57d99f0316933ab3886aa50e25a65c791d0996ff8b7d9cd38766f056b22a9793
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b79ea33f45b11872d85be3c2f5765c2400c11b43e9004f8c7701508bf9b5565e7f8f961c09bb0337be1b6ab7b1cc0701ed72d3b8ccb506ccdc378a74bef77379
|
7
|
+
data.tar.gz: f4c50758a5342921502da3389e2410c05d1a0004e6f9072cf9216cbb5b987ad3960353dbc896b9b6dece71903e897000a59f29ac8c0ce1c8273a918a16da0e58
|
data/.github/workflows/ci.yml
CHANGED
@@ -12,21 +12,21 @@ jobs:
|
|
12
12
|
|
13
13
|
strategy:
|
14
14
|
matrix:
|
15
|
-
ruby-version: [
|
16
|
-
mongodb-version: [4.
|
17
|
-
node-version: [
|
15
|
+
ruby-version: [3.0]
|
16
|
+
mongodb-version: [4.2, 4.4]
|
17
|
+
node-version: [18.x]
|
18
18
|
|
19
19
|
steps:
|
20
|
-
- uses: actions/checkout@
|
20
|
+
- uses: actions/checkout@v3
|
21
21
|
- name: Use Ruby ${{ matrix.ruby-version }}
|
22
22
|
uses: ruby/setup-ruby@v1
|
23
23
|
with:
|
24
24
|
ruby-version: ${{ matrix.ruby-version }}
|
25
|
-
bundler: 2.
|
25
|
+
bundler: 2.3.17
|
26
26
|
- name: Install dependencies
|
27
27
|
run: bundle install
|
28
28
|
- name: Start MongoDB
|
29
|
-
uses: supercharge/mongodb-github-action@1.
|
29
|
+
uses: supercharge/mongodb-github-action@1.10.0
|
30
30
|
with:
|
31
31
|
mongodb-version: ${{ matrix.mongodb-version }}
|
32
32
|
- name: Run audit
|
@@ -38,7 +38,7 @@ jobs:
|
|
38
38
|
- name: Run rubocop
|
39
39
|
run: bundle exec rubocop
|
40
40
|
- name: Use Node.js ${{ matrix.node-version }}
|
41
|
-
uses: actions/setup-node@
|
41
|
+
uses: actions/setup-node@v3
|
42
42
|
with:
|
43
43
|
node-version: ${{ matrix.node-version }}
|
44
44
|
- name: Install Yarn
|
@@ -53,4 +53,3 @@ jobs:
|
|
53
53
|
run: |
|
54
54
|
./bin/validate_dist.sh
|
55
55
|
./bin/validate_browser.sh
|
56
|
-
./bin/validate_generator.sh
|
@@ -3,6 +3,7 @@ const Code = require('./basetypes/Code');
|
|
3
3
|
const Interval = require('./basetypes/Interval');
|
4
4
|
const Quantity = require('./basetypes/Quantity');
|
5
5
|
const DateTime = require('./basetypes/DateTime');
|
6
|
+
const AnyEntity = require('./basetypes/AnyEntity');
|
6
7
|
const AllDataElements = require('./AllDataElements');
|
7
8
|
|
8
9
|
const [Schema, Number, String, Mixed] = [
|
@@ -94,6 +95,12 @@ QDMPatientSchema.methods.getDataElements = function getDataElements(params) {
|
|
94
95
|
return this.dataElements;
|
95
96
|
};
|
96
97
|
|
98
|
+
QDMPatientSchema.methods.addMethodsTo = function addMethodsTo(obj, methods) {
|
99
|
+
Object.entries(methods).forEach(([method_name, method]) => {
|
100
|
+
obj[method_name] = method;
|
101
|
+
});
|
102
|
+
};
|
103
|
+
|
97
104
|
// Returns an array of dataElements that exist on the patient, queried by
|
98
105
|
// QDM profile
|
99
106
|
// @param {string} profile - the data criteria requested by the execution engine
|
@@ -105,10 +112,26 @@ QDMPatientSchema.methods.getByProfile = function getByProfile(profile, isNegated
|
|
105
112
|
// If isNegated == null, return all matching data elements by type, regardless of negationRationale.
|
106
113
|
const results = this.dataElements.filter(element => (element._type === `QDM::${profile}` || element._type === profile) && (isNegated === null || !!element.negationRationale === isNegated));
|
107
114
|
return results.map((result) => {
|
115
|
+
// we need to convert mongoose document to an object.
|
116
|
+
// This is required for comparing the two objects(in cql-execution) as we can't compare two mongoose documents.
|
108
117
|
const removedMongooseItems = new AllDataElements[profile](result).toObject({ virtuals: true });
|
109
118
|
// toObject() will remove all mongoose functions but also remove the schema methods, so we add them back
|
110
|
-
|
111
|
-
|
119
|
+
this.addMethodsTo(removedMongooseItems, result.schema.methods);
|
120
|
+
// add methods to entities
|
121
|
+
Object.entries(result).forEach(([key, values]) => {
|
122
|
+
// entities are always an array
|
123
|
+
if (Array.isArray(values)) {
|
124
|
+
try {
|
125
|
+
// check if the attribute is of Entity
|
126
|
+
if (AnyEntity.prototype.cast(values[0])) {
|
127
|
+
values.forEach((value, index) => {
|
128
|
+
const entity = removedMongooseItems[key][index];
|
129
|
+
this.addMethodsTo(entity, value.schema.methods);
|
130
|
+
});
|
131
|
+
}
|
132
|
+
// eslint-disable-next-line no-empty
|
133
|
+
} catch (e) {}
|
134
|
+
}
|
112
135
|
});
|
113
136
|
return removedMongooseItems;
|
114
137
|
});
|
@@ -44,6 +44,23 @@ function ComponentSchemaFunction(add, options) {
|
|
44
44
|
extended.add(add);
|
45
45
|
}
|
46
46
|
|
47
|
+
/* eslint no-underscore-dangle: 0 */
|
48
|
+
extended.methods._is = function _is(typeSpecifier) {
|
49
|
+
return this._typeHierarchy().some(
|
50
|
+
t => t.type === typeSpecifier.type && t.name === typeSpecifier.name
|
51
|
+
);
|
52
|
+
};
|
53
|
+
|
54
|
+
extended.methods._typeHierarchy = function _typeHierarchy() {
|
55
|
+
const typeName = this._type.replace(/QDM::/, '');
|
56
|
+
const ver = this.qdmVersion.replace('.', '_');
|
57
|
+
return [
|
58
|
+
{
|
59
|
+
name: `{urn:healthit-gov:qdm:v${ver}}${typeName}`,
|
60
|
+
type: 'NamedTypeSpecifier',
|
61
|
+
},
|
62
|
+
];
|
63
|
+
};
|
47
64
|
return extended;
|
48
65
|
}
|
49
66
|
|
@@ -51,6 +51,23 @@ function EntitySchemaFunction(add, options) {
|
|
51
51
|
extended.add(add);
|
52
52
|
}
|
53
53
|
|
54
|
+
/* eslint no-underscore-dangle: 0 */
|
55
|
+
extended.methods._is = function _is(typeSpecifier) {
|
56
|
+
return this._typeHierarchy().some(
|
57
|
+
t => t.type === typeSpecifier.type && t.name === typeSpecifier.name
|
58
|
+
);
|
59
|
+
};
|
60
|
+
|
61
|
+
extended.methods._typeHierarchy = function _typeHierarchy() {
|
62
|
+
const typeName = this._type.replace(/QDM::/, '');
|
63
|
+
const ver = this.qdmVersion.replace('.', '_');
|
64
|
+
return [
|
65
|
+
{
|
66
|
+
name: `{urn:healthit-gov:qdm:v${ver}}${typeName}`,
|
67
|
+
type: 'NamedTypeSpecifier',
|
68
|
+
},
|
69
|
+
];
|
70
|
+
};
|
54
71
|
return extended;
|
55
72
|
}
|
56
73
|
|
@@ -7,7 +7,7 @@ function Any(key, options) {
|
|
7
7
|
Any.prototype = Object.create(mongoose.SchemaType.prototype);
|
8
8
|
|
9
9
|
function RecursiveCast(any) {
|
10
|
-
if (any && any.value && any.unit) {
|
10
|
+
if (any && any.value !== undefined && any.unit) {
|
11
11
|
return new cql.Quantity(any.value, any.unit);
|
12
12
|
}
|
13
13
|
|
@@ -15,7 +15,7 @@ AnyEntity.prototype.cast = (entity) => {
|
|
15
15
|
return null;
|
16
16
|
}
|
17
17
|
|
18
|
-
if (entity instanceof PatientEntity || entity instanceof Practitioner || entity instanceof CarePartner || entity instanceof Organization) {
|
18
|
+
if (entity instanceof PatientEntity || entity instanceof Practitioner || entity instanceof CarePartner || entity instanceof Organization || entity instanceof Location) {
|
19
19
|
return entity;
|
20
20
|
}
|
21
21
|
|
@@ -35,8 +35,8 @@ module CQM
|
|
35
35
|
field :state, type: String, default: 'queued'
|
36
36
|
|
37
37
|
# Relations to other model classes
|
38
|
-
belongs_to :measure
|
39
|
-
belongs_to :patient
|
38
|
+
belongs_to :measure, class_name: 'CQM::Measure', inverse_of: :calculation_result
|
39
|
+
belongs_to :patient, class_name: 'CQM::Patient', inverse_of: :calculation_result
|
40
40
|
|
41
41
|
# Convert the stored array into a hash between clause and result
|
42
42
|
def clause_results_by_clause
|
data/app/models/cqm/measure.rb
CHANGED
@@ -73,7 +73,7 @@ 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'
|
76
|
+
has_many :calculation_results, class_name: 'CQM::IndividualResult', inverse_of: :measure
|
77
77
|
|
78
78
|
def all_stratifications
|
79
79
|
population_sets.flat_map(&:stratifications)
|
data/app/models/cqm/patient.rb
CHANGED
@@ -11,7 +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
|
+
has_many :calculation_results, class_name: 'CQM::IndividualResult', inverse_of: :patient
|
15
15
|
|
16
16
|
# Include '_type' in any JSON output. This is necessary for deserialization.
|
17
17
|
def to_json(options = nil)
|
data/app/models/cqm/provider.rb
CHANGED
@@ -76,7 +76,9 @@ module QDM
|
|
76
76
|
elsif field == 'facilityLocation'
|
77
77
|
facility_location = send(field)
|
78
78
|
unless facility_location.nil?
|
79
|
-
|
79
|
+
# Guessing something changed in mongoid such that facility_location gets typed to an Object
|
80
|
+
# but this method (I think) expects a Hash.
|
81
|
+
shift_facility_location_dates(facility_location.attributes, seconds)
|
80
82
|
send(field + '=', facility_location)
|
81
83
|
end
|
82
84
|
end
|
data/cqm-models.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'cqm-models'
|
7
|
-
spec.version = '4.
|
7
|
+
spec.version = '4.2.0'
|
8
8
|
spec.authors = ['aholmes@mitre.org', 'mokeefe@mitre.org', 'lades@mitre.org']
|
9
9
|
|
10
10
|
spec.summary = 'Mongo models that correspond to the QDM specification.'
|
@@ -20,13 +20,13 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
22
|
spec.add_development_dependency 'bundle-audit'
|
23
|
-
spec.add_development_dependency 'bundler', '~> 2.1.4'
|
24
23
|
spec.add_development_dependency 'byebug', '~> 11.0.1'
|
25
24
|
spec.add_development_dependency 'codecov'
|
26
|
-
spec.add_development_dependency 'mongoid', '~>
|
27
|
-
spec.add_development_dependency '
|
25
|
+
spec.add_development_dependency 'mongoid', '~> 8'
|
26
|
+
spec.add_development_dependency 'nokogiri', '>= 1.16.2'
|
27
|
+
spec.add_development_dependency 'rails', '~> 7.1'
|
28
28
|
spec.add_development_dependency 'rake', '~> 12.3.3'
|
29
29
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
30
|
+
spec.add_development_dependency 'rubocop', '~> 0.63.0'
|
31
31
|
spec.add_development_dependency 'simplecov'
|
32
32
|
end
|