his_emr_api_lab 1.0.4 → 1.1.2
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/README.md +20 -1
- data/app/jobs/lab/update_patient_orders_job.rb +33 -0
- data/app/jobs/lab/void_order_job.rb +18 -0
- data/app/models/lab/lab_order.rb +4 -0
- data/app/serializers/lab/lab_order_serializer.rb +7 -1
- data/app/services/lab/lims/api/rest_api.rb +405 -0
- data/app/services/lab/lims/api/ws_api.rb +121 -0
- data/app/services/lab/lims/config.rb +45 -8
- data/app/services/lab/lims/migrator.rb +12 -9
- data/app/services/lab/lims/order_dto.rb +10 -3
- data/app/services/lab/lims/order_serializer.rb +32 -8
- data/app/services/lab/lims/pull_worker.rb +295 -0
- data/app/services/lab/lims/push_worker.rb +104 -0
- data/app/services/lab/lims/utils.rb +6 -1
- data/app/services/lab/lims/worker.rb +40 -317
- data/app/services/lab/metadata.rb +1 -0
- data/app/services/lab/orders_search_service.rb +20 -0
- data/app/services/lab/orders_service.rb +35 -9
- data/lib/lab/version.rb +1 -1
- data/lib/tasks/loaders/data/reasons-for-test.csv +1 -0
- data/lib/tasks/loaders/data/tests.csv +0 -2
- metadata +22 -3
- data/app/services/lab/lims/failed_imports.rb +0 -34
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lab
|
4
|
+
module Lims
|
5
|
+
class PushWorker
|
6
|
+
attr_reader :lims_api
|
7
|
+
|
8
|
+
include Utils # for logger
|
9
|
+
|
10
|
+
SECONDS_TO_WAIT_FOR_ORDERS = 30
|
11
|
+
|
12
|
+
def initialize(lims_api)
|
13
|
+
@lims_api = lims_api
|
14
|
+
end
|
15
|
+
|
16
|
+
def push_orders(batch_size: 1000, wait: false)
|
17
|
+
loop do
|
18
|
+
logger.info('Looking for new orders to push to LIMS...')
|
19
|
+
orders = orders_pending_sync(batch_size).all
|
20
|
+
orders.each { |order| push_order(order) }
|
21
|
+
|
22
|
+
# Doing this after .each above to stop ActiveRecord from executing
|
23
|
+
# an extra request to the database (ActiveRecord's lazy evaluation
|
24
|
+
# sometimes leads to unnecessary database hits for checking counts).
|
25
|
+
if orders.empty? && !wait
|
26
|
+
logger.info('Finished processing orders; exiting...')
|
27
|
+
break
|
28
|
+
end
|
29
|
+
|
30
|
+
sleep(Lab::Lims::Config.updates_poll_frequency)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def push_order_by_id(order_id)
|
35
|
+
order = Lab::LabOrder.unscoped.find(order_id)
|
36
|
+
push_order(order)
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Pushes given order to LIMS queue
|
41
|
+
def push_order(order)
|
42
|
+
logger.info("Pushing order ##{order.order_id}")
|
43
|
+
|
44
|
+
order_dto = Lab::Lims::OrderSerializer.serialize_order(order)
|
45
|
+
mapping = Lab::LimsOrderMapping.find_by(order_id: order.order_id)
|
46
|
+
|
47
|
+
ActiveRecord::Base.transaction do
|
48
|
+
if mapping && !order.voided.zero?
|
49
|
+
Rails.logger.info("Deleting order ##{order_dto['accession_number']} from LIMS")
|
50
|
+
lims_api.delete_order(mapping.lims_id, order_dto)
|
51
|
+
mapping.destroy
|
52
|
+
elsif mapping
|
53
|
+
Rails.logger.info("Updating order ##{order_dto['accession_number']} in LIMS")
|
54
|
+
lims_api.update_order(mapping.lims_id, order_dto)
|
55
|
+
mapping.update(pushed_at: Time.now)
|
56
|
+
else
|
57
|
+
Rails.logger.info("Creating order ##{order_dto['accession_number']} in LIMS")
|
58
|
+
update = lims_api.create_order(order_dto)
|
59
|
+
Lab::LimsOrderMapping.create!(order: order, lims_id: update['id'], revision: update['rev'],
|
60
|
+
pushed_at: Time.now)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
order_dto
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def orders_pending_sync(batch_size)
|
70
|
+
return new_orders.limit(batch_size) if new_orders.exists?
|
71
|
+
|
72
|
+
return voided_orders.limit(batch_size) if voided_orders.exists?
|
73
|
+
|
74
|
+
updated_orders.limit(batch_size)
|
75
|
+
end
|
76
|
+
|
77
|
+
def new_orders
|
78
|
+
Rails.logger.debug('Looking for new orders that need to be created in LIMS...')
|
79
|
+
Lab::LabOrder.where.not(order_id: Lab::LimsOrderMapping.all.select(:order_id))
|
80
|
+
end
|
81
|
+
|
82
|
+
def updated_orders
|
83
|
+
Rails.logger.debug('Looking for recently updated orders that need to be pushed to LIMS...')
|
84
|
+
last_updated = Lab::LimsOrderMapping.select('MAX(updated_at) AS last_updated')
|
85
|
+
.first
|
86
|
+
.last_updated
|
87
|
+
|
88
|
+
Lab::LabOrder.left_joins(:results)
|
89
|
+
.where('orders.discontinued_date > :last_updated
|
90
|
+
OR obs.date_created > :last_updated',
|
91
|
+
last_updated: last_updated)
|
92
|
+
.group('orders.order_id')
|
93
|
+
end
|
94
|
+
|
95
|
+
def voided_orders
|
96
|
+
Rails.logger.debug('Looking for voided orders that are being tracked by LIMS...')
|
97
|
+
Lab::LabOrder.unscoped
|
98
|
+
.where(order_type: OrderType.where(name: Lab::Metadata::ORDER_TYPE_NAME),
|
99
|
+
order_id: Lab::LimsOrderMapping.all.select(:order_id),
|
100
|
+
voided: 1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -7,6 +7,9 @@ module Lab
|
|
7
7
|
##
|
8
8
|
# Various helper methods for modules in the Lims namespaces...
|
9
9
|
module Utils
|
10
|
+
LIMS_LOG_PATH = Rails.root.join('log', 'lims')
|
11
|
+
FileUtils.mkdir_p(LIMS_LOG_PATH) unless File.exist?(LIMS_LOG_PATH)
|
12
|
+
|
10
13
|
def logger
|
11
14
|
Rails.logger
|
12
15
|
end
|
@@ -54,7 +57,9 @@ module Lab
|
|
54
57
|
def self.parse_date(str_date, fallback_date = nil)
|
55
58
|
str_date = str_date&.to_s
|
56
59
|
|
57
|
-
|
60
|
+
if str_date.blank? && fallback_date.blank?
|
61
|
+
raise "Can't parse blank date"
|
62
|
+
end
|
58
63
|
|
59
64
|
return parse_date(fallback_date) if str_date.blank?
|
60
65
|
|
@@ -1,352 +1,75 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
require_relative './api/couchdb_api'
|
6
|
-
require_relative './exceptions'
|
7
|
-
require_relative './order_serializer'
|
8
|
-
require_relative './utils'
|
3
|
+
require 'logger_multiplexor'
|
9
4
|
|
10
5
|
module Lab
|
11
6
|
module Lims
|
12
|
-
LIMS_LOG_PATH = Rails.root.join('log/lims')
|
13
|
-
Dir.mkdir(LIMS_LOG_PATH) unless File.exist?(LIMS_LOG_PATH)
|
14
|
-
|
15
7
|
##
|
16
8
|
# Pull/Push orders from/to the LIMS queue (Oops meant CouchDB).
|
17
|
-
|
18
|
-
include Utils
|
19
|
-
|
20
|
-
attr_reader :lims_api
|
21
|
-
|
9
|
+
module Worker
|
22
10
|
def self.start
|
23
|
-
|
24
|
-
fout.flock(File::LOCK_EX)
|
25
|
-
|
26
|
-
User.current = Utils.lab_user
|
27
|
-
|
28
|
-
fout.write("Worker ##{Process.pid} started at #{Time.now}")
|
29
|
-
worker = new(Api::CouchDbApi.new)
|
30
|
-
worker.pull_orders
|
31
|
-
# TODO: Verify that names being pushed to LIMS are of the correct format (ie matching
|
32
|
-
# LIMS naming conventions). Enable pushing when that is done
|
33
|
-
worker.push_orders
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def initialize(lims_api)
|
38
|
-
@lims_api = lims_api
|
39
|
-
end
|
40
|
-
|
41
|
-
def push_orders(batch_size: 100)
|
42
|
-
loop do
|
43
|
-
logger.info('Fetching new orders...')
|
44
|
-
orders = LabOrder.where.not(order_id: LimsOrderMapping.all.select(:order_id))
|
45
|
-
.limit(batch_size)
|
46
|
-
|
47
|
-
if orders.empty?
|
48
|
-
logger.info('No new orders available; exiting...')
|
49
|
-
break
|
50
|
-
end
|
11
|
+
User.current = Utils.lab_user
|
51
12
|
|
52
|
-
|
53
|
-
|
54
|
-
|
13
|
+
fork(&method(:start_push_worker))
|
14
|
+
fork(&method(:start_pull_worker))
|
15
|
+
fork(&method(:start_realtime_pull_worker)) if realtime_updates_enabled?
|
55
16
|
|
56
|
-
|
57
|
-
order = LabOrder.find(order_id)
|
58
|
-
push_order(order)
|
17
|
+
Process.waitall
|
59
18
|
end
|
60
19
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
20
|
+
def self.start_push_worker
|
21
|
+
start_worker('push_worker') do
|
22
|
+
api = Lims::Api::RestApi.new(Lab::Lims::Config.rest_api)
|
23
|
+
worker = PushWorker.new(api)
|
65
24
|
|
66
|
-
|
67
|
-
mapping = LimsOrderMapping.find_by(order_id: order.order_id)
|
68
|
-
|
69
|
-
ActiveRecord::Base.transaction do
|
70
|
-
if mapping
|
71
|
-
lims_api.update_order(mapping.lims_id, order_dto)
|
72
|
-
mapping.update(pushed_at: Time.now)
|
73
|
-
else
|
74
|
-
update = lims_api.create_order(order_dto)
|
75
|
-
LimsOrderMapping.create!(order: order, lims_id: update['id'], revision: update['rev'], pushed_at: Time.now)
|
76
|
-
end
|
25
|
+
worker.push_orders # (wait: true)
|
77
26
|
end
|
78
|
-
|
79
|
-
order_dto
|
80
|
-
end
|
81
|
-
|
82
|
-
##
|
83
|
-
# Pulls orders from the LIMS queue and writes them to the local database
|
84
|
-
def pull_orders(batch_size: 10_000)
|
85
|
-
logger.info("Retrieving LIMS orders starting from #{last_seq}")
|
86
|
-
|
87
|
-
lims_api.consume_orders(from: last_seq, limit: batch_size) do |order_dto, context|
|
88
|
-
logger.debug("Retrieved order ##{order_dto[:tracking_number]}: #{order_dto}")
|
89
|
-
|
90
|
-
patient = find_patient_by_nhid(order_dto[:patient][:id])
|
91
|
-
unless patient
|
92
|
-
logger.debug("Discarding order: Non local patient ##{order_dto[:patient][:id]} on order ##{order_dto[:tracking_number]}")
|
93
|
-
order_rejected(order_dto, "Patient NPID, '#{order_dto[:patient][:id]}', didn't match any local NPIDs")
|
94
|
-
next
|
95
|
-
end
|
96
|
-
|
97
|
-
if order_dto[:tests].empty?
|
98
|
-
logger.debug("Discarding order: Missing tests on order ##{order_dto[:tracking_number]}")
|
99
|
-
order_rejected(order_dto, 'Order is missing tests')
|
100
|
-
next
|
101
|
-
end
|
102
|
-
|
103
|
-
diff = match_patient_demographics(patient, order_dto['patient'])
|
104
|
-
if diff.empty?
|
105
|
-
save_order(patient, order_dto)
|
106
|
-
order_saved(order_dto)
|
107
|
-
else
|
108
|
-
save_failed_import(order_dto, 'Demographics not matching', diff)
|
109
|
-
end
|
110
|
-
|
111
|
-
update_last_seq(context.current_seq)
|
112
|
-
rescue DuplicateNHID
|
113
|
-
logger.warn("Failed to import order due to duplicate patient NHID: #{order_dto[:patient][:id]}")
|
114
|
-
save_failed_import(order_dto, "Duplicate local patient NHID: #{order_dto[:patient][:id]}")
|
115
|
-
rescue MissingAccessionNumber
|
116
|
-
logger.warn("Failed to import order due to missing accession number: #{order_dto[:_id]}")
|
117
|
-
save_failed_import(order_dto, 'Order missing tracking number')
|
118
|
-
rescue LimsException => e
|
119
|
-
logger.warn("Failed to import order due to #{e.class} - #{e.message}")
|
120
|
-
save_failed_import(order_dto, e.message)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
protected
|
125
|
-
|
126
|
-
def last_seq
|
127
|
-
File.open(last_seq_path, File::RDONLY | File::CREAT, 0o644) do |fin|
|
128
|
-
data = fin.read&.strip
|
129
|
-
return nil if data.blank?
|
130
|
-
|
131
|
-
return data
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def update_last_seq(last_seq)
|
136
|
-
File.open(last_seq_path, File::WRONLY | File::CREAT, 0o644) do |fout|
|
137
|
-
fout.flock(File::LOCK_EX)
|
138
|
-
|
139
|
-
fout.write(last_seq.to_s)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def order_saved(order_dto); end
|
144
|
-
|
145
|
-
def order_rejected(order_dto, message); end
|
146
|
-
|
147
|
-
private
|
148
|
-
|
149
|
-
def find_patient_by_nhid(nhid)
|
150
|
-
national_id_type = PatientIdentifierType.where(name: ['National id', 'Old Identification Number'])
|
151
|
-
identifiers = PatientIdentifier.where(type: national_id_type, identifier: nhid)
|
152
|
-
.joins('INNER JOIN person ON person.person_id = patient_identifier.patient_id AND person.voided = 0')
|
153
|
-
if identifiers.count.zero?
|
154
|
-
identifiers = PatientIdentifier.unscoped
|
155
|
-
.where(voided: 1, type: national_id_type, identifier: nhid)
|
156
|
-
.joins('INNER JOIN person ON person.person_id = patient_identifier.patient_id AND person.voided = 0')
|
157
|
-
end
|
158
|
-
|
159
|
-
# Joining to person above to ensure that the person is not voided,
|
160
|
-
# it was noted at one site that there were some people that were voided
|
161
|
-
# upon merging but the patient and patient_identifier was not voided
|
162
|
-
|
163
|
-
return nil if identifiers.count.zero?
|
164
|
-
|
165
|
-
patients = Patient.where(patient_id: identifiers.select(:patient_id))
|
166
|
-
.distinct(:patient_id)
|
167
|
-
.all
|
168
|
-
|
169
|
-
raise DuplicateNHID, "Duplicate National Health ID: #{nhid}" if patients.size > 1
|
170
|
-
|
171
|
-
patients.first
|
172
27
|
end
|
173
28
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
person = Person.find(local_patient.id)
|
179
|
-
person_name = PersonName.find_by_person_id(local_patient.id)
|
29
|
+
def self.start_pull_worker
|
30
|
+
start_worker('pull_worker') do
|
31
|
+
api = Lims::Api::RestApi.new(Lab::Lims::Config.rest_api)
|
32
|
+
worker = PullWorker.new(api)
|
180
33
|
|
181
|
-
|
182
|
-
|| person.gender&.first&.casecmp?(lims_patient['gender']&.first)
|
183
|
-
diff[:gender] = { local: person.gender, lims: lims_patient['gender'] }
|
184
|
-
end
|
185
|
-
|
186
|
-
unless names_match?(person_name&.given_name, lims_patient['first_name'])
|
187
|
-
diff[:given_name] = { local: person_name&.given_name, lims: lims_patient['first_name'] }
|
188
|
-
end
|
189
|
-
|
190
|
-
unless names_match?(person_name&.family_name, lims_patient['last_name'])
|
191
|
-
diff[:family_name] = { local: person_name&.family_name, lims: lims_patient['last_name'] }
|
34
|
+
worker.pull_orders
|
192
35
|
end
|
193
|
-
|
194
|
-
diff
|
195
36
|
end
|
196
37
|
|
197
|
-
def
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
return true if name1.blank? && name2.blank?
|
38
|
+
def self.start_realtime_pull_worker
|
39
|
+
start_worker('realtime_pull_worker') do
|
40
|
+
api = Lims::Api::WsApi.new(Lab::Lims::Config.updates_socket)
|
41
|
+
worker = PullWorker.new(api)
|
202
42
|
|
203
|
-
|
204
|
-
|
205
|
-
name1.casecmp?(name2)
|
206
|
-
end
|
207
|
-
|
208
|
-
def save_order(patient, order_dto)
|
209
|
-
raise MissingAccessionNumber if order_dto[:tracking_number].blank?
|
210
|
-
|
211
|
-
logger.info("Importing LIMS order ##{order_dto[:tracking_number]}")
|
212
|
-
mapping = find_order_mapping_by_lims_id(order_dto[:_id])
|
213
|
-
|
214
|
-
ActiveRecord::Base.transaction do
|
215
|
-
if mapping
|
216
|
-
order = update_order(patient, mapping.order_id, order_dto)
|
217
|
-
mapping.update(pulled_at: Time.now)
|
218
|
-
else
|
219
|
-
order = create_order(patient, order_dto)
|
220
|
-
mapping = LimsOrderMapping.create(lims_id: order_dto[:_id],
|
221
|
-
order_id: order['id'],
|
222
|
-
pulled_at: Time.now,
|
223
|
-
revision: order_dto['_rev'])
|
224
|
-
end
|
225
|
-
|
226
|
-
order
|
43
|
+
worker.pull_orders
|
227
44
|
end
|
228
45
|
end
|
229
46
|
|
230
|
-
def
|
231
|
-
logger.
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
order
|
236
|
-
end
|
237
|
-
|
238
|
-
def update_order(patient, order_id, order_dto)
|
239
|
-
logger.debug("Updating order ##{order_dto['_id']}")
|
240
|
-
order = OrdersService.update_order(order_id, order_dto.to_order_service_params(patient_id: patient.patient_id)
|
241
|
-
.merge(force_update: true))
|
242
|
-
update_results(order, order_dto['test_results']) unless order_dto['test_results'].empty?
|
243
|
-
|
244
|
-
order
|
245
|
-
end
|
246
|
-
|
247
|
-
def update_results(order, lims_results)
|
248
|
-
logger.debug("Updating results for order ##{order[:accession_number]}: #{lims_results}")
|
249
|
-
|
250
|
-
lims_results.each do |test_name, test_results|
|
251
|
-
test = find_test(order['id'], test_name)
|
252
|
-
unless test
|
253
|
-
logger.warn("Couldn't find test, #{test_name}, in order ##{order[:id]}")
|
254
|
-
next
|
255
|
-
end
|
256
|
-
|
257
|
-
next unless test_results['results']
|
258
|
-
|
259
|
-
measures = test_results['results'].map do |indicator, value|
|
260
|
-
measure = find_measure(order, indicator, value)
|
261
|
-
next nil unless measure
|
47
|
+
def self.start_worker(worker_name)
|
48
|
+
Rails.logger = LoggerMultiplexor.new(log_path("#{worker_name}.log"), $stdout)
|
49
|
+
ActiveRecord::Base.logger = Rails.logger
|
50
|
+
Rails.logger.level = :debug
|
262
51
|
|
263
|
-
|
52
|
+
File.open(log_path("#{worker_name}.lock"), File::RDWR | File::CREAT, 0o644) do |fout|
|
53
|
+
unless fout.flock(File::LOCK_EX | File::LOCK_NB)
|
54
|
+
Rails.logger.warn("Another process already holds lock #{worker_name} (#{fout.read}), exiting...")
|
55
|
+
break
|
264
56
|
end
|
265
57
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
creator = format_result_entered_by(test_results['result_entered_by'])
|
270
|
-
|
271
|
-
ResultsService.create_results(test.id, provider_id: User.current.person_id,
|
272
|
-
date: Utils.parse_date(test_results['date_result_entered'], order[:order_date].to_s),
|
273
|
-
comments: "LIMS import: Entered by: #{creator}",
|
274
|
-
measures: measures)
|
58
|
+
fout.write("Locked by process ##{Process.pid} under process group ##{Process.ppid} at #{Time.now}")
|
59
|
+
fout.flush
|
60
|
+
yield
|
275
61
|
end
|
276
62
|
end
|
277
63
|
|
278
|
-
def
|
279
|
-
|
280
|
-
test_concept = Utils.find_concept_by_name(test_name)
|
281
|
-
raise "Unknown test name, #{test_name}!" unless test_concept
|
282
|
-
|
283
|
-
LabTest.find_by(order_id: order_id, value_coded: test_concept.concept_id)
|
284
|
-
end
|
285
|
-
|
286
|
-
def find_measure(_order, indicator_name, value)
|
287
|
-
indicator = Utils.find_concept_by_name(indicator_name)
|
288
|
-
unless indicator
|
289
|
-
logger.warn("Result indicator #{indicator_name} not found in concepts list")
|
290
|
-
return nil
|
291
|
-
end
|
292
|
-
|
293
|
-
value_modifier, value, value_type = parse_lims_result_value(value)
|
294
|
-
return nil if value.blank?
|
295
|
-
|
296
|
-
ActiveSupport::HashWithIndifferentAccess.new(
|
297
|
-
indicator: { concept_id: indicator.concept_id },
|
298
|
-
value_type: value_type,
|
299
|
-
value: value_type == 'numeric' ? value.to_f : value,
|
300
|
-
value_modifier: value_modifier.blank? ? '=' : value_modifier
|
301
|
-
)
|
302
|
-
end
|
303
|
-
|
304
|
-
def parse_lims_result_value(value)
|
305
|
-
value = value['result_value']&.strip
|
306
|
-
return nil, nil, nil if value.blank?
|
307
|
-
|
308
|
-
match = value&.match(/^(>|=|<|<=|>=)(.*)$/)
|
309
|
-
return nil, value, guess_result_datatype(value) unless match
|
310
|
-
|
311
|
-
[match[1], match[2], guess_result_datatype(match[2])]
|
64
|
+
def self.log_path(filename)
|
65
|
+
Lab::Lims::Utils::LIMS_LOG_PATH.join(filename)
|
312
66
|
end
|
313
67
|
|
314
|
-
def
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
def format_result_entered_by(result_entered_by)
|
321
|
-
first_name = result_entered_by['first_name']
|
322
|
-
last_name = result_entered_by['last_name']
|
323
|
-
phone_number = result_entered_by['phone_number']
|
324
|
-
id = result_entered_by['id'] # Looks like a user_id of some sort
|
325
|
-
|
326
|
-
"#{id}:#{first_name} #{last_name}:#{phone_number}"
|
327
|
-
end
|
328
|
-
|
329
|
-
def save_failed_import(order_dto, reason, diff = nil)
|
330
|
-
logger.info("Failed to import LIMS order ##{order_dto[:tracking_number]} due to '#{reason}'")
|
331
|
-
LimsFailedImport.create!(lims_id: order_dto[:_id],
|
332
|
-
tracking_number: order_dto[:tracking_number],
|
333
|
-
patient_nhid: order_dto[:patient][:id],
|
334
|
-
reason: reason,
|
335
|
-
diff: diff&.to_json)
|
336
|
-
end
|
337
|
-
|
338
|
-
def last_seq_path
|
339
|
-
LIMS_LOG_PATH.join('last_seq.dat')
|
340
|
-
end
|
341
|
-
|
342
|
-
def find_order_mapping_by_lims_id(lims_id)
|
343
|
-
mapping = Lab::LimsOrderMapping.find_by(lims_id: lims_id)
|
344
|
-
return nil unless mapping
|
345
|
-
|
346
|
-
return mapping if Lab::LabOrder.where(order_id: mapping.order_id).exists?
|
347
|
-
|
348
|
-
mapping.destroy
|
349
|
-
nil
|
68
|
+
def self.realtime_updates_enabled?
|
69
|
+
Lims::Config.updates_socket.key?('url')
|
70
|
+
rescue Lab::Lims::Config::ConfigNotFound => e
|
71
|
+
Rails.logger.warn("Check for realtime updates failed: #{e.message}")
|
72
|
+
false
|
350
73
|
end
|
351
74
|
end
|
352
75
|
end
|