his_emr_api_lab 1.1.13 → 1.1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7b7bee82670948e0315bde7a3d0f9cab91476bcb27646ec7c234e0c96d11bc9
4
- data.tar.gz: 127d70d6a044a8ddc5dcc25ed2460d1fcb463d8f27f3817b54fca7d5ada6d88a
3
+ metadata.gz: 9180f5367d311361a972c4ec15d72bbd6296731adf1bd71b4ae25a1ff58dc4b5
4
+ data.tar.gz: d6b399321648924e31cecda13c4348b53370796a89344947b0932f0720ed0b11
5
5
  SHA512:
6
- metadata.gz: 421db4bdc5cb32b994d9329c87ebe8c79eae681765abe980bd87c6fab83c70de74961d78845d2602af31aea018b480ddcad9f97de4dfa01a8cd975c8c9a49db8
7
- data.tar.gz: 4d1c1df19df7b297e66d44055bcbe88b410f25e744a56f0bb46a99f8fd06af9e25ad332499cbd34e8ea10f7879c14455f8b16d376e24c7a50bf7518156ce3646
6
+ metadata.gz: 284aab03e785c885b3e1a88f8fef8826c73c89b9f7436e17aa730d14c2f3fc5fe14cb65e2f29ce6171675a363c5945b73d547094f11a4187d67dbdfc9636c4dd
7
+ data.tar.gz: 0c849e47f58c86fd221f9c97111c0028f3fafdad3cf07393baf64928ebd462008895550fd4ab754e2708654cde5867fb81abb07dcbdd289454e4da14bbafd4d2
@@ -8,14 +8,15 @@ module Lab
8
8
  OrdersService.order_test(order_params)
9
9
  end
10
10
 
11
+ orders.each { |order| Lab::PushOrderJob.perform_later(order.fetch(:order_id)) }
12
+
11
13
  render json: orders, status: :created
12
14
  end
13
15
 
14
16
  def update
15
17
  specimen = params.require(:specimen).permit(:concept_id)
16
-
17
- order = OrdersService.update_order(params[:id], specimen: specimen,
18
- force_update: params[:force_update])
18
+ order = OrdersService.update_order(params[:id], specimen: specimen, force_update: params[:force_update])
19
+ Lab::PushOrderJob.perform_later(order.fetch(:order_id))
19
20
 
20
21
  render json: order
21
22
  end
@@ -23,11 +24,13 @@ module Lab
23
24
  def index
24
25
  filters = params.permit(%i[patient_id accession_number date status])
25
26
 
27
+ Lab::UpdatePatientOrdersJob.perform_later(filters[:patient_id]) if filters[:patient_id]
26
28
  render json: OrdersSearchService.find_orders(filters)
27
29
  end
28
30
 
29
31
  def destroy
30
32
  OrdersService.void_order(params[:id], params[:reason])
33
+ Lab::VoidOrderJob.perform_later(params[:id])
31
34
 
32
35
  render status: :no_content
33
36
  end
@@ -14,7 +14,8 @@ class Lab::TestsController < ::ApplicationController
14
14
  order_id, test_concepts = test_params.require(%i[order_id tests])
15
15
  date = test_params[:date] || Date.today
16
16
 
17
- tests = service.create_tests(Order.find(order_id), date, test_concepts)
17
+ tests = service.create_tests(Lab::LabOrder.find(order_id), date, test_concepts)
18
+ Lab::PushOrderJob.perform_later(order_id)
18
19
 
19
20
  render json: tests, status: :created
20
21
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lab
4
+ ##
5
+ # Push an order to LIMS.
6
+ class PushOrderJob < ApplicationJob
7
+ def perform(order_id)
8
+ push_worker = Lab::Lims::PushWorker.new(Lab::Lims::ApiFactory.create_api)
9
+ push_worker.push_order_by_id(order_id)
10
+ end
11
+ end
12
+ end
@@ -20,8 +20,7 @@ module Lab
20
20
  break false
21
21
  end
22
22
 
23
- lims_api = Lab::Lims::Api::RestApi.new(Lab::Lims::Config.rest_api)
24
- worker = Lab::Lims::PullWorker.new(lims_api)
23
+ worker = Lab::Lims::PullWorker.new(Lab::Lims::ApiFactory.create_api)
25
24
  worker.pull_orders(patient_id: patient_id)
26
25
 
27
26
  true
@@ -10,8 +10,7 @@ module Lab
10
10
  User.current = Lab::Lims::Utils.lab_user
11
11
  Location.current = Location.find_by_name('ART clinic')
12
12
 
13
- lims_api = Lab::Lims::Api::RestApi.new
14
- worker = Lab::Lims::Worker.new(lims_api)
13
+ worker = Lab::Lims::PushWorker.new(Lab::Lims::ApiFactory.create_api)
15
14
  worker.push_order(Lab::LabOrder.unscoped.find(order_id))
16
15
  end
17
16
  end
@@ -42,7 +42,6 @@ module Lab
42
42
  end
43
43
 
44
44
  scope :drawn, -> { where.not(concept_id: ConceptName.where(name: 'Unknown').select(:concept_id)) }
45
-
46
45
  scope :not_drawn, -> { where(concept_id: ConceptName.where(name: 'Unknown').select(:concept_id)) }
47
46
 
48
47
  def self.prefetch_relationships
@@ -6,7 +6,7 @@ module Lab
6
6
  tests ||= order.voided == 1 ? voided_tests(order) : order.tests
7
7
  requesting_clinician ||= order.requesting_clinician
8
8
  reason_for_test ||= order.reason_for_test
9
- target_lab = target_lab || order.target_lab || Location.current_health_center.name
9
+ target_lab = target_lab&.value_text || order.target_lab&.value_text || Location.current_health_center&.name
10
10
 
11
11
  ActiveSupport::HashWithIndifferentAccess.new(
12
12
  {
@@ -21,7 +21,7 @@ module Lab
21
21
  name: concept_name(order.concept_id)
22
22
  },
23
23
  requesting_clinician: requesting_clinician&.value_text,
24
- target_lab: target_lab&.value_text,
24
+ target_lab: target_lab,
25
25
  reason_for_test: {
26
26
  concept_id: reason_for_test&.value_coded,
27
27
  name: concept_name(reason_for_test&.value_coded)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lab
4
+ module Lims
5
+ module Api
6
+ ##
7
+ # A LIMS Api wrappper that does nothing really.
8
+ #
9
+ # Primarily meant as a dummy for testing environments.
10
+ class BlackholeApi
11
+ def create_order(order_dto); end
12
+
13
+ def update_order(order_dto); end
14
+
15
+ def void_order(order_dto); end
16
+
17
+ def consume_orders(&_block); end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -395,7 +395,7 @@ class Lab::Lims::Api::RestApi
395
395
  def orders_without_results(patient_id = nil)
396
396
  Rails.logger.debug('Looking for orders without a result')
397
397
  Lab::OrdersSearchService.find_orders_without_results(patient_id: patient_id)
398
- .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id))
398
+ .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id).where("pulled_at IS NULL"))
399
399
  end
400
400
 
401
401
  def orders_without_reason(patient_id = nil)
@@ -0,0 +1,19 @@
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
@@ -46,9 +46,20 @@ require_relative 'utils'
46
46
 
47
47
  module Lab
48
48
  module Lims
49
+ ##
50
+ # Tools for performing a bulk import of data from LIMS' databases to local OpenMRS database.
51
+ #
52
+ # Migration sources supported:
53
+ # - MySQL
54
+ # - CouchDB
55
+ #
56
+ # The sources above can be changed by setting the environment various MIGRATION_SOURCE to
57
+ # either mysql or couchdb.
49
58
  module Migrator
50
59
  MAX_THREADS = ENV.fetch('MIGRATION_WORKERS', 6).to_i
51
60
 
61
+ ##
62
+ # A Lab::Lims::Api object that supports crawling of a LIMS CouchDB instance.
52
63
  class CouchDbMigratorApi < Lab::Lims::Api::CouchDbApi
53
64
  def initialize(*args, processes: 1, on_merge_processes: nil, **kwargs)
54
65
  super(*args, **kwargs)
@@ -91,6 +102,12 @@ module Lab
91
102
  end
92
103
  end
93
104
 
105
+ ##
106
+ # Extends the PullWorker to provide pause/resume capabilities.
107
+ #
108
+ # Migrations can be take a long time to complete, in cases where something
109
+ # went wrong you wouldn't to start all over. This worker thus saves
110
+ # progress and allows for the process to continue from whether it stopped.
94
111
  class MigrationWorker < PullWorker
95
112
  LOG_FILE_PATH = Utils::LIMS_LOG_PATH.join('migration-last-id.dat')
96
113
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Lab
4
4
  module Lims
5
+ ##
6
+ # Pulls orders from a Lims API object and saves them to the local database.
5
7
  class PullWorker
6
8
  attr_reader :lims_api
7
9
 
@@ -100,9 +102,7 @@ module Lab
100
102
  .distinct(:patient_id)
101
103
  .all
102
104
 
103
- if patients.size > 1
104
- raise DuplicateNHID, "Duplicate National Health ID: #{nhid}"
105
- end
105
+ raise DuplicateNHID, "Duplicate National Health ID: #{nhid}" if patients.size > 1
106
106
 
107
107
  patients.first
108
108
  end
@@ -166,9 +166,7 @@ module Lab
166
166
  def create_order(patient, order_dto)
167
167
  logger.debug("Creating order ##{order_dto['_id']}")
168
168
  order = OrdersService.order_test(order_dto.to_order_service_params(patient_id: patient.patient_id))
169
- unless order_dto['test_results'].empty?
170
- update_results(order, order_dto['test_results'])
171
- end
169
+ update_results(order, order_dto['test_results']) unless order_dto['test_results'].empty?
172
170
 
173
171
  order
174
172
  end
@@ -177,9 +175,7 @@ module Lab
177
175
  logger.debug("Updating order ##{order_dto['_id']}")
178
176
  order = OrdersService.update_order(order_id, order_dto.to_order_service_params(patient_id: patient.patient_id)
179
177
  .merge(force_update: 'true'))
180
- unless order_dto['test_results'].empty?
181
- update_results(order, order_dto['test_results'])
182
- end
178
+ update_results(order, order_dto['test_results']) unless order_dto['test_results'].empty?
183
179
 
184
180
  order
185
181
  end
@@ -283,9 +279,7 @@ module Lab
283
279
  mapping = Lab::LimsOrderMapping.find_by(lims_id: lims_id)
284
280
  return nil unless mapping
285
281
 
286
- if Lab::LabOrder.where(order_id: mapping.order_id).exists?
287
- return mapping
288
- end
282
+ return mapping if Lab::LabOrder.where(order_id: mapping.order_id).exists?
289
283
 
290
284
  mapping.destroy
291
285
  nil
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Lab
4
4
  module Lims
5
+ ##
6
+ # Pushes all local orders to a LIMS Api object.
5
7
  class PushWorker
6
8
  attr_reader :lims_api
7
9
 
@@ -33,7 +35,9 @@ module Lab
33
35
  end
34
36
 
35
37
  def push_order_by_id(order_id)
36
- order = Lab::LabOrder.unscoped.find(order_id)
38
+ order = Lab::LabOrder.joins(order_type: { name: 'Lab' })
39
+ .unscoped
40
+ .find(order_id)
37
41
  push_order(order)
38
42
  end
39
43
 
@@ -79,11 +79,7 @@ module Lab
79
79
  end
80
80
 
81
81
  def self.lims_api
82
- case Lims::Config.preferred_api
83
- when /couchdb/i then Api::CouchDbApi.new(config: Lab::Lims::Config.couchdb)
84
- when /rest/i then Api::RestApi.new(Lab::Lims::Config.rest_api)
85
- else raise "Invalid LIMS API in application.yml, expected 'rest' or 'couchdb'"
86
- end
82
+ Lab::Lims::ApiFactory.create_api
87
83
  end
88
84
  end
89
85
  end
@@ -5,14 +5,6 @@ module Lab
5
5
  module OrdersSearchService
6
6
  class << self
7
7
  def find_orders(filters)
8
- # A bit of hack-ish solution to have a patient's orders updated upon
9
- # scanning of a patient. Done in this way to deal with LIMS' lack of
10
- # a notification system for lab order updates. We are limited to polling
11
- # for updates on a per order basis.
12
- if filters[:patient_id]
13
- Lab::UpdatePatientOrdersJob.perform_later(filters[:patient_id])
14
- end
15
-
16
8
  extra_filters = pop_filters(filters, :date, :end_date, :status)
17
9
 
18
10
  orders = Lab::LabOrder.prefetch_relationships
@@ -39,13 +31,9 @@ module Lab
39
31
  date = date&.to_date
40
32
  end_date = end_date&.to_date
41
33
 
42
- if date && end_date
43
- return orders.where('start_date BETWEEN ? AND ?', date, end_date + 1.day)
44
- end
34
+ return orders.where('start_date BETWEEN ? AND ?', date, end_date + 1.day) if date && end_date
45
35
 
46
- if date
47
- return orders.where('start_date BETWEEN ? AND ?', date, date + 1.day)
48
- end
36
+ return orders.where('start_date BETWEEN ? AND ?', date, date + 1.day) if date
49
37
 
50
38
  return orders.where('start_date < ?', end_date + 1.day) if end_date
51
39
 
@@ -100,7 +100,6 @@ module Lab
100
100
 
101
101
  order.tests.each { |test| test.void(reason) }
102
102
  voided = order.void(reason)
103
- Lab::VoidOrderJob.perform_later(order_id)
104
103
 
105
104
  voided
106
105
  end
data/lib/lab/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lab
4
- VERSION = '1.1.13'
4
+ VERSION = '1.1.17'
5
5
  end
@@ -23,10 +23,16 @@ class LoggerMultiplexor
23
23
  end
24
24
 
25
25
  def method_missing(method_name, *args)
26
- @loggers.each { |logger| logger.method(method_name).call(*args) }
26
+ if respond_to_missing?(method_name)
27
+ @loggers.each { |logger| logger.send(method_name, *args) }
28
+ else
29
+ super
30
+ end
27
31
  end
28
32
 
29
33
  def respond_to_missing?(method_name)
30
- @loggers.all? { |logger| logger.respond_to_missing?(method_name) }
34
+ @loggers.all? do |logger|
35
+ logger.respond_to?(method_name)
36
+ end
31
37
  end
32
38
  end
@@ -68,6 +68,7 @@
68
68
  "Hepatitis B Test","Hepatitis B"
69
69
  "Hepatitis C Test","Hepatitis C"
70
70
  "Rheumatoid Factor Test","Rheumatoid Factor"
71
+ "CrAg","CrAg"
71
72
  "Cryptococcus Antigen Test","CrAg"
72
73
  "Anti Streptolysis O","ASO"
73
74
  "C-reactive protein","CRP"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: his_emr_api_lab
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.13
4
+ version: 1.1.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elizabeth Glaser Pediatric Foundation Malawi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-06 00:00:00.000000000 Z
11
+ date: 2021-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: couchrest
@@ -248,6 +248,7 @@ files:
248
248
  - app/controllers/lab/test_types_controller.rb
249
249
  - app/controllers/lab/tests_controller.rb
250
250
  - app/jobs/lab/application_job.rb
251
+ - app/jobs/lab/push_order_job.rb
251
252
  - app/jobs/lab/update_patient_orders_job.rb
252
253
  - app/jobs/lab/void_order_job.rb
253
254
  - app/mailers/lab/application_mailer.rb
@@ -265,10 +266,12 @@ files:
265
266
  - app/services/lab/accession_number_service.rb
266
267
  - app/services/lab/concepts_service.rb
267
268
  - app/services/lab/labelling_service/order_label.rb
269
+ - app/services/lab/lims/api/blackhole_api.rb
268
270
  - app/services/lab/lims/api/couchdb_api.rb
269
271
  - app/services/lab/lims/api/mysql_api.rb
270
272
  - app/services/lab/lims/api/rest_api.rb
271
273
  - app/services/lab/lims/api/ws_api.rb
274
+ - app/services/lab/lims/api_factory.rb
272
275
  - app/services/lab/lims/config.rb
273
276
  - app/services/lab/lims/exceptions.rb
274
277
  - app/services/lab/lims/migrator.rb
@@ -331,7 +334,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
331
334
  - !ruby/object:Gem::Version
332
335
  version: '0'
333
336
  requirements: []
334
- rubygems_version: 3.1.4
337
+ rubygems_version: 3.2.3
335
338
  signing_key:
336
339
  specification_version: 4
337
340
  summary: Lab extension for the HIS-EMR-API