his_emr_api_lab 1.1.13 → 1.1.17

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.
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