his_emr_api_lab 1.1.12 → 1.1.16
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 +4 -4
- data/app/controllers/lab/orders_controller.rb +6 -3
- data/app/controllers/lab/tests_controller.rb +2 -1
- data/app/jobs/lab/push_order_job.rb +12 -0
- data/app/jobs/lab/update_patient_orders_job.rb +1 -2
- data/app/jobs/lab/void_order_job.rb +1 -2
- data/app/models/lab/lab_order.rb +0 -1
- data/app/serializers/lab/lab_order_serializer.rb +2 -2
- data/app/services/lab/lims/api/blackhole_api.rb +21 -0
- data/app/services/lab/lims/api_factory.rb +19 -0
- data/app/services/lab/lims/migrator.rb +17 -0
- data/app/services/lab/lims/pull_worker.rb +6 -12
- data/app/services/lab/lims/push_worker.rb +5 -1
- data/app/services/lab/lims/worker.rb +1 -5
- data/app/services/lab/orders_search_service.rb +2 -14
- data/app/services/lab/orders_service.rb +2 -1
- data/lib/lab/version.rb +1 -1
- data/lib/logger_multiplexor.rb +8 -2
- data/lib/tasks/loaders/data/test-measures.csv +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31eb65eeca1c291f733da313a36a6477143ed6119afa9858cd7afb6979ef75bd
|
4
|
+
data.tar.gz: 3f753f4313b69f613388c2517a8efe7936871baad6adb43dfc8475ecfe303688
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94ba7f43627d0def3edb609439535f9a715b695afda5ba43a494b673f421b1878cda6386b2b58c9960990f58c5156f308d85a5909668aad7c1dba97ab4aae2a9
|
7
|
+
data.tar.gz: 2f2d3552dcbe2608623066a65bb4fff59932aea55b3ab4b8a24478cc773161b6b1149c4bba08175233e4c6a43d3ed247abd889fcf258528c31bb4c4e8c89c35e
|
@@ -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
|
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(
|
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
|
-
|
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
|
-
|
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
|
data/app/models/lab/lab_order.rb
CHANGED
@@ -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
|
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
|
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
|
@@ -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.
|
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
|
-
|
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
|
@@ -169,6 +168,8 @@ module Lab
|
|
169
168
|
##
|
170
169
|
# Attach the lab where the test is going to get carried out.
|
171
170
|
def add_target_lab(order, params)
|
171
|
+
return nil unless params['target_lab']
|
172
|
+
|
172
173
|
create_order_observation(
|
173
174
|
order,
|
174
175
|
Lab::Metadata::TARGET_LAB_CONCEPT_NAME,
|
data/lib/lab/version.rb
CHANGED
data/lib/logger_multiplexor.rb
CHANGED
@@ -23,10 +23,16 @@ class LoggerMultiplexor
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def method_missing(method_name, *args)
|
26
|
-
|
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?
|
34
|
+
@loggers.all? do |logger|
|
35
|
+
logger.respond_to?(method_name)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
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.
|
4
|
+
version: 1.1.16
|
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-
|
11
|
+
date: 2021-10-17 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
|