his_emr_api_lab 2.1.7.pre.beta.0 → 2.1.7.pre.gamma

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b15bb82b3ff39714e8f48a1a8102bc9c0347d5498f2e8fae7d8e5c446d0d15f5
4
- data.tar.gz: 159e9321795329ae186bf7d4a88aa492f63634ed5b5a236fb6a634da0dbd8342
3
+ metadata.gz: 593219b282a6f5cbe26cdd80a8324412650f3242d6ab48d622d1572699033c82
4
+ data.tar.gz: fb5bf82bc4569423c1e8b3ac5ff5d076e7734c565736e51ab0d453a61269d027
5
5
  SHA512:
6
- metadata.gz: e2632b305212c9f09bc2347f6d2a14d873b781e02311c1f52309f52db418ea194124fcc2065f7258865204bd918a56888e29c4d40656f08cf99b8d6184b75b0a
7
- data.tar.gz: 6e4f055b0412a7300c11abcb955c732302b5429db0aec611a888df507c5f547328715a7831f9411a181695549f698cb04430b5a4f564f3f9e42d23b25af2034e
6
+ metadata.gz: 1a941f7c1be9866e55bdbc035e23566b9e185f6131ab52f5fb17b3dd362cbfeb2d2b630929aea6904121232247edcb69ff451a1bc5a3d4528a1373e8db79f907
7
+ data.tar.gz: 60e00f01de37eb379b7f1a816baa793452f0b4b05cdda4596c495f5049a2431d69946aa33c3cae26c23847a69e1a99a9903b25a6dcf48b73c4cd237896653671
@@ -7,7 +7,7 @@ module Lab
7
7
  queue_as :default
8
8
  def perform(results_obs_id, serializer, result_enter_by)
9
9
  Rails.logger.info("Lab::ProcessLabResultJob: Processing result completion for #{serializer}")
10
- results_obs = Lab::LabResult.find(results_obs_id)
10
+ results_obs = Lab::LabResult.unscoped.find(results_obs_id)
11
11
  Lab::ResultsService.process_result_completion(results_obs, serializer, result_enter_by)
12
12
  end
13
13
  end
@@ -14,9 +14,12 @@ module Lab
14
14
  date_received: params[:date_received])
15
15
  end
16
16
 
17
- def acknowledgements_pending_sync(batch_size)
18
- Lab::LabAcknowledgement.where(pushed: false)
19
- .limit(batch_size)
17
+ def acknowledgements_pending_sync(batch_size, start_date: nil)
18
+ query = Lab::LabAcknowledgement.joins(:order).where(pushed: false)
19
+
20
+ query = query.where('orders.date_created >= ?', start_date) if start_date
21
+
22
+ query.limit(batch_size)
20
23
  end
21
24
 
22
25
  def push_acknowledgement(acknowledgement, lims_api)
@@ -30,7 +33,8 @@ module Lab
30
33
  Rails.logger.info("Updating acknowledgement ##{acknowledgement_dto[:tracking_number]} in LIMS")
31
34
  response = lims_api.acknowledge(acknowledgement_dto)
32
35
  Rails.logger.info("Info #{response}")
33
- if ['results already delivered for test name given', 'test result acknowledged successfully', 'test result already acknowledged electronically at facility'].include?(response['message'])
36
+ if ['results already delivered for test name given', 'test result acknowledged successfully',
37
+ 'test result already acknowledged electronically at facility'].include?(response['message'])
34
38
  acknowledgement.pushed = true
35
39
  acknowledgement.date_pushed = Time.now
36
40
  acknowledgement.save!
@@ -4,20 +4,22 @@ module Lab
4
4
  module Lims
5
5
  # This class is responsible for handling the acknowledgement of lab orders
6
6
  class AcknowledgementWorker
7
- attr_reader :lims_api
7
+ attr_reader :lims_api, :start_date
8
8
 
9
9
  include Utils # for logger
10
10
 
11
11
  SECONDS_TO_WAIT_FOR_ORDERS = 30
12
12
 
13
- def initialize(lims_api)
13
+ def initialize(lims_api, start_date: nil)
14
14
  @lims_api = lims_api
15
+ @start_date = start_date
15
16
  end
16
17
 
17
18
  def push_acknowledgement(batch_size: 1000, wait: false)
18
19
  loop do
19
20
  logger.info('Looking for new acknowledgements to push to LIMS...')
20
- acknowledgements = Lab::AcknowledgementService.acknowledgements_pending_sync(batch_size).all
21
+ acknowledgements = Lab::AcknowledgementService.acknowledgements_pending_sync(batch_size,
22
+ start_date: start_date).all
21
23
 
22
24
  logger.debug("Found #{acknowledgements.size} acknowledgements...")
23
25
  acknowledgements.each do |acknowledgement|
@@ -74,8 +74,8 @@ module Lab
74
74
  { tracking_number: order_dto[:tracking_number] }
75
75
  end
76
76
 
77
- def consume_orders(*_args, patient_id: nil, **_kwargs)
78
- orders_pending_updates(patient_id).each do |order|
77
+ def consume_orders(*_args, patient_id: nil, start_date: nil, **_kwargs)
78
+ orders_pending_updates(patient_id, start_date: start_date).each do |order|
79
79
  order_dto = Lab::Lims::OrderSerializer.serialize_order(order)
80
80
  if order_dto['priority'].nil? || order_dto['sample_type'].casecmp?('not_specified')
81
81
  patch_order_dto_with_lims_order!(order_dto, find_lims_order(order.accession_number))
@@ -510,43 +510,47 @@ module Lab
510
510
  }
511
511
  end
512
512
 
513
- def orders_pending_updates(patient_id = nil)
513
+ def orders_pending_updates(patient_id = nil, start_date: nil)
514
514
  Rails.logger.info('Looking for orders that need to be updated...')
515
515
  orders = {}
516
516
 
517
- orders_without_specimen(patient_id).each { |order| orders[order.order_id] = order }
518
- orders_without_results(patient_id).each { |order| orders[order.order_id] = order }
519
- orders_without_reason(patient_id).each { |order| orders[order.order_id] = order }
517
+ orders_without_specimen(patient_id, start_date: start_date).each { |order| orders[order.order_id] = order }
518
+ orders_without_results(patient_id, start_date: start_date).each { |order| orders[order.order_id] = order }
519
+ orders_without_reason(patient_id, start_date: start_date).each { |order| orders[order.order_id] = order }
520
520
 
521
521
  orders.values
522
522
  end
523
523
 
524
- def orders_without_specimen(patient_id = nil)
524
+ def orders_without_specimen(patient_id = nil, start_date: nil)
525
525
  Rails.logger.debug('Looking for orders without a specimen')
526
526
  unknown_specimen = ConceptName.where(name: Lab::Metadata::UNKNOWN_SPECIMEN)
527
527
  .select(:concept_id)
528
528
  orders = Lab::LabOrder.where(concept_id: unknown_specimen)
529
529
  .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id))
530
530
  orders = orders.where(patient_id:) if patient_id
531
+ orders = orders.where('orders.date_created >= ?', start_date) if start_date
531
532
 
532
533
  orders
533
534
  end
534
535
 
535
- def orders_without_results(patient_id = nil)
536
+ def orders_without_results(patient_id = nil, start_date: nil)
536
537
  Rails.logger.debug('Looking for orders without a result')
537
538
  # Lab::OrdersSearchService.find_orders_without_results(patient_id: patient_id)
538
539
  # .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id).where("pulled_at IS NULL"))
539
- Lab::OrdersSearchService.find_orders_without_results(patient_id:)
540
- .where(order_id: Lab::LimsOrderMapping.select(:order_id))
540
+ orders = Lab::OrdersSearchService.find_orders_without_results(patient_id:)
541
+ .where(order_id: Lab::LimsOrderMapping.select(:order_id))
542
+ orders = orders.where('orders.date_created >= ?', start_date) if start_date
543
+ orders
541
544
  end
542
545
 
543
- def orders_without_reason(patient_id = nil)
546
+ def orders_without_reason(patient_id = nil, start_date: nil)
544
547
  Rails.logger.debug('Looking for orders without a reason for test')
545
548
  orders = Lab::LabOrder.joins(:reason_for_test)
546
549
  .merge(Observation.where(value_coded: nil, value_text: nil))
547
550
  .limit(1000)
548
551
  .where.not(accession_number: Lab::LimsOrderMapping.select(:lims_id))
549
552
  orders = orders.where(patient_id:) if patient_id
553
+ orders = orders.where('orders.date_created >= ?', start_date) if start_date
550
554
 
551
555
  orders
552
556
  end
@@ -5,14 +5,15 @@ module Lab
5
5
  ##
6
6
  # Pulls orders from a Lims API object and saves them to the local database.
7
7
  class PullWorker
8
- attr_reader :lims_api
8
+ attr_reader :lims_api, :start_date
9
9
 
10
10
  include Utils # for logger
11
11
 
12
12
  LIMS_LOG_PATH = Rails.root.join('log', 'lims')
13
13
 
14
- def initialize(lims_api)
14
+ def initialize(lims_api, start_date: nil)
15
15
  @lims_api = lims_api
16
+ @start_date = start_date
16
17
  end
17
18
 
18
19
  ##
@@ -20,7 +21,7 @@ module Lab
20
21
  def pull_orders(batch_size: 10_000, **)
21
22
  logger.info("Retrieving LIMS orders starting from #{last_seq}")
22
23
 
23
- lims_api.consume_orders(from: last_seq, limit: batch_size, **) do |order_dto, context|
24
+ lims_api.consume_orders(from: last_seq, limit: batch_size, start_date: start_date, **) do |order_dto, context|
24
25
  logger.debug("Retrieved order ##{order_dto[:tracking_number]}: #{order_dto}")
25
26
 
26
27
  patient = find_patient_by_nhid(order_dto[:patient][:id], order_dto[:tracking_number])
@@ -5,15 +5,16 @@ module Lab
5
5
  ##
6
6
  # Pushes all local orders to a LIMS Api object.
7
7
  class PushWorker
8
- attr_reader :lims_api
8
+ attr_reader :lims_api, :start_date
9
9
 
10
10
  include Utils # for logger
11
11
 
12
12
  SECONDS_TO_WAIT_FOR_ORDERS = 30
13
13
  START_DATE = Time.parse('2024-09-03').freeze
14
14
 
15
- def initialize(lims_api)
15
+ def initialize(lims_api, start_date: nil)
16
16
  @lims_api = lims_api
17
+ @start_date = start_date
17
18
  end
18
19
 
19
20
  def push_orders(batch_size: 1000, wait: false)
@@ -81,8 +82,8 @@ module Lab
81
82
 
82
83
  def void_order_in_lims(order_id)
83
84
  order = Lab::LabOrder.joins(order_type: { name: 'Lab' })
84
- .unscoped
85
- .find(order_id)
85
+ .unscoped
86
+ .find(order_id)
86
87
  order_dto = Lab::Lims::OrderSerializer.serialize_order(order)
87
88
  Rails.logger.info("Deleting order ##{order_dto[:accession_number]} from LIMS")
88
89
  lims_api.delete_order('', order_dto)
@@ -100,10 +101,16 @@ module Lab
100
101
 
101
102
  def new_orders
102
103
  Rails.logger.debug('Looking for new orders that need to be created in LIMS...')
103
- Lab::LabOrder.where.not(order_id: Lab::LimsOrderMapping.all.select(:order_id))
104
- .where("accession_number IS NOT NULL AND accession_number !=''")
105
- .where(date_created: START_DATE..(Date.today + 1.day))
106
- .order(date_created: :desc)
104
+ query = Lab::LabOrder.where.not(order_id: Lab::LimsOrderMapping.all.select(:order_id))
105
+ .where("accession_number IS NOT NULL AND accession_number !=''")
106
+
107
+ query = if start_date
108
+ query.where('orders.date_created >= ?', start_date)
109
+ else
110
+ query.where('orders.date_created >= ? AND orders.date_created <= ?', START_DATE, Date.today + 1.day)
111
+ end
112
+
113
+ query.order(date_created: :desc)
107
114
  end
108
115
 
109
116
  def updated_orders
@@ -9,43 +9,43 @@ module Lab
9
9
  ##
10
10
  # Pull/Push orders from/to the LIMS queue (Oops meant CouchDB).
11
11
  module Worker
12
- def self.start
12
+ def self.start(start_date: nil)
13
13
  User.current = Utils.lab_user
14
14
 
15
- fork(&method(:start_push_worker))
16
- fork(&method(:start_pull_worker))
17
- fork(&method(:start_acknowledgement_worker))
18
- fork(&method(:start_realtime_pull_worker)) if realtime_updates_enabled?
15
+ fork { start_push_worker(start_date: start_date) }
16
+ fork { start_pull_worker(start_date: start_date) }
17
+ fork { start_acknowledgement_worker(start_date: start_date) }
18
+ fork { start_realtime_pull_worker(start_date: start_date) } if realtime_updates_enabled?
19
19
 
20
20
  Process.waitall
21
21
  end
22
22
 
23
- def self.start_push_worker
23
+ def self.start_push_worker(start_date: nil)
24
24
  start_worker('push_worker') do
25
- worker = PushWorker.new(lims_api)
25
+ worker = PushWorker.new(lims_api, start_date: start_date)
26
26
 
27
27
  worker.push_orders # (wait: true)
28
28
  end
29
29
  end
30
30
 
31
- def self.start_acknowledgement_worker
31
+ def self.start_acknowledgement_worker(start_date: nil)
32
32
  start_worker('acknowledgement_worker') do
33
- worker = AcknowledgementWorker.new(lims_api)
33
+ worker = AcknowledgementWorker.new(lims_api, start_date: start_date)
34
34
  worker.push_acknowledgement
35
35
  end
36
36
  end
37
37
 
38
- def self.start_pull_worker
38
+ def self.start_pull_worker(start_date: nil)
39
39
  start_worker('pull_worker') do
40
- worker = PullWorker.new(lims_api)
40
+ worker = PullWorker.new(lims_api, start_date: start_date)
41
41
 
42
42
  worker.pull_orders
43
43
  end
44
44
  end
45
45
 
46
- def self.start_realtime_pull_worker
46
+ def self.start_realtime_pull_worker(start_date: nil)
47
47
  start_worker('realtime_pull_worker') do
48
- worker = PullWorker.new(Lims::Api::WsApi.new(Lab::Lims::Config.updates_socket))
48
+ worker = PullWorker.new(Lims::Api::WsApi.new(Lab::Lims::Config.updates_socket), start_date: start_date)
49
49
 
50
50
  worker.pull_orders
51
51
  end
@@ -102,16 +102,14 @@ module Lab
102
102
 
103
103
  if reason_for_test
104
104
  Rails.logger.debug("Updating reason for test on order ##{order.order_id}")
105
- update_reason_for_test(order, Concept.find(reason_for_test)&.id,
106
- force_update: params.fetch('force_update', false))
105
+ update_reason_for_test(order, Concept.find(reason_for_test)&.id, force_update: params.fetch('force_update', false))
107
106
  end
108
107
 
109
108
  Lab::LabOrderSerializer.serialize_order(order)
110
109
  end
111
110
 
112
111
  def void_order(order_id, reason)
113
- order = Lab::LabOrder.includes(%i[requesting_clinician reason_for_test target_lab comment_to_fulfiller],
114
- tests: [:result])
112
+ order = Lab::LabOrder.includes(%i[requesting_clinician reason_for_test target_lab comment_to_fulfiller], tests: [:result])
115
113
  .find(order_id)
116
114
 
117
115
  order.requesting_clinician&.void(reason)
@@ -162,15 +160,13 @@ module Lab
162
160
  last_order_date: Lab::LabOrder.last&.start_date&.to_date,
163
161
  lab_orders: []
164
162
  }
165
- if include_data
166
- data[:lab_orders] = orders.map do |order|
167
- Lab::LabOrderSerializer.serialize_order(
168
- order, requesting_clinician: order.requesting_clinician,
169
- reason_for_test: order.reason_for_test,
170
- target_lab: order.target_lab
171
- )
172
- end
173
- end
163
+ data[:lab_orders] = orders.map do |order|
164
+ Lab::LabOrderSerializer.serialize_order(
165
+ order, requesting_clinician: order.requesting_clinician,
166
+ reason_for_test: order.reason_for_test,
167
+ target_lab: order.target_lab
168
+ )
169
+ end if include_data
174
170
  data
175
171
  end
176
172
 
@@ -178,14 +174,14 @@ module Lab
178
174
 
179
175
  def create_rejection_notification(order_params)
180
176
  order = find_order order_params['tracking_number']
181
- data = { type: 'LIMS',
182
- specimen: ConceptName.find_by(concept_id: order.concept_id)&.name,
183
- accession_number: order&.accession_number,
184
- order_date: order&.start_date,
185
- arv_number: find_arv_number(order.patient_id),
186
- patient_id: result.person_id,
187
- ordered_by: order&.provider&.person&.name,
188
- rejection_reason: order_params['comments'] }.as_json
177
+ data = { 'type': 'LIMS',
178
+ 'specimen': ConceptName.find_by(concept_id: order.concept_id)&.name,
179
+ 'accession_number': order&.accession_number,
180
+ 'order_date': order&.start_date,
181
+ 'arv_number': find_arv_number(order.patient_id),
182
+ 'patient_id': result.person_id,
183
+ 'ordered_by': order&.provider&.person&.name,
184
+ 'rejection_reason': order_params['comments'] }.as_json
189
185
  NotificationService.new.create_notification('LIMS', data)
190
186
  end
191
187
 
@@ -239,9 +235,7 @@ module Lab
239
235
  encounter.encounter_datetime = order_params[:date] || Date.today
240
236
  encounter.visit = Visit.find_by_uuid(visit) if Encounter.column_names.include?('visit_id')
241
237
  encounter.provider_id = User.current&.person&.id if Encounter.column_names.include?('provider_id')
242
- if Encounter.column_names.include?('program_id') && order_params[:program_id].present?
243
- encounter.program_id = order_params[:program_id]
244
- end
238
+ encounter.program_id = order_params[:program_id] if Encounter.column_names.include?('program_id') && order_params[:program_id].present?
245
239
  encounter.save!
246
240
  encounter.reload
247
241
  end
@@ -265,7 +259,7 @@ module Lab
265
259
  order.date_created = params[:date]&.to_date || Date.today if order.respond_to?(:date_created)
266
260
  order.start_date = params[:date]&.to_date || Date.today if order.respond_to?(:start_date)
267
261
  order.auto_expire_date = params[:end_date]
268
- # NOTE: comment_to_fulfiller is a has_one association, not a field
262
+ # Note: comment_to_fulfiller is a has_one association, not a field
269
263
  # It will be created via add_comment_to_fulfiller method
270
264
  order.accession_number = access_number
271
265
  order.orderer = User.current&.user_id
@@ -362,10 +356,7 @@ module Lab
362
356
 
363
357
  return if order.reason_for_test&.value_coded == concept_id
364
358
 
365
- if order.reason_for_test&.value_coded && !force_update
366
- raise InvalidParameterError,
367
- "Can't change reason for test once set"
368
- end
359
+ raise InvalidParameterError, "Can't change reason for test once set" if order.reason_for_test&.value_coded && !force_update
369
360
 
370
361
  order.reason_for_test&.delete
371
362
  date = order.start_date if order.respond_to?(:start_date)
data/lib/lab/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lab
4
- VERSION = '2.1.7-beta.0'
4
+ VERSION = '2.1.7-gamma'
5
5
  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: 2.1.7.pre.beta.0
4
+ version: 2.1.7.pre.gamma
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-02-19 00:00:00.000000000 Z
11
+ date: 2026-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: couchrest