his_emr_api_lab 1.2.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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')
|