his_emr_api_lab 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +52 -0
  4. data/Rakefile +32 -0
  5. data/app/controllers/lab/application_controller.rb +6 -0
  6. data/app/controllers/lab/orders_controller.rb +34 -0
  7. data/app/controllers/lab/reasons_for_test_controller.rb +9 -0
  8. data/app/controllers/lab/results_controller.rb +19 -0
  9. data/app/controllers/lab/specimen_types_controller.rb +15 -0
  10. data/app/controllers/lab/test_result_indicators_controller.rb +9 -0
  11. data/app/controllers/lab/test_types_controller.rb +15 -0
  12. data/app/controllers/lab/tests_controller.rb +25 -0
  13. data/app/jobs/lab/application_job.rb +4 -0
  14. data/app/mailers/lab/application_mailer.rb +6 -0
  15. data/app/models/lab/application_record.rb +5 -0
  16. data/app/models/lab/lab_accession_number_counter.rb +13 -0
  17. data/app/models/lab/lab_encounter.rb +7 -0
  18. data/app/models/lab/lab_order.rb +47 -0
  19. data/app/models/lab/lab_result.rb +21 -0
  20. data/app/models/lab/lab_test.rb +14 -0
  21. data/app/models/lab/lims_failed_import.rb +4 -0
  22. data/app/models/lab/lims_order_mapping.rb +10 -0
  23. data/app/serializers/lab/lab_order_serializer.rb +49 -0
  24. data/app/serializers/lab/result_serializer.rb +36 -0
  25. data/app/serializers/lab/test_serializer.rb +29 -0
  26. data/app/services/lab/accession_number_service.rb +77 -0
  27. data/app/services/lab/concepts_service.rb +82 -0
  28. data/app/services/lab/lims/api.rb +46 -0
  29. data/app/services/lab/lims/config.rb +56 -0
  30. data/app/services/lab/lims/order_dto.rb +177 -0
  31. data/app/services/lab/lims/order_serializer.rb +112 -0
  32. data/app/services/lab/lims/utils.rb +27 -0
  33. data/app/services/lab/lims/worker.rb +121 -0
  34. data/app/services/lab/metadata.rb +23 -0
  35. data/app/services/lab/orders_search_service.rb +48 -0
  36. data/app/services/lab/orders_service.rb +194 -0
  37. data/app/services/lab/results_service.rb +92 -0
  38. data/app/services/lab/tests_service.rb +93 -0
  39. data/config/routes.rb +15 -0
  40. data/db/migrate/20210126092910_create_lab_lab_accession_number_counters.rb +12 -0
  41. data/db/migrate/20210310115457_create_lab_lims_order_mappings.rb +15 -0
  42. data/db/migrate/20210323080140_change_lims_id_to_string_in_lims_order_mapping.rb +15 -0
  43. data/db/migrate/20210326195504_add_order_revision_to_lims_order_mapping.rb +5 -0
  44. data/db/migrate/20210407071728_create_lab_lims_failed_imports.rb +19 -0
  45. data/lib/couch_bum/couch_bum.rb +77 -0
  46. data/lib/generators/lab/install/USAGE +9 -0
  47. data/lib/generators/lab/install/install_generator.rb +19 -0
  48. data/lib/generators/lab/install/templates/rswag-ui-lab.rb +5 -0
  49. data/lib/generators/lab/install/templates/start_worker.rb +32 -0
  50. data/lib/generators/lab/install/templates/swagger.yaml +682 -0
  51. data/lib/his_emr_api_lab.rb +5 -0
  52. data/lib/lab/engine.rb +15 -0
  53. data/lib/lab/version.rb +5 -0
  54. data/lib/logger_multiplexor.rb +32 -0
  55. data/lib/tasks/lab_tasks.rake +25 -0
  56. data/lib/tasks/loaders/data/reasons-for-test.csv +6 -0
  57. data/lib/tasks/loaders/data/test-measures.csv +224 -0
  58. data/lib/tasks/loaders/data/tests.csv +142 -0
  59. data/lib/tasks/loaders/loader_mixin.rb +53 -0
  60. data/lib/tasks/loaders/metadata_loader.rb +26 -0
  61. data/lib/tasks/loaders/reasons_for_test_loader.rb +23 -0
  62. data/lib/tasks/loaders/specimens_loader.rb +65 -0
  63. data/lib/tasks/loaders/test_result_indicators_loader.rb +54 -0
  64. metadata +296 -0
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lab
4
+ module Loaders
5
+ module LoaderMixin
6
+ def self.included(_mod)
7
+ User.current = User.find_by_username('admin') || User.first
8
+ Location.current = Location.find_by_name('Registration') || Location.first
9
+ end
10
+
11
+ CONCEPT_DATATYPE_CODED = 2
12
+ CONCEPT_CLASS_TEST = 1
13
+
14
+ def find_or_create_concept(name, is_set: false)
15
+ # Filter out concept_names with voided concepts
16
+ concept = ConceptName.joins(:concept).find_by_name(name)
17
+ return concept if concept
18
+
19
+ ConceptName.create!(
20
+ concept: Concept.create!(
21
+ short_name: name,
22
+ datatype_id: CONCEPT_DATATYPE_CODED,
23
+ class_id: CONCEPT_CLASS_TEST,
24
+ is_set: is_set,
25
+ uuid: SecureRandom.uuid,
26
+ creator: User.current.user_id,
27
+ date_created: Time.now
28
+ ),
29
+ name: name,
30
+ locale: 'en',
31
+ concept_name_type: 'FULLY_SPECIED',
32
+ uuid: SecureRandom.uuid,
33
+ creator: User.current.user_id,
34
+ date_created: Time.now
35
+ )
36
+ end
37
+
38
+ def add_concept_to_set(set_concept_id:, concept_id:)
39
+ set = ConceptSet.find_by(concept_set: set_concept_id, concept_id: concept_id)
40
+ return set if set
41
+
42
+ ConceptSet.create!(concept_set: set_concept_id,
43
+ concept_id: concept_id,
44
+ creator: User.current.user_id,
45
+ date_created: Time.now)
46
+ end
47
+
48
+ def data_path(filename)
49
+ "#{__dir__}/data/#{filename}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'reasons_for_test_loader'
4
+ require_relative 'specimens_loader'
5
+ require_relative 'test_result_indicators_loader'
6
+
7
+ module Lab
8
+ module Loaders
9
+ module MetadataLoader
10
+ def self.load
11
+ unless Program.where(name: 'Laboratory program').exists?
12
+ Program.create(name: 'Laboratory program',
13
+ description: 'Manage Lab information',
14
+ creator: 1,
15
+ uuid: SecureRandom.uuid)
16
+ end
17
+
18
+ SpecimensLoader.load
19
+ TestResultIndicatorsLoader.load
20
+ ReasonsForTestLoader.load
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ Lab::Loaders::MetadataLoader.load
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './loader_mixin'
4
+
5
+ module Lab
6
+ module Loaders
7
+ module ReasonsForTestLoader
8
+ class << self
9
+ include LoaderMixin
10
+
11
+ def load
12
+ CSV.open(data_path('reasons-for-test.csv'), headers: :first_row) do |csv|
13
+ csv.each do |row|
14
+ puts "Adding reason for test: #{row['reason_name']}"
15
+ add_concept_to_set(set_concept_id: find_or_create_concept(Lab::Metadata::REASON_FOR_TEST_CONCEPT_NAME).concept_id,
16
+ concept_id: find_or_create_concept(row['reason_name']).concept_id)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+ require_relative './loader_mixin'
5
+
6
+ module Lab
7
+ module Loaders
8
+ ##
9
+ # Load specimens and their tests into the database
10
+ module SpecimensLoader
11
+ class << self
12
+ include LoaderMixin
13
+
14
+ def load
15
+ puts "------- Loading tests and specimens ---------"
16
+ CSV.open(data_path('tests.csv'), headers: :first_row) do |csv|
17
+ csv.each_with_object({}) do |row, test_types|
18
+ specimen_name = row['specimen_name']
19
+ test_name = row['test_name']
20
+
21
+ ActiveRecord::Base.transaction do
22
+ test_type = test_types[test_name] || create_test_type(test_name)
23
+ create_specimen_type(specimen_name, test_type)
24
+
25
+ test_types[test_name] ||= test_type
26
+ end
27
+
28
+ puts "Created test #{test_name} <--< #{specimen_name}"
29
+ rescue StandardError => e
30
+ puts "Error: #{test_name}: #{e}"
31
+ end
32
+ end
33
+ end
34
+
35
+ def test_type_concept_id
36
+ find_or_create_concept(Lab::Metadata::TEST_TYPE_CONCEPT_NAME).concept_id
37
+ end
38
+
39
+ def specimen_type_concept_id
40
+ find_or_create_concept(Lab::Metadata::SPECIMEN_TYPE_CONCEPT_NAME).concept_id
41
+ end
42
+
43
+
44
+ def create_test_type(name)
45
+ concept_id = find_or_create_concept(name, is_set: true).concept_id
46
+
47
+ add_concept_to_set(set_concept_id: test_type_concept_id, concept_id: concept_id)
48
+ rescue StandardError => e
49
+ raise "Failed to create test type `#{name}`: #{e}"
50
+ end
51
+
52
+ def create_specimen_type(name, test_type)
53
+ concept_id = find_or_create_concept(name).concept_id
54
+
55
+ [
56
+ add_concept_to_set(set_concept_id: specimen_type_concept_id, concept_id: concept_id),
57
+ add_concept_to_set(set_concept_id: test_type.concept_id, concept_id: concept_id)
58
+ ]
59
+ rescue StandardError => e
60
+ raise "Failed to create specimen type `#{name}`: #{e}"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+ require_relative './loader_mixin'
5
+
6
+ module Lab
7
+ module Loaders
8
+ ##
9
+ # Load specimens and their tests into the database
10
+ module TestResultIndicatorsLoader
11
+ class << self
12
+ include LoaderMixin
13
+
14
+ def load
15
+ puts "------- Loading measures ------------"
16
+ CSV.open(data_path('test-measures.csv'), headers: :first_row) do |csv|
17
+ csv.each_with_object({}) do |row, test_measures|
18
+ test_name = row['test_name']
19
+ measure_name = row['measure_name']
20
+
21
+ ActiveRecord::Base.transaction do
22
+ measure_concept = find_or_create_concept(measure_name)
23
+ add_measure_to_test(test_name, measure_concept)
24
+ end
25
+
26
+ puts "Created measure #{test_name} <--< #{measure_name}"
27
+ rescue StandardError => e
28
+ puts "Error: #{measure_name}: #{e}"
29
+ end
30
+ end
31
+ end
32
+
33
+ def create_test_type(name)
34
+ concept_id = find_or_create_concept(name, is_set: true).concept_id
35
+
36
+ create_concept_set(concept_set: test_type_concept_id, concept_id: concept_id)
37
+ rescue StandardError => e
38
+ raise "Failed to create test type `#{name}`: #{e}"
39
+ end
40
+
41
+ def add_measure_to_test(test_name, measure_concept)
42
+ [
43
+ add_concept_to_set(set_concept_id: find_or_create_concept(Lab::Metadata::TEST_RESULT_INDICATOR_CONCEPT_NAME).concept_id,
44
+ concept_id: measure_concept.concept_id),
45
+ add_concept_to_set(set_concept_id: measure_concept.concept_id,
46
+ concept_id: find_or_create_concept(test_name).concept_id)
47
+ ]
48
+ rescue StandardError => e
49
+ raise "Failed to create measure for test `#{name}`: #{e}"
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,296 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: his_emr_api_lab
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Elizabeth Glaser Pediatric Foundation Malawi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: couchrest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 5.2.4
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 5.2.4.3
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: 5.2.4
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 5.2.4.3
47
+ - !ruby/object:Gem::Dependency
48
+ name: bcrypt
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 3.1.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 3.1.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: factory_bot_rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 6.1.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 6.1.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: faker
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 2.16.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 2.16.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec-rails
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 5.0.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 5.0.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: rswag-api
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 2.4.0
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 2.4.0
117
+ - !ruby/object:Gem::Dependency
118
+ name: rswag-specs
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 2.4.0
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 2.4.0
131
+ - !ruby/object:Gem::Dependency
132
+ name: rswag-ui
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 2.4.0
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 2.4.0
145
+ - !ruby/object:Gem::Dependency
146
+ name: rubocop
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: 0.79.0
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: 0.79.0
159
+ - !ruby/object:Gem::Dependency
160
+ name: rubocop-rspec
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: 1.41.0
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: 1.41.0
173
+ - !ruby/object:Gem::Dependency
174
+ name: shoulda-matchers
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: 4.5.0
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: 4.5.0
187
+ - !ruby/object:Gem::Dependency
188
+ name: sqlite3
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: 1.4.0
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: 1.4.0
201
+ description: |
202
+ This adds a lab interface to the OpenMRS compatible core API provided by
203
+ [HIS-EMR-API](https://github.com/EGPAFMalawiHIS/HIS-EMR-API).
204
+ email:
205
+ - emrdevelopersmalawi@pedaids.org
206
+ executables: []
207
+ extensions: []
208
+ extra_rdoc_files: []
209
+ files:
210
+ - MIT-LICENSE
211
+ - README.md
212
+ - Rakefile
213
+ - app/controllers/lab/application_controller.rb
214
+ - app/controllers/lab/orders_controller.rb
215
+ - app/controllers/lab/reasons_for_test_controller.rb
216
+ - app/controllers/lab/results_controller.rb
217
+ - app/controllers/lab/specimen_types_controller.rb
218
+ - app/controllers/lab/test_result_indicators_controller.rb
219
+ - app/controllers/lab/test_types_controller.rb
220
+ - app/controllers/lab/tests_controller.rb
221
+ - app/jobs/lab/application_job.rb
222
+ - app/mailers/lab/application_mailer.rb
223
+ - app/models/lab/application_record.rb
224
+ - app/models/lab/lab_accession_number_counter.rb
225
+ - app/models/lab/lab_encounter.rb
226
+ - app/models/lab/lab_order.rb
227
+ - app/models/lab/lab_result.rb
228
+ - app/models/lab/lab_test.rb
229
+ - app/models/lab/lims_failed_import.rb
230
+ - app/models/lab/lims_order_mapping.rb
231
+ - app/serializers/lab/lab_order_serializer.rb
232
+ - app/serializers/lab/result_serializer.rb
233
+ - app/serializers/lab/test_serializer.rb
234
+ - app/services/lab/accession_number_service.rb
235
+ - app/services/lab/concepts_service.rb
236
+ - app/services/lab/lims/api.rb
237
+ - app/services/lab/lims/config.rb
238
+ - app/services/lab/lims/order_dto.rb
239
+ - app/services/lab/lims/order_serializer.rb
240
+ - app/services/lab/lims/utils.rb
241
+ - app/services/lab/lims/worker.rb
242
+ - app/services/lab/metadata.rb
243
+ - app/services/lab/orders_search_service.rb
244
+ - app/services/lab/orders_service.rb
245
+ - app/services/lab/results_service.rb
246
+ - app/services/lab/tests_service.rb
247
+ - config/routes.rb
248
+ - db/migrate/20210126092910_create_lab_lab_accession_number_counters.rb
249
+ - db/migrate/20210310115457_create_lab_lims_order_mappings.rb
250
+ - db/migrate/20210323080140_change_lims_id_to_string_in_lims_order_mapping.rb
251
+ - db/migrate/20210326195504_add_order_revision_to_lims_order_mapping.rb
252
+ - db/migrate/20210407071728_create_lab_lims_failed_imports.rb
253
+ - lib/couch_bum/couch_bum.rb
254
+ - lib/generators/lab/install/USAGE
255
+ - lib/generators/lab/install/install_generator.rb
256
+ - lib/generators/lab/install/templates/rswag-ui-lab.rb
257
+ - lib/generators/lab/install/templates/start_worker.rb
258
+ - lib/generators/lab/install/templates/swagger.yaml
259
+ - lib/his_emr_api_lab.rb
260
+ - lib/lab/engine.rb
261
+ - lib/lab/version.rb
262
+ - lib/logger_multiplexor.rb
263
+ - lib/tasks/lab_tasks.rake
264
+ - lib/tasks/loaders/data/reasons-for-test.csv
265
+ - lib/tasks/loaders/data/test-measures.csv
266
+ - lib/tasks/loaders/data/tests.csv
267
+ - lib/tasks/loaders/loader_mixin.rb
268
+ - lib/tasks/loaders/metadata_loader.rb
269
+ - lib/tasks/loaders/reasons_for_test_loader.rb
270
+ - lib/tasks/loaders/specimens_loader.rb
271
+ - lib/tasks/loaders/test_result_indicators_loader.rb
272
+ homepage: https://github.com/EGPAFMalawiHIS/his_emr_api_lab
273
+ licenses:
274
+ - MIT
275
+ metadata:
276
+ source_code_uri: https://github.com/EGPAFMalawiHIS/his_emr_api_lab
277
+ post_install_message:
278
+ rdoc_options: []
279
+ require_paths:
280
+ - lib
281
+ required_ruby_version: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ required_rubygems_version: !ruby/object:Gem::Requirement
287
+ requirements:
288
+ - - ">="
289
+ - !ruby/object:Gem::Version
290
+ version: '0'
291
+ requirements: []
292
+ rubygems_version: 3.0.8
293
+ signing_key:
294
+ specification_version: 4
295
+ summary: Lab extension for the HIS-EMR-API
296
+ test_files: []