his_emr_api_lab 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []