his_emr_api_lab 1.1.21 → 1.1.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. metadata +3 -82
  3. data/MIT-LICENSE +0 -20
  4. data/README.md +0 -71
  5. data/Rakefile +0 -32
  6. data/app/controllers/lab/application_controller.rb +0 -6
  7. data/app/controllers/lab/labels_controller.rb +0 -17
  8. data/app/controllers/lab/orders_controller.rb +0 -38
  9. data/app/controllers/lab/reasons_for_test_controller.rb +0 -9
  10. data/app/controllers/lab/results_controller.rb +0 -19
  11. data/app/controllers/lab/specimen_types_controller.rb +0 -15
  12. data/app/controllers/lab/test_result_indicators_controller.rb +0 -9
  13. data/app/controllers/lab/test_types_controller.rb +0 -15
  14. data/app/controllers/lab/tests_controller.rb +0 -26
  15. data/app/jobs/lab/application_job.rb +0 -4
  16. data/app/jobs/lab/push_order_job.rb +0 -12
  17. data/app/jobs/lab/update_patient_orders_job.rb +0 -32
  18. data/app/jobs/lab/void_order_job.rb +0 -17
  19. data/app/mailers/lab/application_mailer.rb +0 -6
  20. data/app/models/lab/application_record.rb +0 -5
  21. data/app/models/lab/lab_accession_number_counter.rb +0 -13
  22. data/app/models/lab/lab_encounter.rb +0 -7
  23. data/app/models/lab/lab_order.rb +0 -58
  24. data/app/models/lab/lab_result.rb +0 -31
  25. data/app/models/lab/lab_test.rb +0 -19
  26. data/app/models/lab/lims_failed_import.rb +0 -4
  27. data/app/models/lab/lims_order_mapping.rb +0 -10
  28. data/app/serializers/lab/lab_order_serializer.rb +0 -55
  29. data/app/serializers/lab/result_serializer.rb +0 -36
  30. data/app/serializers/lab/test_serializer.rb +0 -29
  31. data/app/services/lab/accession_number_service.rb +0 -77
  32. data/app/services/lab/concepts_service.rb +0 -82
  33. data/app/services/lab/labelling_service/order_label.rb +0 -106
  34. data/app/services/lab/lims/api/blackhole_api.rb +0 -21
  35. data/app/services/lab/lims/api/couchdb_api.rb +0 -53
  36. data/app/services/lab/lims/api/mysql_api.rb +0 -316
  37. data/app/services/lab/lims/api/rest_api.rb +0 -416
  38. data/app/services/lab/lims/api/ws_api.rb +0 -121
  39. data/app/services/lab/lims/api_factory.rb +0 -19
  40. data/app/services/lab/lims/config.rb +0 -100
  41. data/app/services/lab/lims/exceptions.rb +0 -11
  42. data/app/services/lab/lims/migrator.rb +0 -216
  43. data/app/services/lab/lims/order_dto.rb +0 -105
  44. data/app/services/lab/lims/order_serializer.rb +0 -244
  45. data/app/services/lab/lims/pull_worker.rb +0 -289
  46. data/app/services/lab/lims/push_worker.rb +0 -149
  47. data/app/services/lab/lims/utils.rb +0 -91
  48. data/app/services/lab/lims/worker.rb +0 -86
  49. data/app/services/lab/metadata.rb +0 -24
  50. data/app/services/lab/orders_search_service.rb +0 -66
  51. data/app/services/lab/orders_service.rb +0 -212
  52. data/app/services/lab/results_service.rb +0 -147
  53. data/app/services/lab/tests_service.rb +0 -93
  54. data/config/routes.rb +0 -17
  55. data/db/migrate/20210126092910_create_lab_lab_accession_number_counters.rb +0 -12
  56. data/db/migrate/20210310115457_create_lab_lims_order_mappings.rb +0 -15
  57. data/db/migrate/20210323080140_change_lims_id_to_string_in_lims_order_mapping.rb +0 -15
  58. data/db/migrate/20210326195504_add_order_revision_to_lims_order_mapping.rb +0 -5
  59. data/db/migrate/20210407071728_create_lab_lims_failed_imports.rb +0 -19
  60. data/db/migrate/20210610095024_fix_numeric_results_value_type.rb +0 -20
  61. data/db/migrate/20210807111531_add_default_to_lims_order_mapping.rb +0 -7
  62. data/lib/auto12epl.rb +0 -201
  63. data/lib/couch_bum/couch_bum.rb +0 -92
  64. data/lib/generators/lab/install/USAGE +0 -9
  65. data/lib/generators/lab/install/install_generator.rb +0 -19
  66. data/lib/generators/lab/install/templates/rswag-ui-lab.rb +0 -5
  67. data/lib/generators/lab/install/templates/start_worker.rb +0 -32
  68. data/lib/generators/lab/install/templates/swagger.yaml +0 -714
  69. data/lib/his_emr_api_lab.rb +0 -5
  70. data/lib/lab/engine.rb +0 -15
  71. data/lib/lab/version.rb +0 -5
  72. data/lib/logger_multiplexor.rb +0 -38
  73. data/lib/tasks/lab_tasks.rake +0 -25
  74. data/lib/tasks/loaders/data/reasons-for-test.csv +0 -7
  75. data/lib/tasks/loaders/data/test-measures.csv +0 -225
  76. data/lib/tasks/loaders/data/tests.csv +0 -161
  77. data/lib/tasks/loaders/loader_mixin.rb +0 -53
  78. data/lib/tasks/loaders/metadata_loader.rb +0 -26
  79. data/lib/tasks/loaders/reasons_for_test_loader.rb +0 -23
  80. data/lib/tasks/loaders/specimens_loader.rb +0 -65
  81. data/lib/tasks/loaders/test_result_indicators_loader.rb +0 -54
@@ -1,316 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lab
4
- module Lims
5
- module Api
6
- class MysqlApi
7
- def self.start
8
- instance = MysqlApi.new
9
- orders_processed = 0
10
- instance.consume_orders(from: 0, limit: 1000) do |order|
11
- puts "Order ##{orders_processed}"
12
- pp order
13
- orders_processed += 1
14
- puts
15
- end
16
- end
17
-
18
- def initialize(processes: 1, on_merge_processes: nil)
19
- @processes = processes
20
- @on_merge_processes = on_merge_processes
21
- @mysql_connection_pool = {}
22
- end
23
-
24
- def multiprocessed?
25
- @processes > 1
26
- end
27
-
28
- def consume_orders(from: nil, limit: 1000)
29
- loop do
30
- specimens_to_process = specimens(from, limit)
31
- break if specimens_to_process.size.zero?
32
-
33
- processes = multiprocessed? ? @processes : 0
34
- on_merge_processes = ->(_item, index, _result) { @on_merge_processes&.call(from + index) }
35
-
36
- Parallel.map(specimens_to_process, in_processes: processes, finish: on_merge_processes) do |specimen|
37
- User.current ||= Utils.lab_user
38
-
39
- tests = specimen_tests(specimen['specimen_id'])
40
- results = tests.each_with_object({}) do |test, object|
41
- object[test['test_name']] = test_results(test['test_id'])
42
- end
43
-
44
- dto = make_order_dto(
45
- specimen: specimen,
46
- patient: specimen_patient(specimen['specimen_id']),
47
- test_results: results,
48
- specimen_status_trail: specimen_status_trail(specimen['specimen_id']),
49
- test_status_trail: tests.each_with_object({}) do |test, trails|
50
- trails[test['test_name']] = test_status_trail(test['test_id'])
51
- end
52
- )
53
-
54
- yield dto, OpenStruct.new(last_seq: from)
55
- end
56
-
57
- from += limit
58
- end
59
- end
60
-
61
- def parallel_map(items, on_merge: nil, &block); end
62
-
63
- private
64
-
65
- def specimens(start_id, limit)
66
- query = <<~SQL
67
- SELECT specimen.id AS specimen_id,
68
- specimen.couch_id AS doc_id,
69
- specimen_types.name AS specimen_name,
70
- specimen.tracking_number,
71
- specimen.priority,
72
- specimen.target_lab,
73
- specimen.sending_facility,
74
- specimen.drawn_by_id,
75
- specimen.drawn_by_name,
76
- specimen.drawn_by_phone_number,
77
- specimen.ward_id,
78
- specimen_statuses.name AS specimen_status,
79
- specimen.district,
80
- specimen.date_created AS order_date
81
- FROM specimen
82
- INNER JOIN specimen_types ON specimen_types.id = specimen.specimen_type_id
83
- INNER JOIN specimen_statuses ON specimen_statuses.id = specimen.specimen_status_id
84
- SQL
85
-
86
- query = "#{query} WHERE specimen.id > #{sql_escape(start_id)}" if start_id
87
- query = "#{query} LIMIT #{limit.to_i}"
88
-
89
- Rails.logger.debug(query)
90
- query(query)
91
- end
92
-
93
- ##
94
- # Pull patient associated with given specimen
95
- def specimen_patient(specimen_id)
96
- results = query <<~SQL
97
- SELECT patients.patient_number AS nhid,
98
- patients.name,
99
- patients.gender,
100
- DATE(patients.dob) AS birthdate
101
- FROM patients
102
- INNER JOIN tests
103
- ON tests.patient_id = patients.id
104
- AND tests.specimen_id = #{sql_escape(specimen_id)}
105
- LIMIT 1
106
- SQL
107
-
108
- results.first
109
- end
110
-
111
- def specimen_tests(specimen_id)
112
- query <<~SQL
113
- SELECT tests.id AS test_id,
114
- test_types.name AS test_name,
115
- tests.created_by AS drawn_by_name
116
- FROM tests
117
- INNER JOIN test_types ON test_types.id = tests.test_type_id
118
- WHERE tests.specimen_id = #{sql_escape(specimen_id)}
119
- SQL
120
- end
121
-
122
- def specimen_status_trail(specimen_id)
123
- query <<~SQL
124
- SELECT specimen_statuses.name AS status_name,
125
- specimen_status_trails.who_updated_id AS updated_by_id,
126
- specimen_status_trails.who_updated_name AS updated_by_name,
127
- specimen_status_trails.who_updated_phone_number AS updated_by_phone_number,
128
- specimen_status_trails.time_updated AS date
129
- FROM specimen_status_trails
130
- INNER JOIN specimen_statuses
131
- ON specimen_statuses.id = specimen_status_trails.specimen_status_id
132
- WHERE specimen_status_trails.specimen_id = #{sql_escape(specimen_id)}
133
- SQL
134
- end
135
-
136
- def test_status_trail(test_id)
137
- query <<~SQL
138
- SELECT test_statuses.name AS status_name,
139
- test_status_trails.who_updated_id AS updated_by_id,
140
- test_status_trails.who_updated_name AS updated_by_name,
141
- test_status_trails.who_updated_phone_number AS updated_by_phone_number,
142
- COALESCE(test_status_trails.time_updated, test_status_trails.created_at) AS date
143
- FROM test_status_trails
144
- INNER JOIN test_statuses
145
- ON test_statuses.id = test_status_trails.test_status_id
146
- WHERE test_status_trails.test_id = #{sql_escape(test_id)}
147
- SQL
148
- end
149
-
150
- def test_results(test_id)
151
- query <<~SQL
152
- SELECT measures.name AS measure_name,
153
- test_results.result,
154
- test_results.time_entered AS date
155
- FROM test_results
156
- INNER JOIN measures ON measures.id = test_results.measure_id
157
- WHERE test_results.test_id = #{sql_escape(test_id)}
158
- SQL
159
- end
160
-
161
- def make_order_dto(specimen:, patient:, test_status_trail:, specimen_status_trail:, test_results:)
162
- drawn_by_first_name, drawn_by_last_name = specimen['drawn_by_name']&.split
163
- patient_first_name, patient_last_name = patient['name'].split
164
-
165
- OrderDTO.new(
166
- _id: specimen['doc_id'].blank? ? SecureRandom.uuid : specimen['doc_id'],
167
- _rev: '0',
168
- tracking_number: specimen['tracking_number'],
169
- date_created: specimen['order_date'],
170
- sample_type: specimen['specimen_name'],
171
- tests: test_status_trail.keys,
172
- districy: specimen['district'], # districy [sic] - That's how it's named
173
- order_location: specimen['ward_id'],
174
- sending_facility: specimen['sending_facility'],
175
- receiving_facility: specimen['target_lab'],
176
- priority: specimen['priority'],
177
- patient: {
178
- id: patient['nhid'],
179
- first_name: patient_first_name,
180
- last_name: patient_last_name,
181
- gender: patient['gender'],
182
- birthdate: patient['birthdate'],
183
- email: nil,
184
- phone_number: nil
185
- },
186
- type: 'Order',
187
- who_order_test: {
188
- first_name: drawn_by_first_name,
189
- last_name: drawn_by_last_name,
190
- id: specimen['drawn_by_id'],
191
- phone_number: specimen['drawn_by_phone_number']
192
- },
193
- sample_status: specimen['specimen_status'],
194
- sample_statuses: specimen_status_trail.each_with_object({}) do |trail_entry, object|
195
- first_name, last_name = trail_entry['updated_by_name'].split
196
-
197
- object[format_date(trail_entry['date'])] = {
198
- status: trail_entry['status_name'],
199
- updated_by: {
200
- first_name: first_name,
201
- last_name: last_name,
202
- phone_number: trail_entry['updated_by_phone_number'],
203
- id: trail_entry['updated_by_id']
204
- }
205
- }
206
- end,
207
- test_statuses: test_status_trail.each_with_object({}) do |trail_entry, formatted_trail|
208
- test_name, test_statuses = trail_entry
209
-
210
- formatted_trail[test_name] = test_statuses.each_with_object({}) do |test_status, formatted_statuses|
211
- updated_by_first_name, updated_by_last_name = test_status['updated_by_name'].split
212
-
213
- formatted_statuses[format_date(test_status['date'])] = {
214
- status: test_status['status_name'],
215
- updated_by: {
216
- first_name: updated_by_first_name,
217
- last_name: updated_by_last_name,
218
- phone_number: test_status['updated_by_phone_number'],
219
- id: test_status['updated_by_id']
220
- }
221
- }
222
- end
223
- end,
224
- test_results: test_results.each_with_object({}) do |results_entry, formatted_results|
225
- test_name, results = results_entry
226
-
227
- formatted_results[test_name] = format_test_result_for_dto(test_name, specimen, results, test_status_trail)
228
- end
229
- )
230
- end
231
-
232
- def format_test_result_for_dto(test_name, specimen, results, test_status_trail)
233
- return {} if results.size.zero?
234
-
235
- result_create_event = test_status_trail[test_name]&.find do |trail_entry|
236
- trail_entry['status_name'].casecmp?('drawn')
237
- end
238
-
239
- result_creator_first_name, result_creator_last_name = result_create_event&.fetch('updated_by_name')&.split
240
- unless result_creator_first_name
241
- result_creator_first_name, result_creator_last_name = specimen['drawn_by_name']&.split
242
- end
243
-
244
- {
245
- results: results.each_with_object({}) do |result, formatted_measures|
246
- formatted_measures[result['measure_name']] = {
247
- result_value: result['result']
248
- }
249
- end,
250
- date_result_entered: format_date(result_create_event&.fetch('date') || specimen['order_date'], :iso),
251
- result_entered_by: {
252
- first_name: result_creator_first_name,
253
- last_name: result_creator_last_name,
254
- phone_number: result_create_event&.fetch('updated_by_phone_number') || specimen['drawn_by_phone_number'],
255
- id: result_create_event&.fetch('updated_by_id') || specimen['updated_by_id']
256
- }
257
- }
258
- end
259
-
260
- def mysql
261
- return mysql_connection if mysql_connection
262
-
263
- config = lambda do |key|
264
- @config ||= Lab::Lims::Config.database
265
- @config['default'][key] || @config['development'][key]
266
- end
267
-
268
- connection = Mysql2::Client.new(host: config['host'] || 'localhost',
269
- username: config['username'] || 'root',
270
- password: config['password'],
271
- port: config['port'] || '3306',
272
- database: config['database'],
273
- reconnect: true)
274
-
275
- self.mysql_connection = connection
276
- end
277
-
278
- def pid
279
- return -1 if Parallel.worker_number.nil?
280
-
281
- Parallel.worker_number
282
- end
283
-
284
- def mysql_connection=(connection)
285
- @mysql_connection_pool[pid] = connection
286
- end
287
-
288
- def mysql_connection
289
- @mysql_connection_pool[pid]
290
- end
291
-
292
- def query(sql)
293
- Rails.logger.debug("#{MysqlApi}: #{sql}")
294
- mysql.query(sql)
295
- end
296
-
297
- def sql_escape(value)
298
- mysql.escape(value.to_s)
299
- end
300
-
301
- ##
302
- # Lims has some weird date formatting standards...
303
- def format_date(date, format = nil)
304
- date = date&.to_time
305
-
306
- case format
307
- when :iso
308
- date&.strftime('%Y-%m-%d %H:%M:%S')
309
- else
310
- date&.strftime('%Y%m%d%H%M%S')
311
- end
312
- end
313
- end
314
- end
315
- end
316
- end