his_emr_api_lab 1.2.0 → 2.0.1
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/Rakefile +3 -1
- data/app/controllers/lab/application_controller.rb +5 -0
- data/app/controllers/lab/orders_controller.rb +3 -3
- data/app/controllers/lab/specimen_types_controller.rb +1 -1
- data/app/controllers/lab/test_result_indicators_controller.rb +6 -4
- data/app/controllers/lab/test_types_controller.rb +1 -1
- data/app/controllers/lab/tests_controller.rb +20 -17
- data/app/jobs/lab/application_job.rb +2 -0
- data/app/jobs/lab/update_patient_orders_job.rb +1 -1
- data/app/mailers/lab/application_mailer.rb +2 -0
- data/app/models/lab/application_record.rb +2 -0
- data/app/models/lab/lab_order.rb +1 -1
- data/app/models/lab/lims_failed_import.rb +2 -0
- data/app/serializers/lab/lab_order_serializer.rb +2 -2
- data/app/serializers/lab/result_serializer.rb +2 -2
- data/app/services/lab/accession_number_service.rb +2 -2
- data/app/services/lab/concepts_service.rb +2 -2
- data/app/services/lab/labelling_service/order_label.rb +2 -2
- data/app/services/lab/lims/api/blackhole_api.rb +1 -1
- data/app/services/lab/lims/api/couchdb_api.rb +3 -3
- data/app/services/lab/lims/api/mysql_api.rb +6 -6
- data/app/services/lab/lims/api/rest_api.rb +378 -372
- data/app/services/lab/lims/api/ws_api.rb +1 -1
- data/app/services/lab/lims/api_factory.rb +1 -1
- data/app/services/lab/lims/config.rb +1 -1
- data/app/services/lab/lims/exceptions.rb +1 -0
- data/app/services/lab/lims/migrator.rb +11 -12
- data/app/services/lab/lims/order_dto.rb +4 -4
- data/app/services/lab/lims/order_serializer.rb +12 -12
- data/app/services/lab/lims/pull_worker.rb +17 -14
- data/app/services/lab/lims/push_worker.rb +14 -5
- data/app/services/lab/lims/utils.rb +12 -8
- data/app/services/lab/lims/worker.rb +1 -1
- data/app/services/lab/orders_search_service.rb +3 -3
- data/app/services/lab/orders_service.rb +5 -5
- data/app/services/lab/results_service.rb +3 -3
- data/app/services/lab/tests_service.rb +5 -5
- data/db/migrate/20210126092910_create_lab_lab_accession_number_counters.rb +2 -0
- data/db/migrate/20210310115457_create_lab_lims_order_mappings.rb +2 -0
- data/db/migrate/20210326195504_add_order_revision_to_lims_order_mapping.rb +2 -0
- data/db/migrate/20210610095024_fix_numeric_results_value_type.rb +2 -0
- data/db/migrate/20210807111531_add_default_to_lims_order_mapping.rb +2 -0
- data/lib/auto12epl.rb +62 -54
- data/lib/couch_bum/couch_bum.rb +4 -4
- data/lib/generators/lab/install/templates/rswag-ui-lab.rb +2 -0
- data/lib/his_emr_api_lab.rb +2 -0
- data/lib/lab/engine.rb +2 -0
- data/lib/lab/version.rb +1 -1
- data/lib/logger_multiplexor.rb +2 -2
- data/lib/tasks/lab_tasks.rake +2 -0
- data/lib/tasks/loaders/loader_mixin.rb +4 -4
- data/lib/tasks/loaders/reasons_for_test_loader.rb +1 -1
- data/lib/tasks/loaders/specimens_loader.rb +6 -7
- data/lib/tasks/loaders/test_result_indicators_loader.rb +5 -5
- metadata +15 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8ec4677af7163c2d90687ca46d2ebdfa5e438abe0d705a621545d26d2889b7e
|
4
|
+
data.tar.gz: 8a071aaef1ce28cae2b57253e739f406f60fe0724a8379414c667d20e756efa6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cddefdce79e09c49a190fc3c31d92eb15d5394b1fe1a5187d2a54c614d48da06b75d7863e24cf5196c076adc2c3400119d8a108ffdb62a72bdc85cf3523c7b55
|
7
|
+
data.tar.gz: caf9c33fc7480884576e83f07335d768705255a2586508c2e616cca9f0667cc422cde28267e3234f9995deb99727f5b2d482db4019fdfba6d83fdd699536c6e4
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'bundler/setup'
|
3
5
|
rescue LoadError
|
@@ -14,7 +16,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
14
16
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
17
|
end
|
16
18
|
|
17
|
-
APP_RAKEFILE = File.expand_path(
|
19
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
18
20
|
load 'rails/tasks/engine.rake'
|
19
21
|
|
20
22
|
load 'rails/tasks/statistics.rake'
|
@@ -17,15 +17,15 @@ module Lab
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def update
|
20
|
-
specimen = params.require(:specimen).
|
21
|
-
order = OrdersService.update_order(params[:id], specimen
|
20
|
+
specimen = params.require(:specimen).slice(:concept_id)
|
21
|
+
order = OrdersService.update_order(params[:id], specimen:, force_update: params[:force_update])
|
22
22
|
Lab::PushOrderJob.perform_later(order.fetch(:order_id))
|
23
23
|
|
24
24
|
render json: order
|
25
25
|
end
|
26
26
|
|
27
27
|
def index
|
28
|
-
filters = params.
|
28
|
+
filters = params.slice(:patient_id, :accession_number, :date, :status)
|
29
29
|
|
30
30
|
Lab::UpdatePatientOrdersJob.perform_later(filters[:patient_id]) if filters[:patient_id]
|
31
31
|
render json: OrdersSearchService.find_orders(filters)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Lab
|
4
4
|
class SpecimenTypesController < ApplicationController
|
5
5
|
def index
|
6
|
-
filters = params.
|
6
|
+
filters = params.slice(:name, :test_type)
|
7
7
|
|
8
8
|
specimen_types = ConceptsService.specimen_types(name: filters['name'],
|
9
9
|
test_type: filters['test_type'])
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Lab
|
4
|
+
class TestResultIndicatorsController < ApplicationController
|
5
|
+
def index
|
6
|
+
test_type_id = params.require(:test_type_id)
|
6
7
|
|
7
|
-
|
8
|
+
render json: Lab::ConceptsService.test_result_indicators(test_type_id)
|
9
|
+
end
|
8
10
|
end
|
9
11
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Lab
|
4
4
|
class TestTypesController < ApplicationController
|
5
5
|
def index
|
6
|
-
filters = params.
|
6
|
+
filters = params.slice(:name, :specimen_type)
|
7
7
|
|
8
8
|
test_types = ConceptsService.test_types(name: filters['name'],
|
9
9
|
specimen_type: filters['specimen_type'])
|
@@ -1,26 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Lab
|
4
|
+
class TestsController < ApplicationController
|
5
|
+
def index
|
6
|
+
filters = params.slice(:order_date, :accession_number, :patient_id, :test_type_id, :specimen_type_id,
|
7
|
+
:pending_results)
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
tests = service.find_tests(filters)
|
10
|
+
render json: tests
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
# Add a specimen to an existing order
|
14
|
+
def create
|
15
|
+
test_params = params.slice(:order_id, :date, tests: [:concept_id])
|
16
|
+
order_id, test_concepts = test_params.require(%i[order_id tests])
|
17
|
+
date = test_params[:date] || Date.today
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
tests = service.create_tests(Lab::LabOrder.find(order_id), date, test_concepts)
|
20
|
+
Lab::PushOrderJob.perform_later(order_id)
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
render json: tests, status: :created
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
def service
|
26
|
+
Lab::TestsService
|
27
|
+
end
|
25
28
|
end
|
26
29
|
end
|
data/app/models/lab/lab_order.rb
CHANGED
@@ -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
|
24
|
+
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)
|
@@ -50,7 +50,7 @@ module Lab
|
|
50
50
|
def self.voided_tests(order)
|
51
51
|
concept = ConceptName.where(name: Lab::Metadata::TEST_TYPE_CONCEPT_NAME)
|
52
52
|
.select(:concept_id)
|
53
|
-
LabTest.unscoped.where(concept
|
53
|
+
LabTest.unscoped.where(concept:, order:, voided: true)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -24,10 +24,10 @@ module Lab
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def find_counter(date)
|
27
|
-
counter = Lab::LabAccessionNumberCounter.find_by(date:
|
27
|
+
counter = Lab::LabAccessionNumberCounter.find_by(date:)
|
28
28
|
return counter if counter
|
29
29
|
|
30
|
-
Lab::LabAccessionNumberCounter.create(date
|
30
|
+
Lab::LabAccessionNumberCounter.create(date:, value: 1)
|
31
31
|
end
|
32
32
|
|
33
33
|
# Checks if date does not exceed system date
|
@@ -5,7 +5,7 @@ module Lab
|
|
5
5
|
module ConceptsService
|
6
6
|
def self.test_types(name: nil, specimen_type: nil)
|
7
7
|
test_types = ConceptSet.find_members_by_name(Lab::Metadata::TEST_TYPE_CONCEPT_NAME)
|
8
|
-
test_types = test_types.filter_members(name:
|
8
|
+
test_types = test_types.filter_members(name:) if name
|
9
9
|
|
10
10
|
unless specimen_type
|
11
11
|
return test_types.joins('INNER JOIN concept_name ON concept_set.concept_id = concept_name.concept_id AND concept_name.voided = 0 AND concept_name.locale_preferred = 1')
|
@@ -31,7 +31,7 @@ module Lab
|
|
31
31
|
|
32
32
|
def self.specimen_types(name: nil, test_type: nil)
|
33
33
|
specimen_types = ConceptSet.find_members_by_name(Lab::Metadata::SPECIMEN_TYPE_CONCEPT_NAME)
|
34
|
-
specimen_types = specimen_types.filter_members(name:
|
34
|
+
specimen_types = specimen_types.filter_members(name:) if name
|
35
35
|
|
36
36
|
unless test_type
|
37
37
|
return specimen_types.select('concept_name.concept_id, concept_name.name')
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative '../../../../lib/auto12epl'
|
4
4
|
|
5
5
|
module Lab
|
6
6
|
module LabellingService
|
@@ -89,7 +89,7 @@ module Lab
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def short_concept_name(concept_id)
|
92
|
-
ConceptName.where(concept_id:
|
92
|
+
ConceptName.where(concept_id:)
|
93
93
|
.min_by { |concept| concept.name.size }
|
94
94
|
&.name
|
95
95
|
end
|
@@ -9,7 +9,7 @@ module Lab
|
|
9
9
|
module Api
|
10
10
|
##
|
11
11
|
# Talk to LIMS like a boss
|
12
|
-
class
|
12
|
+
class CouchdbApi
|
13
13
|
attr_reader :bum
|
14
14
|
|
15
15
|
def initialize(config: nil)
|
@@ -30,10 +30,10 @@ module Lab
|
|
30
30
|
# given block until the queue is empty or connection is terminated
|
31
31
|
# by calling method +choke+.
|
32
32
|
def consume_orders(from: 0, limit: 30)
|
33
|
-
bum.binge_changes(since: from, limit
|
33
|
+
bum.binge_changes(since: from, limit:, include_docs: true) do |change|
|
34
34
|
next unless change['doc']['type']&.casecmp?('Order')
|
35
35
|
|
36
|
-
yield
|
36
|
+
yield OrderDto.new(change['doc']), self
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -28,7 +28,7 @@ module Lab
|
|
28
28
|
def consume_orders(from: nil, limit: 1000)
|
29
29
|
loop do
|
30
30
|
specimens_to_process = specimens(from, limit)
|
31
|
-
break if specimens_to_process.
|
31
|
+
break if specimens_to_process.empty?
|
32
32
|
|
33
33
|
processes = multiprocessed? ? @processes : 0
|
34
34
|
on_merge_processes = ->(_item, index, _result) { @on_merge_processes&.call(from + index) }
|
@@ -42,7 +42,7 @@ module Lab
|
|
42
42
|
end
|
43
43
|
|
44
44
|
dto = make_order_dto(
|
45
|
-
specimen
|
45
|
+
specimen:,
|
46
46
|
patient: specimen_patient(specimen['specimen_id']),
|
47
47
|
test_results: results,
|
48
48
|
specimen_status_trail: specimen_status_trail(specimen['specimen_id']),
|
@@ -162,7 +162,7 @@ module Lab
|
|
162
162
|
drawn_by_first_name, drawn_by_last_name = specimen['drawn_by_name']&.split
|
163
163
|
patient_first_name, patient_last_name = patient['name'].split
|
164
164
|
|
165
|
-
|
165
|
+
OrderDto.new(
|
166
166
|
_id: specimen['doc_id'].blank? ? SecureRandom.uuid : specimen['doc_id'],
|
167
167
|
_rev: '0',
|
168
168
|
tracking_number: specimen['tracking_number'],
|
@@ -197,8 +197,8 @@ module Lab
|
|
197
197
|
object[format_date(trail_entry['date'])] = {
|
198
198
|
status: trail_entry['status_name'],
|
199
199
|
updated_by: {
|
200
|
-
first_name
|
201
|
-
last_name
|
200
|
+
first_name:,
|
201
|
+
last_name:,
|
202
202
|
phone_number: trail_entry['updated_by_phone_number'],
|
203
203
|
id: trail_entry['updated_by_id']
|
204
204
|
}
|
@@ -230,7 +230,7 @@ module Lab
|
|
230
230
|
end
|
231
231
|
|
232
232
|
def format_test_result_for_dto(test_name, specimen, results, test_status_trail)
|
233
|
-
return {} if results.
|
233
|
+
return {} if results.empty?
|
234
234
|
|
235
235
|
result_create_event = test_status_trail[test_name]&.find do |trail_entry|
|
236
236
|
trail_entry['status_name'].casecmp?('drawn')
|