his_emr_api_lab 2.4.7 → 2.4.8
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 +2 -2
- data/app/controllers/lab/tests_controller.rb +1 -1
- data/app/models/lab/lab_order.rb +12 -0
- data/app/services/lab/lims/exceptions.rb +2 -0
- data/app/services/lab/lims/pull_worker.rb +91 -26
- data/app/services/lab/lims/utils.rb +40 -14
- data/app/services/lab/orders_service.rb +21 -3
- data/app/services/lab/tests_service.rb +1 -1
- data/app/services/lab/user_service.rb +5 -0
- data/lib/lab/version.rb +1 -1
- metadata +29 -43
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9f5de1660061373145b1d5de0080384f472c305659f23e599901cb72267134c9
|
|
4
|
+
data.tar.gz: a2689968ec069c8759d8c14a36ab767e124d8c042e43e7ecf3d10a20e6b01f1b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a172df300261d1828cda8d4942873ff3b5ce2d5607e854323ec9f5f9d18d73299e5c0e75488110f2a977b421d15f374342f141ec1833987f6c5de9222539084
|
|
7
|
+
data.tar.gz: 209dceff50ab86215a5c56b168568fbfb9c3d00d7b0ff0f035c25822d0b3ce84387d56448f5c084f7b2078b9a8a10ebb4efce649fee55a7e5fe5e94b862def60
|
|
@@ -22,8 +22,8 @@ module Lab
|
|
|
22
22
|
|
|
23
23
|
def update
|
|
24
24
|
specimen = params.require(:specimen).slice(:concept_id)
|
|
25
|
-
order = OrdersService.update_order(params[:id], specimen:, force_update: params[:force_update])
|
|
26
|
-
|
|
25
|
+
order = OrdersService.update_order(params[:id], specimen:, force_update: params[:force_update], date: params[:date])
|
|
26
|
+
|
|
27
27
|
begin
|
|
28
28
|
Lab::PushOrderJob.perform_later(order.fetch(:order_id))
|
|
29
29
|
rescue StandardError => e
|
|
@@ -10,7 +10,7 @@ module Lab
|
|
|
10
10
|
|
|
11
11
|
# Add a specimen to an existing order
|
|
12
12
|
def create
|
|
13
|
-
test_params = params.
|
|
13
|
+
test_params = params.permit(:order_id, :date, tests: %i[concept_id concept])
|
|
14
14
|
order_id, test_concepts = test_params.require(%i[order_id tests])
|
|
15
15
|
date = test_params[:date] || Date.today
|
|
16
16
|
|
data/app/models/lab/lab_order.rb
CHANGED
|
@@ -66,6 +66,10 @@ module Lab
|
|
|
66
66
|
.where.not(concept_id: ConceptName.where(name: 'Tests ordered').select(:concept_id))
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
# Only checked when start_date is set or changed, so existing future-dated
|
|
70
|
+
# orders can still be voided or updated during clean-up.
|
|
71
|
+
validate :start_date_cannot_be_in_the_future, if: :will_save_change_to_start_date?
|
|
72
|
+
|
|
69
73
|
scope :drawn, -> { where.not(concept_id: ConceptName.where(name: 'Unknown').select(:concept_id)) }
|
|
70
74
|
scope :not_drawn, -> { where(concept_id: ConceptName.where(name: 'Unknown').select(:concept_id)) }
|
|
71
75
|
|
|
@@ -78,5 +82,13 @@ module Lab
|
|
|
78
82
|
:comment_to_fulfiller,
|
|
79
83
|
:tests)
|
|
80
84
|
end
|
|
85
|
+
|
|
86
|
+
# Allows up to tomorrow to cover timezone differences, matching
|
|
87
|
+
# Lab::Lims::Utils.parse_date.
|
|
88
|
+
def start_date_cannot_be_in_the_future
|
|
89
|
+
return if start_date.blank? || start_date.to_date <= Date.current + 1.day
|
|
90
|
+
|
|
91
|
+
errors.add(:start_date, 'cannot be in the future')
|
|
92
|
+
end
|
|
81
93
|
end
|
|
82
94
|
end
|
|
@@ -9,6 +9,7 @@ module Lab
|
|
|
9
9
|
class UnknownSpecimenType < LimsException; end
|
|
10
10
|
class UnknownTestType < LimsException; end
|
|
11
11
|
class ValidationUnavailable < LimsException; end
|
|
12
|
+
class InvalidDate < LimsException; end
|
|
12
13
|
end
|
|
13
14
|
end
|
|
14
15
|
end
|
|
@@ -21,5 +22,6 @@ module Lab
|
|
|
21
22
|
class UnknownSpecimenType < LimsException; end
|
|
22
23
|
class UnknownTestType < LimsException; end
|
|
23
24
|
class ValidationUnavailable < LimsException; end
|
|
25
|
+
class InvalidDate < LimsException; end
|
|
24
26
|
end
|
|
25
27
|
end
|
|
@@ -12,6 +12,8 @@ module Lab
|
|
|
12
12
|
include Utils # for logger
|
|
13
13
|
|
|
14
14
|
LIMS_LOG_PATH = Rails.root.join('log', 'lims')
|
|
15
|
+
UNMAPPED_ORDER_REASON = 'Order not mapped to LIMS: pull worker does not create orders'
|
|
16
|
+
DECEASED_PATIENT_REASON = "Order dated after patient's death"
|
|
15
17
|
|
|
16
18
|
def initialize(lims_api, start_date: nil, accession_numbers: [], patient_id: nil)
|
|
17
19
|
@lims_api = lims_api
|
|
@@ -171,47 +173,84 @@ module Lab
|
|
|
171
173
|
name1.casecmp?(name2)
|
|
172
174
|
end
|
|
173
175
|
|
|
176
|
+
##
|
|
177
|
+
# Applies a LIMS order to the local order it is mapped to.
|
|
178
|
+
#
|
|
179
|
+
# Orders are only ever created in the EMR, never by the pull worker.
|
|
180
|
+
# find_patient_by_nhid only lets an order through when a local order with
|
|
181
|
+
# the same accession number already exists, so creating one here would
|
|
182
|
+
# always produce a duplicate. Orders without a LIMS mapping (e.g. legacy
|
|
183
|
+
# orders, or new orders the push worker has not sent yet) are skipped and
|
|
184
|
+
# recorded once in lab_lims_failed_imports for review. So are orders
|
|
185
|
+
# dated after the patient's death.
|
|
186
|
+
#
|
|
187
|
+
# Returns the updated order, or nil if the order was skipped.
|
|
174
188
|
def save_order(patient, order_dto)
|
|
175
189
|
raise MissingAccessionNumber if order_dto[:tracking_number].blank?
|
|
176
190
|
|
|
177
191
|
logger.info("Importing LIMS order ##{order_dto[:tracking_number]}")
|
|
192
|
+
|
|
193
|
+
death_date = death_date_before_order(patient, order_dto)
|
|
194
|
+
if death_date
|
|
195
|
+
order_date = lims_order_date(order_dto)
|
|
196
|
+
logger.warn("Not importing order ##{order_dto[:tracking_number]}: dated #{order_date}, after patient's death on #{death_date}")
|
|
197
|
+
record_skipped_order(order_dto, DECEASED_PATIENT_REASON, { order_date:, death_date: })
|
|
198
|
+
return nil
|
|
199
|
+
end
|
|
200
|
+
|
|
178
201
|
mapping = find_order_mapping_by_lims_id(order_dto[:_id])
|
|
179
202
|
|
|
203
|
+
unless mapping
|
|
204
|
+
logger.warn("Not creating order ##{order_dto[:tracking_number]} from LIMS: no LIMS mapping for local order")
|
|
205
|
+
record_skipped_order(order_dto, UNMAPPED_ORDER_REASON)
|
|
206
|
+
return nil
|
|
207
|
+
end
|
|
208
|
+
|
|
180
209
|
ActiveRecord::Base.transaction do
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
mapping.update(pulled_at: Time.now)
|
|
184
|
-
else
|
|
185
|
-
order = create_order(patient, order_dto)
|
|
186
|
-
mapping = LimsOrderMapping.create(lims_id: order_dto[:_id],
|
|
187
|
-
order_id: order['id'],
|
|
188
|
-
pulled_at: Time.now,
|
|
189
|
-
revision: order_dto['_rev'])
|
|
190
|
-
end
|
|
210
|
+
order = update_order(patient, mapping.order_id, order_dto)
|
|
211
|
+
mapping.update(pulled_at: Time.now)
|
|
191
212
|
|
|
192
213
|
order
|
|
193
214
|
end
|
|
194
215
|
end
|
|
195
216
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
217
|
+
##
|
|
218
|
+
# Returns the patient's death date if the order is dated after it, else nil.
|
|
219
|
+
#
|
|
220
|
+
# Orders dated on or before the death date are still imported, so results
|
|
221
|
+
# for samples drawn before death keep arriving.
|
|
222
|
+
def death_date_before_order(patient, order_dto)
|
|
223
|
+
person = Person.unscoped.find_by(person_id: patient.patient_id)
|
|
224
|
+
return nil unless person && ActiveModel::Type::Boolean.new.cast(person.dead) && person.death_date
|
|
225
|
+
|
|
226
|
+
death_date = person.death_date.to_date
|
|
227
|
+
death_date if lims_order_date(order_dto) > death_date
|
|
228
|
+
end
|
|
201
229
|
|
|
202
|
-
|
|
203
|
-
|
|
230
|
+
def lims_order_date(order_dto)
|
|
231
|
+
raise LimsException, 'Order missing created date' if order_dto[:date_created].blank?
|
|
204
232
|
|
|
205
|
-
|
|
206
|
-
|
|
233
|
+
Utils.parse_date(order_dto[:date_created]).to_date
|
|
234
|
+
end
|
|
207
235
|
|
|
208
|
-
|
|
236
|
+
# The REST pull re-selects skipped orders on every run, so each one is
|
|
237
|
+
# recorded only once instead of adding a row per run.
|
|
238
|
+
def record_skipped_order(order_dto, reason, diff = nil)
|
|
239
|
+
LimsFailedImport.find_or_create_by!(lims_id: order_dto[:_id],
|
|
240
|
+
tracking_number: order_dto[:tracking_number],
|
|
241
|
+
reason:) do |failed_import|
|
|
242
|
+
failed_import.patient_nhid = order_dto.dig(:patient, :id)
|
|
243
|
+
failed_import.diff = diff&.to_json
|
|
244
|
+
end
|
|
245
|
+
rescue StandardError => e
|
|
246
|
+
logger.error("Failed to record skipped order ##{order_dto[:tracking_number]}: #{e.message}")
|
|
209
247
|
end
|
|
210
248
|
|
|
211
249
|
def update_order(patient, order_id, order_dto)
|
|
212
250
|
logger.debug("Updating order ##{order_dto['_id']}")
|
|
213
251
|
params = order_dto.to_order_service_params(patient_id: patient.patient_id)
|
|
214
252
|
params[:location_id] ||= Lab::OrderLocationResolver.location_id_for_order_id(order_id, facility_name: order_dto[:sending_facility])
|
|
253
|
+
keep_local_specimen(order_id, params) unless specimen_update_allowed?(order_id)
|
|
215
254
|
order = OrdersService.update_order(order_id, params.merge(force_update: 'true'))
|
|
216
255
|
|
|
217
256
|
# Extract and save status trails from NLIMS
|
|
@@ -223,6 +262,38 @@ module Lab
|
|
|
223
262
|
order
|
|
224
263
|
end
|
|
225
264
|
|
|
265
|
+
##
|
|
266
|
+
# LIMS may only set the specimen of an order whose sample has not been
|
|
267
|
+
# drawn yet (specimen 'Unknown') and that has no results. Any other order
|
|
268
|
+
# keeps its local specimen, so a sync can never change or discontinue an
|
|
269
|
+
# order that has already been drawn or resulted.
|
|
270
|
+
def specimen_update_allowed?(order_id)
|
|
271
|
+
order = Lab::LabOrder.unscoped.find(order_id)
|
|
272
|
+
|
|
273
|
+
order.concept_id == unknown_specimen_concept_id && !order_has_results?(order_id)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def keep_local_specimen(order_id, params)
|
|
277
|
+
local_specimen_id = Lab::LabOrder.unscoped.find(order_id).concept_id
|
|
278
|
+
lims_specimen_id = params.dig(:specimen, :concept_id)
|
|
279
|
+
|
|
280
|
+
if lims_specimen_id.present? && lims_specimen_id.to_i != local_specimen_id
|
|
281
|
+
logger.info("Keeping local specimen ##{local_specimen_id} on order ##{order_id}, ignoring LIMS specimen ##{lims_specimen_id}")
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
params[:specimen] = { concept_id: local_specimen_id }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def unknown_specimen_concept_id
|
|
288
|
+
@unknown_specimen_concept_id ||= ConceptName.find_by(name: Lab::Metadata::UNKNOWN_SPECIMEN)&.concept_id
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def order_has_results?(order_id)
|
|
292
|
+
result_concept = ConceptName.where(name: Lab::Metadata::TEST_RESULT_CONCEPT_NAME).select(:concept_id)
|
|
293
|
+
|
|
294
|
+
Observation.unscoped.where(order_id:, concept_id: result_concept, voided: 0).exists?
|
|
295
|
+
end
|
|
296
|
+
|
|
226
297
|
def update_results(order, lims_results)
|
|
227
298
|
logger.debug("Updating results for order ##{order[:accession_number]}: #{lims_results}")
|
|
228
299
|
|
|
@@ -266,12 +337,6 @@ module Lab
|
|
|
266
337
|
LabTest.unscoped.find_by(order_id:, value_coded: test_concept.concept_id, voided: 0)
|
|
267
338
|
end
|
|
268
339
|
|
|
269
|
-
def location_id_for_order_dto(order_dto)
|
|
270
|
-
local_order = Lab::LabOrder.unscoped.find_by(accession_number: order_dto[:tracking_number])
|
|
271
|
-
|
|
272
|
-
Lab::OrderLocationResolver.location_id_for_order(local_order, facility_name: order_dto[:sending_facility])
|
|
273
|
-
end
|
|
274
|
-
|
|
275
340
|
def find_measure(_order, indicator_name, value)
|
|
276
341
|
indicator = Utils.find_concept_by_name(indicator_name)
|
|
277
342
|
unless indicator
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'cgi/util'
|
|
4
4
|
|
|
5
|
+
require_relative 'exceptions'
|
|
6
|
+
|
|
5
7
|
module Lab
|
|
6
8
|
module Lims
|
|
7
9
|
##
|
|
@@ -54,6 +56,16 @@ module Lab
|
|
|
54
56
|
User.create!(username: 'lab_daemon', person:, creator: god_user.user_id)
|
|
55
57
|
end
|
|
56
58
|
|
|
59
|
+
# Earliest date accepted from LIMS. Anything older is a corrupted
|
|
60
|
+
# legacy date (e.g. year 0026 or 18xx), not a real lab order.
|
|
61
|
+
EARLIEST_VALID_DATE = Date.new(2000, 1, 1)
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Parses a LIMS date, accepting only real calendar dates with a
|
|
65
|
+
# four-digit year between EARLIEST_VALID_DATE and tomorrow (to allow for
|
|
66
|
+
# timezone differences). Invalid dates are never guessed at or rewritten:
|
|
67
|
+
# the fallback date is used if one is given, otherwise InvalidDate is
|
|
68
|
+
# raised.
|
|
57
69
|
def self.parse_date(str_date, fallback_date = nil)
|
|
58
70
|
str_date = str_date&.to_s
|
|
59
71
|
|
|
@@ -61,21 +73,35 @@ module Lab
|
|
|
61
73
|
|
|
62
74
|
return parse_date(fallback_date) if str_date.blank?
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
parse_date(fallback_date)
|
|
76
|
+
date = begin
|
|
77
|
+
case str_date
|
|
78
|
+
when /\d{4}-\d{2}-\d{2}/
|
|
79
|
+
str_date
|
|
80
|
+
when /\d{2}-\d{2}-\d{4}/
|
|
81
|
+
Date.strptime(str_date, '%d-%m-%Y').strftime('%Y-%m-%d')
|
|
82
|
+
when /(\d{4}\d{2}\d{2})\d+/
|
|
83
|
+
Date.strptime(str_date, '%Y%m%d').strftime('%Y-%m-%d')
|
|
84
|
+
when %r{\d{2}/\d{2}/\d{4}}
|
|
85
|
+
str_date.to_date.to_s
|
|
86
|
+
end
|
|
87
|
+
rescue Date::Error, ArgumentError
|
|
88
|
+
nil
|
|
78
89
|
end
|
|
90
|
+
|
|
91
|
+
return date if valid_date?(date)
|
|
92
|
+
|
|
93
|
+
Rails.logger.warn("Invalid date: #{str_date}")
|
|
94
|
+
raise InvalidDate, "Invalid date: #{str_date}" if fallback_date.blank?
|
|
95
|
+
|
|
96
|
+
parse_date(fallback_date)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def self.valid_date?(date)
|
|
100
|
+
return false if date.blank?
|
|
101
|
+
|
|
102
|
+
date.to_date.between?(EARLIEST_VALID_DATE, Date.current + 1.day)
|
|
103
|
+
rescue Date::Error, ArgumentError
|
|
104
|
+
false
|
|
79
105
|
end
|
|
80
106
|
|
|
81
107
|
def self.find_concept_by_name(name)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'order_location_resolver'
|
|
4
|
+
require_relative 'lims/exceptions'
|
|
4
5
|
|
|
5
6
|
module Lab
|
|
6
7
|
##
|
|
@@ -248,7 +249,7 @@ module Lab
|
|
|
248
249
|
orders = Lab::LabOrder.where(order_id: tests.pluck(:order_id))
|
|
249
250
|
data = {
|
|
250
251
|
count: orders.count,
|
|
251
|
-
last_order_date:
|
|
252
|
+
last_order_date: last_order_date(location_id),
|
|
252
253
|
lab_orders: []
|
|
253
254
|
}
|
|
254
255
|
if (include_data.present? && include_data == 'true')
|
|
@@ -265,6 +266,19 @@ module Lab
|
|
|
265
266
|
|
|
266
267
|
private
|
|
267
268
|
|
|
269
|
+
# Without a location this is the latest lab order overall (unchanged behaviour). With a location
|
|
270
|
+
# it is the latest lab order whose tests were drawn there, so a central EMR serving many sites
|
|
271
|
+
# reports each site's own last order instead of the latest order across all sites.
|
|
272
|
+
def last_order_date(location_id)
|
|
273
|
+
return Lab::LabOrder.last&.start_date&.to_date if location_id.blank?
|
|
274
|
+
|
|
275
|
+
order_ids = Lab::LabTest.unscoped
|
|
276
|
+
.where(voided: false, location_id:,
|
|
277
|
+
concept: ConceptName.where(name: Lab::Metadata::TEST_TYPE_CONCEPT_NAME))
|
|
278
|
+
.select(:order_id)
|
|
279
|
+
Lab::LabOrder.where(order_id: order_ids).maximum(:start_date)&.to_date
|
|
280
|
+
end
|
|
281
|
+
|
|
268
282
|
def create_rejection_notification(order_params)
|
|
269
283
|
order = find_order order_params['tracking_number']
|
|
270
284
|
data = { type: 'LIMS',
|
|
@@ -372,11 +386,15 @@ module Lab
|
|
|
372
386
|
end
|
|
373
387
|
|
|
374
388
|
def accession_number_exists?(accession_number)
|
|
375
|
-
Lab::LabOrder.where(accession_number:).exists?
|
|
389
|
+
Lab::LabOrder.unscoped.where(accession_number:, voided: 0).exists?
|
|
376
390
|
end
|
|
377
391
|
|
|
378
392
|
def nlims_accession_number_exists?(accession_number)
|
|
379
|
-
config
|
|
393
|
+
# No config file means NLIMS is not configured, same as no lims_api entry.
|
|
394
|
+
config_path = Rails.root.join('config', 'application.yml')
|
|
395
|
+
return false unless File.exist?(config_path)
|
|
396
|
+
|
|
397
|
+
config = YAML.load_file(config_path)
|
|
380
398
|
return false unless config['lims_api']
|
|
381
399
|
|
|
382
400
|
# fetch from the rest api and check if it exists
|
|
@@ -15,7 +15,7 @@ module Lab
|
|
|
15
15
|
Lab::UpdatePatientOrdersJob.perform_later(patient_id) if patient_id
|
|
16
16
|
|
|
17
17
|
tests = filter_tests(tests, test_type_id: filters.delete(:test_type_id),
|
|
18
|
-
patient_id
|
|
18
|
+
patient_id:,
|
|
19
19
|
patient: filters.delete(:patient))
|
|
20
20
|
|
|
21
21
|
tests = filter_tests_by_results(tests) if %w[1 true].include?(filters[:pending_results]&.downcase)
|
|
@@ -17,6 +17,8 @@ module Lab
|
|
|
17
17
|
def authenticate_user(username:, password:, user_agent:, request_ip:)
|
|
18
18
|
# Use unscoped for authentication - should not be location-dependent
|
|
19
19
|
user = User.unscoped.find_by_username username
|
|
20
|
+
return nil if user.nil?
|
|
21
|
+
|
|
20
22
|
encrypted_pass = Password.new(user.password)
|
|
21
23
|
if encrypted_pass == password
|
|
22
24
|
generate_token(user, user_agent, request_ip)
|
|
@@ -24,6 +26,9 @@ module Lab
|
|
|
24
26
|
# throw authentication error
|
|
25
27
|
nil
|
|
26
28
|
end
|
|
29
|
+
rescue BCrypt::Errors::InvalidHash
|
|
30
|
+
# Regular EMR users have SHA passwords; only users created through the LIMS user endpoint can log in here
|
|
31
|
+
nil
|
|
27
32
|
end
|
|
28
33
|
|
|
29
34
|
private
|
data/lib/lab/version.rb
CHANGED
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: 2.4.
|
|
4
|
+
version: 2.4.8
|
|
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: 2026-09
|
|
11
|
+
date: 2026-10-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: couchrest
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: 7.0.6
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rest-client
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 2.1.0
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 2.1.0
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
70
|
name: socket.io-client-simple
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -109,35 +123,35 @@ dependencies:
|
|
|
109
123
|
- !ruby/object:Gem::Version
|
|
110
124
|
version: 2.16.0
|
|
111
125
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
126
|
+
name: mysql2
|
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
|
114
128
|
requirements:
|
|
115
129
|
- - "~>"
|
|
116
130
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 5.
|
|
131
|
+
version: 0.5.7
|
|
118
132
|
type: :development
|
|
119
133
|
prerelease: false
|
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
135
|
requirements:
|
|
122
136
|
- - "~>"
|
|
123
137
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: 5.
|
|
138
|
+
version: 0.5.7
|
|
125
139
|
- !ruby/object:Gem::Dependency
|
|
126
|
-
name:
|
|
140
|
+
name: rspec-rails
|
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
|
128
142
|
requirements:
|
|
129
143
|
- - "~>"
|
|
130
144
|
- !ruby/object:Gem::Version
|
|
131
|
-
version:
|
|
145
|
+
version: 5.0.0
|
|
132
146
|
type: :development
|
|
133
147
|
prerelease: false
|
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
149
|
requirements:
|
|
136
150
|
- - "~>"
|
|
137
151
|
- !ruby/object:Gem::Version
|
|
138
|
-
version:
|
|
152
|
+
version: 5.0.0
|
|
139
153
|
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: rswag-
|
|
154
|
+
name: rswag-api
|
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
|
142
156
|
requirements:
|
|
143
157
|
- - "~>"
|
|
@@ -151,7 +165,7 @@ dependencies:
|
|
|
151
165
|
- !ruby/object:Gem::Version
|
|
152
166
|
version: 2.5.1
|
|
153
167
|
- !ruby/object:Gem::Dependency
|
|
154
|
-
name: rswag-
|
|
168
|
+
name: rswag-specs
|
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
|
156
170
|
requirements:
|
|
157
171
|
- - "~>"
|
|
@@ -165,61 +179,33 @@ dependencies:
|
|
|
165
179
|
- !ruby/object:Gem::Version
|
|
166
180
|
version: 2.5.1
|
|
167
181
|
- !ruby/object:Gem::Dependency
|
|
168
|
-
name:
|
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
|
170
|
-
requirements:
|
|
171
|
-
- - "~>"
|
|
172
|
-
- !ruby/object:Gem::Version
|
|
173
|
-
version: 0.79.0
|
|
174
|
-
type: :development
|
|
175
|
-
prerelease: false
|
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
-
requirements:
|
|
178
|
-
- - "~>"
|
|
179
|
-
- !ruby/object:Gem::Version
|
|
180
|
-
version: 0.79.0
|
|
181
|
-
- !ruby/object:Gem::Dependency
|
|
182
|
-
name: rubocop-rspec
|
|
182
|
+
name: rswag-ui
|
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
|
184
184
|
requirements:
|
|
185
185
|
- - "~>"
|
|
186
186
|
- !ruby/object:Gem::Version
|
|
187
|
-
version:
|
|
187
|
+
version: 2.5.1
|
|
188
188
|
type: :development
|
|
189
189
|
prerelease: false
|
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
|
191
191
|
requirements:
|
|
192
192
|
- - "~>"
|
|
193
193
|
- !ruby/object:Gem::Version
|
|
194
|
-
version:
|
|
194
|
+
version: 2.5.1
|
|
195
195
|
- !ruby/object:Gem::Dependency
|
|
196
196
|
name: shoulda-matchers
|
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
|
198
198
|
requirements:
|
|
199
199
|
- - "~>"
|
|
200
200
|
- !ruby/object:Gem::Version
|
|
201
|
-
version:
|
|
202
|
-
type: :development
|
|
203
|
-
prerelease: false
|
|
204
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
205
|
-
requirements:
|
|
206
|
-
- - "~>"
|
|
207
|
-
- !ruby/object:Gem::Version
|
|
208
|
-
version: 4.5.0
|
|
209
|
-
- !ruby/object:Gem::Dependency
|
|
210
|
-
name: sqlite3
|
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
|
212
|
-
requirements:
|
|
213
|
-
- - "~>"
|
|
214
|
-
- !ruby/object:Gem::Version
|
|
215
|
-
version: 1.4.0
|
|
201
|
+
version: '5.3'
|
|
216
202
|
type: :development
|
|
217
203
|
prerelease: false
|
|
218
204
|
version_requirements: !ruby/object:Gem::Requirement
|
|
219
205
|
requirements:
|
|
220
206
|
- - "~>"
|
|
221
207
|
- !ruby/object:Gem::Version
|
|
222
|
-
version:
|
|
208
|
+
version: '5.3'
|
|
223
209
|
description: |
|
|
224
210
|
This adds a lab interface to the OpenMRS compatible core API provided by
|
|
225
211
|
[HIS-EMR-API](https://github.com/EGPAFMalawiHIS/HIS-EMR-API).
|