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,416 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Lab::Lims::Api::RestApi
4
- class LimsApiError < GatewayError; end
5
-
6
- class AuthenticationTokenExpired < LimsApiError; end
7
-
8
- class InvalidParameters < LimsApiError; end
9
-
10
- def initialize(config)
11
- @config = config
12
- end
13
-
14
- def create_order(order_dto)
15
- response = in_authenticated_session do |headers|
16
- Rails.logger.info("Pushing order ##{order_dto[:tracking_number]} to LIMS")
17
-
18
- if order_dto['sample_type'].casecmp?('not_specified')
19
- RestClient.post(expand_uri('request_order', api_version: 'v2'), make_create_params(order_dto), headers)
20
- else
21
- RestClient.post(expand_uri('create_order'), make_create_params(order_dto), headers)
22
- end
23
- end
24
-
25
- data = JSON.parse(response.body)
26
- update_order_results(order_dto) unless data['message'].casecmp?('Order already available')
27
-
28
- ActiveSupport::HashWithIndifferentAccess.new(
29
- id: order_dto.fetch(:_id, order_dto[:tracking_number]),
30
- rev: 0,
31
- tracking_number: order_dto[:tracking_number]
32
- )
33
- end
34
-
35
- def update_order(_id, order_dto)
36
- in_authenticated_session do |headers|
37
- RestClient.post(expand_uri('update_order'), make_update_params(order_dto), headers)
38
- end
39
-
40
- update_order_results(order_dto)
41
-
42
- { tracking_number: order_dto[:tracking_number] }
43
- end
44
-
45
- def consume_orders(*_args, patient_id: nil, **_kwargs)
46
- orders_pending_updates(patient_id).each do |order|
47
- order_dto = Lab::Lims::OrderSerializer.serialize_order(order)
48
-
49
- if order_dto['priority'].nil? || order_dto['sample_type'].casecmp?('not_specified')
50
- patch_order_dto_with_lims_order!(order_dto, find_lims_order(order.accession_number))
51
- end
52
-
53
- if order_dto['test_results'].empty?
54
- begin
55
- patch_order_dto_with_lims_results!(order_dto, find_lims_results(order.accession_number))
56
- rescue InvalidParameters => e # LIMS responds with a 401 when a result is not found :(
57
- Rails.logger.error("Failed to fetch results for ##{order.accession_number}: #{e.message}")
58
- end
59
- end
60
-
61
- yield order_dto, OpenStruct.new(last_seq: 0)
62
- rescue LimsApiError => e
63
- Rails.logger.error("Failed to fetch updates for ##{order.accession_number}: #{e.class} - #{e.message}")
64
- sleep(1)
65
- end
66
- end
67
-
68
- def delete_order(_id, order_dto)
69
- tracking_number = order_dto.fetch('tracking_number')
70
-
71
- order_dto['tests'].each do |test|
72
- Rails.logger.info("Voiding test '#{test}' (#{tracking_number}) in LIMS")
73
- in_authenticated_session do |headers|
74
- date_voided, voided_status = find_test_status(order_dto, test, 'Voided')
75
- params = make_void_test_params(tracking_number, test, voided_status['updated_by'], date_voided)
76
- RestClient.post(expand_uri('update_test'), params, headers)
77
- end
78
- end
79
- end
80
-
81
- private
82
-
83
- attr_reader :config
84
-
85
- MAX_LIMS_RETRIES = 5 # LIMS API Calls can only fail this number of times before we give up on it
86
-
87
- ##
88
- # Execute LIMS API calls within an authenticated session.
89
- #
90
- # Method automatically checks authenticates with LIMS if necessary and passes
91
- # down the necessary headers for authentication to the REST call being made.
92
- #
93
- # Example:
94
- #
95
- # response = in_authenticated_session do |headers|
96
- # RestClient.get(expand_uri('query_results_by_tracking_number/XXXXXX'), headers)
97
- # end
98
- #
99
- # pp JSON.parse(response.body) if response.code == 200
100
- def in_authenticated_session
101
- retries ||= MAX_LIMS_RETRIES
102
-
103
- self.authentication_token = authenticate unless authentication_token
104
-
105
- response = yield 'token' => authentication_token, 'Content-type' => 'application/json'
106
- check_response!(response)
107
- rescue AuthenticationTokenExpired => e
108
- self.authentication_token = nil
109
- retry if (retries -= 1).positive?
110
- rescue RestClient::ExceptionWithResponse => e
111
- Rails.logger.error("LIMS Error: #{e.response&.code} - #{e.response&.body}")
112
- raise e unless e.response&.code == 401
113
-
114
- self.authentication_token = nil
115
- retry if (retries -= 1).positive?
116
- end
117
-
118
- def authenticate
119
- username = config.fetch(:username)
120
- password = config.fetch(:password)
121
-
122
- Rails.logger.debug("Authenticating with LIMS as: #{username}")
123
- response = RestClient.get(expand_uri("re_authenticate/#{username}/#{password}"),
124
- headers: { 'Content-type' => 'application/json' })
125
- response_body = JSON.parse(response.body)
126
-
127
- if response_body['status'] == 401
128
- Rails.logger.error("Failed to authenticate with LIMS as #{config.fetch(:username)}: #{response_body['message']}")
129
- raise LimsApiError, 'LIMS authentication failed'
130
- end
131
-
132
- response_body['data']['token']
133
- end
134
-
135
- def authentication_token=(token)
136
- Thread.current[:lims_authentication_token] = token
137
- end
138
-
139
- def authentication_token
140
- Thread.current[:lims_authentication_token]
141
- end
142
-
143
- ##
144
- # Examines a response from LIMS to check if token has expired.
145
- #
146
- # LIMS' doesn't properly use HTTP status codes; the codes are embedded in the
147
- # response body. 200 is used for success responses and 401 for everything else.
148
- # We have this work around to examine the response body and
149
- # throw errors accordingly. The following are the errors thrown:
150
- #
151
- # Lims::AuthenticationTokenExpired
152
- # Lims::InvalidParameters
153
- # Lims::ApiError - Thrown when we couldn't make sense of the error
154
- def check_response!(response)
155
- body = JSON.parse(response.body)
156
- return response if body['status'] == 200
157
-
158
- Rails.logger.error("Lims Api Error: #{response.body}")
159
-
160
- raise LimsApiError, "#{body['status']} - #{body['message']}" if body['status'] != 401
161
-
162
- if body['message'].match?(/token expired/i)
163
- raise AuthenticationTokenExpired, "Authentication token expired: #{body['message']}"
164
- end
165
-
166
- raise InvalidParameters, body['message']
167
- end
168
-
169
- ##
170
- # Takes a LIMS API relative URI and converts it to a full URL.
171
- def expand_uri(uri, api_version: 'v1')
172
- protocol = config.fetch(:protocol)
173
- host = config.fetch(:host)
174
- port = config.fetch(:port)
175
- uri = uri.gsub(%r{^/+}, '')
176
-
177
- "#{protocol}://#{host}:#{port}/api/#{api_version}/#{uri}"
178
- end
179
-
180
- ##
181
- # Converts an OrderDTO to parameters for POST /create_order
182
- def make_create_params(order_dto)
183
- {
184
- tracking_number: order_dto.fetch(:tracking_number),
185
- district: current_district,
186
- health_facility_name: order_dto.fetch(:sending_facility),
187
- first_name: order_dto.fetch(:patient).fetch(:first_name),
188
- last_name: order_dto.fetch(:patient).fetch(:last_name),
189
- phone_number: order_dto.fetch(:patient).fetch(:phone_number),
190
- gender: order_dto.fetch(:patient).fetch(:gender),
191
- arv_number: order_dto.fetch(:patient).fetch(:arv_number),
192
- art_regimen: order_dto.fetch(:patient).fetch(:art_regimen),
193
- art_start_date: order_dto.fetch(:patient).fetch(:art_start_date),
194
- national_patient_id: order_dto.fetch(:patient).fetch(:id),
195
- requesting_clinician: requesting_clinician(order_dto),
196
- sample_type: order_dto.fetch(:sample_type),
197
- tests: order_dto.fetch(:tests),
198
- date_sample_drawn: sample_drawn_date(order_dto),
199
- sample_priority: order_dto.fetch(:priority) || 'Routine',
200
- sample_status: order_dto.fetch(:sample_status),
201
- target_lab: order_dto.fetch(:receiving_facility),
202
- order_location: order_dto.fetch(:order_location) || 'Unknown',
203
- who_order_test_first_name: order_dto.fetch(:who_order_test).fetch(:first_name),
204
- who_order_test_last_name: order_dto.fetch(:who_order_test).fetch(:last_name)
205
- }
206
- end
207
-
208
- ##
209
- # Converts an OrderDTO to parameters for POST /update_order
210
- def make_update_params(order_dto)
211
- date_updated, status = sample_drawn_status(order_dto)
212
-
213
- {
214
- tracking_number: order_dto.fetch(:tracking_number),
215
- who_updated: status.fetch(:updated_by),
216
- date_updated: date_updated,
217
- specimen_type: order_dto.fetch(:sample_type),
218
- status: 'specimen_collected'
219
- }
220
- end
221
-
222
- def current_district
223
- health_centre = Location.current_health_center
224
- raise 'Current health centre not set' unless health_centre
225
-
226
- district = health_centre.district || Lab::Lims::Config.application['district']
227
-
228
- unless district
229
- health_centre_name = "##{health_centre.id} - #{health_centre.name}"
230
- raise "Current health centre district not set: #{health_centre_name}"
231
- end
232
-
233
- district
234
- end
235
-
236
- ##
237
- # Extracts sample drawn status from an OrderDTO
238
- def sample_drawn_status(order_dto)
239
- order_dto[:sample_statuses].each do |trail_entry|
240
- date, status = trail_entry.each_pair.find { |_date, status| status['status'].casecmp?('Drawn') }
241
- next unless date
242
-
243
- return Date.strptime(date, '%Y%m%d%H%M%S').strftime('%Y-%m-%d'), status
244
- end
245
-
246
- [order_dto['date_created'], nil]
247
- end
248
-
249
- ##
250
- # Extracts a sample drawn date from a LIMS OrderDTO.
251
- def sample_drawn_date(order_dto)
252
- sample_drawn_status(order_dto).first
253
- end
254
-
255
- ##
256
- # Extracts the requesting clinician from a LIMS OrderDTO
257
- def requesting_clinician(order_dto)
258
- orderer = order_dto[:who_order_test]
259
-
260
- "#{orderer[:first_name]} #{orderer[:last_name]}"
261
- end
262
-
263
- def find_lims_order(tracking_number)
264
- response = in_authenticated_session do |headers|
265
- Rails.logger.info("Fetching order ##{tracking_number}")
266
- RestClient.get(expand_uri("query_order_by_tracking_number/#{tracking_number}"), headers)
267
- end
268
-
269
- Rails.logger.info("Order ##{tracking_number} found... Parsing...")
270
- JSON.parse(response).fetch('data')
271
- end
272
-
273
- def find_lims_results(tracking_number)
274
- response = in_authenticated_session do |headers|
275
- Rails.logger.info("Fetching results for order ##{tracking_number}")
276
- RestClient.get(expand_uri("query_results_by_tracking_number/#{tracking_number}"), headers)
277
- end
278
-
279
- Rails.logger.info("Result for order ##{tracking_number} found... Parsing...")
280
- JSON.parse(response).fetch('data').fetch('results')
281
- end
282
-
283
- ##
284
- # Make a copy of the order_dto with the results from LIMS parsed
285
- # and appended to it.
286
- def patch_order_dto_with_lims_results!(order_dto, results)
287
- order_dto.merge!(
288
- '_id' => order_dto[:tracking_number],
289
- '_rev' => 0,
290
- 'test_results' => results.each_with_object({}) do |result, formatted_results|
291
- test_name, measures = result
292
- result_date = measures.delete('result_date')
293
-
294
- formatted_results[test_name] = {
295
- results: measures.each_with_object({}) do |measure, processed_measures|
296
- processed_measures[measure[0]] = { 'result_value' => measure[1] }
297
- end,
298
- result_date: result_date,
299
- result_entered_by: {}
300
- }
301
- end
302
- )
303
- end
304
-
305
- def patch_order_dto_with_lims_order!(order_dto, lims_order)
306
- order_dto.merge!(
307
- 'sample_type' => lims_order['other']['sample_type'],
308
- 'sample_status' => lims_order['other']['specimen_status'],
309
- 'priority' => lims_order['other']['priority']
310
- )
311
- end
312
-
313
- def update_order_results(order_dto)
314
- return nil if order_dto['test_results'].nil? || order_dto['test_results'].empty?
315
-
316
- order_dto['test_results'].each do |test_name, results|
317
- Rails.logger.info("Pushing result for order ##{order_dto['tracking_number']}")
318
- in_authenticated_session do |headers|
319
- params = make_update_test_params(order_dto['tracking_number'], test_name, results)
320
-
321
- RestClient.post(expand_uri('update_test'), params, headers)
322
- end
323
- end
324
- end
325
-
326
- def make_update_test_params(tracking_number, test_name, results, test_status = 'Drawn')
327
- {
328
- tracking_number: tracking_number,
329
- test_name: test_name,
330
- result_date: results['result_date'],
331
- time_updated: results['result_date'],
332
- who_updated: {
333
- first_name: results[:result_entered_by][:first_name],
334
- last_name: results[:result_entered_by][:last_name],
335
- id_number: results[:result_entered_by][:id]
336
- },
337
- test_status: test_status,
338
- results: results['results']&.each_with_object({}) do |measure, formatted_results|
339
- measure_name, measure_value = measure
340
-
341
- formatted_results[measure_name] = measure_value['result_value']
342
- end
343
- }
344
- end
345
-
346
- def find_test_status(order_dto, target_test, target_status)
347
- order_dto['test_statuses'].each do |test, statuses|
348
- next unless test.casecmp?(target_test)
349
-
350
- statuses.each do |date, status|
351
- next unless status['status'].casecmp?(target_status)
352
-
353
- return [Date.strptime(date, '%Y%m%d%H%M%S'), status]
354
- end
355
- end
356
-
357
- nil
358
- end
359
-
360
- def make_void_test_params(tracking_number, test_name, voided_by, void_date = nil)
361
- void_date ||= Time.now
362
-
363
- {
364
- tracking_number: tracking_number,
365
- test_name: test_name,
366
- time_updated: void_date,
367
- who_updated: {
368
- first_name: voided_by[:first_name],
369
- last_name: voided_by[:last_name],
370
- id_number: voided_by[:id]
371
- },
372
- test_status: 'voided'
373
- }
374
- end
375
-
376
- def orders_pending_updates(patient_id = nil)
377
- Rails.logger.info('Looking for orders that need to be updated...')
378
- orders = {}
379
-
380
- orders_without_specimen(patient_id).each { |order| orders[order.order_id] = order }
381
- orders_without_results(patient_id).each { |order| orders[order.order_id] = order }
382
- orders_without_reason(patient_id).each { |order| orders[order.order_id] = order }
383
-
384
- orders.values
385
- end
386
-
387
- def orders_without_specimen(patient_id = nil)
388
- Rails.logger.debug('Looking for orders without a specimen')
389
- unknown_specimen = ConceptName.where(name: Lab::Metadata::UNKNOWN_SPECIMEN)
390
- .select(:concept_id)
391
- orders = Lab::LabOrder.where(concept_id: unknown_specimen)
392
- .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id))
393
- orders = orders.where(patient_id: patient_id) if patient_id
394
-
395
- orders
396
- end
397
-
398
- def orders_without_results(patient_id = nil)
399
- Rails.logger.debug('Looking for orders without a result')
400
- # Lab::OrdersSearchService.find_orders_without_results(patient_id: patient_id)
401
- # .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id).where("pulled_at IS NULL"))
402
- Lab::OrdersSearchService.find_orders_without_results(patient_id: patient_id)
403
- .where(order_id: Lab::LimsOrderMapping.select(:order_id))
404
- end
405
-
406
- def orders_without_reason(patient_id = nil)
407
- Rails.logger.debug('Looking for orders without a reason for test')
408
- orders = Lab::LabOrder.joins(:reason_for_test)
409
- .merge(Observation.where(value_coded: nil, value_text: nil))
410
- .limit(1000)
411
- .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id))
412
- orders = orders.where(patient_id: patient_id) if patient_id
413
-
414
- orders
415
- end
416
- end
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'socket.io-client-simple'
4
-
5
- module Lab
6
- module Lims
7
- module Api
8
- ##
9
- # Retrieve results from LIMS only through a websocket
10
- class WsApi
11
- def initialize(config)
12
- @config = config
13
- @results_queue = []
14
- @socket = nil
15
- end
16
-
17
- def consume_orders(**_kwargs)
18
- loop do
19
- results = fetch_results
20
- unless results
21
- Rails.logger.debug('No results available... Waiting for results...')
22
- sleep(Lab::Lims::Config.updates_poll_frequency)
23
- next
24
- end
25
-
26
- Rails.logger.info("Received result for ##{results['tracking_number']}")
27
- order = find_order(results['tracking_number'])
28
- next unless order
29
-
30
- Rails.logger.info("Updating result for order ##{order.order_id}")
31
- yield make_order_dto(order, results), OpenStruct.new(last_seq: 1)
32
- end
33
- end
34
-
35
- private
36
-
37
- def initialize_socket
38
- Rails.logger.debug('Establishing connection to socket...')
39
- socket = SocketIO::Client::Simple.connect(socket_url)
40
- socket.on(:connect, &method(:on_socket_connect))
41
- socket.on(:disconnect, &method(:on_socket_disconnect))
42
- socket.on(:results, &method(:on_results_received))
43
- end
44
-
45
- def socket_url
46
- @config.fetch('url')
47
- end
48
-
49
- def on_socket_connect
50
- Rails.logger.debug('Connection to LIMS results socket established...')
51
- end
52
-
53
- def on_socket_disconnect
54
- Rails.logger.debug('Connection to LIMS results socket lost...')
55
- @socket = nil
56
- end
57
-
58
- def on_results_received(result)
59
- Rails.logger.debug("Received result from LIMS: #{result}")
60
- tracking_number = result['tracking_number']
61
-
62
- Rails.logger.debug("Queueing result for order ##{tracking_number}")
63
- @results_queue.push(result)
64
- end
65
-
66
- def order_exists?(tracking_number)
67
- Rails.logger.debug("Looking for order for result ##{tracking_number}")
68
- orders = OrdersSearchService.find_orders_without_results
69
- .where(accession_number: tracking_number)
70
- # The following ensures that the order was previously pushed to LIMS
71
- # or was received from LIMS
72
- Lab::LimsOrderMapping.where.not(order: orders).exists?
73
- end
74
-
75
- def fetch_results
76
- loop do
77
- @socket ||= initialize_socket
78
-
79
- results = @results_queue.shift
80
- return nil unless results
81
-
82
- unless order_exists?(results['tracking_number'])
83
- Rails.logger.debug("Ignoring result for order ##{tracking_number}")
84
- next
85
- end
86
-
87
- return results
88
- end
89
- end
90
-
91
- def find_order(lims_id)
92
- mapping = Lab::LimsOrderMapping.where(lims_id: lims_id).select(:order_id)
93
- Lab::LabOrder.find_by(order_id: mapping)
94
- end
95
-
96
- def make_order_dto(order, results)
97
- Lab::Lims::OrderSerializer
98
- .serialize_order(order)
99
- .merge(
100
- id: order.accession_number,
101
- test_results: {
102
- results['test_name'] => {
103
- results: results['results'].each_with_object({}) do |measure, formatted_measures|
104
- measure_name, measure_value = measure
105
-
106
- formatted_measures[measure_name] = { result_value: measure_value }
107
- end,
108
- result_date: results['date_updated'],
109
- result_entered_by: {
110
- first_name: results['who_updated']['first_name'],
111
- last_name: results['who_updated']['last_name'],
112
- id: results['who_updated']['id_number']
113
- }
114
- }
115
- }
116
- )
117
- end
118
- end
119
- end
120
- end
121
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lab
4
- module Lims
5
- ##
6
- # Creates LIMS Apis based on current configuration
7
- module ApiFactory
8
- def self.create_api
9
- return Lab::Lims::Api::BlackholeApi.new if Rails.env.casecmp?('test')
10
-
11
- case Lab::Lims::Config.preferred_api
12
- when /rest/i then Lab::Lims::Api::RestApi.new(Lab::Lims::Config.rest_api)
13
- when /couchdb/ then Lab::Lims::Api::CouchDbApi.new(config: Lab::Lims::Config.couchdb_api)
14
- else raise "Invalid lims_api configuration: #{Lab::Lims::Config.preferred_api}"
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lab
4
- module Lims
5
- ##
6
- # Load LIMS' configuration files
7
- module Config
8
- # TODO: Replace this maybe with `Rails.application.configuration.lab.lims`
9
- # so that we do not have to directly mess with configuration files.
10
-
11
- class ConfigNotFound < RuntimeError; end
12
-
13
- class << self
14
- def preferred_api
15
- emr_api_application('lims_api')
16
- end
17
-
18
- ##
19
- # Returns LIMS' couchdb configuration file for the current environment (Rails.env)
20
- def couchdb
21
- config_path = begin
22
- find_config_path('couchdb.yml')
23
- rescue ConfigNotFound => e
24
- Rails.logger.error("Failed to find default LIMS couchdb config: #{e.message}")
25
- find_config_path('couchdb-lims.yml') # This can be placed in HIS-EMR-API/config
26
- end
27
-
28
- Rails.logger.debug("Using LIMS couchdb config: #{config_path}")
29
-
30
- YAML.load_file(config_path)[Rails.env]
31
- end
32
-
33
- def rest_api
34
- @rest_api ||= {
35
- protocol: emr_api_application('lims_protocol', 'http'),
36
- host: emr_api_application('lims_host'),
37
- port: emr_api_application('lims_port'),
38
- username: emr_api_application('lims_username'),
39
- password: emr_api_application('lims_password')
40
- }
41
- end
42
-
43
- def updates_socket
44
- @updates_socket ||= {
45
- 'url' => emr_api_application('lims_realtime_updates_url')
46
- }
47
- end
48
-
49
- def updates_poll_frequency
50
- 30 # Seconds
51
- end
52
-
53
- ##
54
- # Returns LIMS' application.yml configuration file
55
- def application
56
- @application ||= YAML.load_file(find_config_path('application.yml'))
57
- end
58
-
59
- ##
60
- # Returns LIMS' database.yml configuration file
61
- def database
62
- @database ||= YAML.load_file(find_config_path('database.yml'))
63
- end
64
-
65
- private
66
-
67
- def emr_api_application(param, fallback = nil)
68
- @emr_api_application ||= YAML.load_file(Rails.root.join('config', 'application.yml'))
69
-
70
- @emr_api_application.fetch(param) do
71
- raise ConfigNotFound, "Missing config param: #{param}" unless fallback
72
-
73
- fallback
74
- end
75
- end
76
-
77
- ##
78
- # Looks for a config file in various LIMS installation directories
79
- #
80
- # Returns: a path to a file found
81
- def find_config_path(filename)
82
- paths = [
83
- "#{ENV['HOME']}/apps/nlims_controller/config/#{filename}",
84
- "/var/www/nlims_controller/config/#{filename}",
85
- Rails.root.parent.join("nlims_controller/config/#{filename}")
86
- ]
87
-
88
- paths = [Rails.root.join('config/lims-couchdb.yml'), *paths] if filename == 'couchdb.yml'
89
-
90
- paths.each do |path|
91
- Rails.logger.debug("Looking for LIMS couchdb config at: #{path}")
92
- return path if File.exist?(path)
93
- end
94
-
95
- raise ConfigNotFound, "Could not find a configuration file, checked: #{paths.join(':')}"
96
- end
97
- end
98
- end
99
- end
100
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lab
4
- module Lims
5
- class LimsException < StandardError; end
6
- class DuplicateNHID < LimsException; end
7
- class MissingAccessionNumber < LimsException; end
8
- class UnknownSpecimenType < LimsException; end
9
- class UnknownTestType < LimsException; end
10
- end
11
- end