his_emr_api_lab 2.1.9.pre.beta → 2.2.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/README.md +17 -4
- data/app/controllers/lab/orders_controller.rb +23 -3
- data/app/jobs/lab/process_lab_result_job.rb +1 -4
- data/app/jobs/lab/update_patient_orders_job.rb +1 -50
- data/app/jobs/lab/void_order_job.rb +2 -6
- data/app/models/lab/lab_order.rb +23 -8
- data/app/models/lab/lab_result.rb +2 -2
- data/app/models/lab/lab_test.rb +21 -2
- data/app/serializers/lab/lab_order_serializer.rb +77 -7
- data/app/services/lab/acknowledgement_service.rb +8 -4
- data/app/services/lab/lims/acknowledgement_worker.rb +5 -3
- data/app/services/lab/lims/api/rest_api.rb +139 -47
- data/app/services/lab/lims/order_serializer.rb +29 -39
- data/app/services/lab/lims/pull_worker.rb +173 -3
- data/app/services/lab/lims/push_worker.rb +15 -8
- data/app/services/lab/lims/utils.rb +1 -2
- data/app/services/lab/lims/worker.rb +13 -13
- data/app/services/lab/metadata.rb +1 -0
- data/app/services/lab/notification_service.rb +1 -2
- data/app/services/lab/orders_service.rb +225 -25
- data/app/services/lab/results_service.rb +1 -1
- data/app/services/lab/tests_service.rb +48 -4
- data/app/services/lab/user_service.rb +2 -3
- data/db/migrate/20260226065149_create_lab_status_concepts.rb +80 -0
- data/lib/lab/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c59744a50921b0f2244c94e052d4d66cbf39096485f99755e84f9cb66c311a0b
|
|
4
|
+
data.tar.gz: 989cc056aa59acbcd9d24977d3fc34b330cd1793db5d35908ccce44ca08dab34
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22429cb56bfb9c5af91e5b44e2da11b66551ac89d084eeea45f5b16bb06daf5cc4f99d41cb5f2e4f3d5a38443fb62c15e5a30a14c5e5fff85006a3233d8f71de
|
|
7
|
+
data.tar.gz: 622a040596dc790f1d5a3c05469f7afe131badeca6313eb2412f8da378e632b7b28643c6a12eba6f02c618b9bed680722a635ce6e2e57ea6863872eb5e9b0966
|
data/README.md
CHANGED
|
@@ -22,25 +22,25 @@ For details on how to perform these operations please see the
|
|
|
22
22
|
Add this line to your application's Gemfile:
|
|
23
23
|
|
|
24
24
|
```ruby
|
|
25
|
-
gem '
|
|
25
|
+
gem 'his_emr_api_lab', git: 'https://github.com/EGPAFMalawiHIS/HIS-EMR-API-Lab', branch: 'development'
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
And then execute:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
$ bundle install
|
|
31
|
+
$ bundle install
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Or install it yourself as:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
$ gem install
|
|
37
|
+
$ gem install his_emr_api_lab
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Finally run:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
$ bundle exec rails
|
|
43
|
+
$ bundle exec rails his_emr_api_lab:install
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
## Configuration
|
|
@@ -66,6 +66,19 @@ but too much a departure from it is frowned upon. For example, you will be forgi
|
|
|
66
66
|
for writing a method with 15 to 20 lines if you clearly justify why you couldn't
|
|
67
67
|
break that method into multiple smaller methods.
|
|
68
68
|
|
|
69
|
+
## Publishing
|
|
70
|
+
|
|
71
|
+
To publish a new version of the gem, first update the version number in
|
|
72
|
+
`lib/lab/version.rb` and then run the following command:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
$ gem build his_emr_api_lab.gemspec
|
|
76
|
+
$ gem push his_emr_api_lab-<version>.gem
|
|
77
|
+
```
|
|
78
|
+
Make sure to replace `<version>` with the version number you set in `lib/lab/version.rb`.
|
|
79
|
+
|
|
80
|
+
NB: You need to have an account on [rubygems.org](https://rubygems.org/) and permission to publish gems.
|
|
81
|
+
|
|
69
82
|
## License
|
|
70
83
|
|
|
71
84
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Lab
|
|
4
4
|
class OrdersController < ApplicationController
|
|
5
|
+
skip_before_action :authenticate, only: %i[order_status order_result summary]
|
|
5
6
|
before_action :authenticate_request, only: %i[order_status order_result summary]
|
|
6
7
|
|
|
7
8
|
def create
|
|
@@ -52,7 +53,8 @@ module Lab
|
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
def order_status
|
|
55
|
-
order_params = params.permit(:tracking_number, :status, :status_time, :comments
|
|
56
|
+
order_params = params.permit(:tracking_number, :status, :status_time, :comments, :status_id,
|
|
57
|
+
updated_by: [:first_name, :last_name, :id, :phone_number])
|
|
56
58
|
OrdersService.update_order_status(order_params)
|
|
57
59
|
render json: { message: "Status for order #{order_params['tracking_number']} successfully updated" }, status: :ok
|
|
58
60
|
end
|
|
@@ -76,8 +78,26 @@ module Lab
|
|
|
76
78
|
private
|
|
77
79
|
|
|
78
80
|
def authenticate_request
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
header = request.headers['Authorization']
|
|
82
|
+
content = header.split(' ')
|
|
83
|
+
auth_scheme = content.first
|
|
84
|
+
unless header
|
|
85
|
+
errors = ['Authorization token required']
|
|
86
|
+
render json: { errors: errors }, status: :unauthorized
|
|
87
|
+
return false
|
|
88
|
+
end
|
|
89
|
+
unless auth_scheme == 'Bearer'
|
|
90
|
+
errors = ['Authorization token bearer scheme required']
|
|
91
|
+
render json: { errors: errors }, status: :unauthorized
|
|
92
|
+
return false
|
|
93
|
+
end
|
|
94
|
+
process_token(content.last)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def process_token(token)
|
|
98
|
+
browser = Browser.new(request.user_agent)
|
|
99
|
+
decoded = Lab::JsonWebTokenService.decode(token, request.remote_ip + browser.name + browser.version)
|
|
100
|
+
user(decoded)
|
|
81
101
|
end
|
|
82
102
|
|
|
83
103
|
def user(decoded)
|
|
@@ -7,11 +7,8 @@ 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
|
-
# set location context for the job based on the order's encounter to ensure proper context for any operations performed in the job
|
|
11
10
|
results_obs = Lab::LabResult.unscoped.find(results_obs_id)
|
|
12
|
-
encounter = Encounter.unscoped.find_by(encounter_id: results_obs.encounter_id)
|
|
13
|
-
Location.current = Location.find(encounter.location_id) if encounter&.location_id
|
|
14
11
|
Lab::ResultsService.process_result_completion(results_obs, serializer, result_enter_by)
|
|
15
12
|
end
|
|
16
13
|
end
|
|
17
|
-
end
|
|
14
|
+
end
|
|
@@ -10,8 +10,7 @@ module Lab
|
|
|
10
10
|
Rails.logger.info('Initialising LIMS REST API...')
|
|
11
11
|
|
|
12
12
|
User.current = Lab::Lims::Utils.lab_user
|
|
13
|
-
|
|
14
|
-
set_location_from_patient_encounter(patient_id)
|
|
13
|
+
Location.current = Location.find_by_name('ART clinic')
|
|
15
14
|
|
|
16
15
|
lockfile = Rails.root.join('tmp', "update-patient-orders-#{patient_id}.lock")
|
|
17
16
|
|
|
@@ -29,53 +28,5 @@ module Lab
|
|
|
29
28
|
|
|
30
29
|
File.unlink(lockfile) if done
|
|
31
30
|
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def set_location_from_patient_encounter(patient_id)
|
|
36
|
-
Rails.logger.info("Setting location context for patient #{patient_id}")
|
|
37
|
-
|
|
38
|
-
# Strategy 1: Find location from patient's most recent order (ANY order type)
|
|
39
|
-
recent_order = Order.unscoped
|
|
40
|
-
.where(patient_id: patient_id)
|
|
41
|
-
.order(start_date: :desc)
|
|
42
|
-
.first
|
|
43
|
-
|
|
44
|
-
if recent_order
|
|
45
|
-
encounter = Encounter.unscoped.find_by(encounter_id: recent_order.encounter_id)
|
|
46
|
-
if encounter&.location_id
|
|
47
|
-
Location.current = Location.find(encounter.location_id)
|
|
48
|
-
Rails.logger.info("Location set from patient's recent order: #{Location.current.name} (ID: #{Location.current.location_id})")
|
|
49
|
-
return
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Strategy 2: Find location from patient's most recent encounter
|
|
54
|
-
recent_encounter = Encounter.unscoped
|
|
55
|
-
.where(patient_id: patient_id)
|
|
56
|
-
.order(encounter_datetime: :desc)
|
|
57
|
-
.first
|
|
58
|
-
|
|
59
|
-
if recent_encounter&.location_id
|
|
60
|
-
Location.current = Location.find(recent_encounter.location_id)
|
|
61
|
-
Rails.logger.info("Location set from patient's recent encounter: #{Location.current.name} (ID: #{Location.current.location_id})")
|
|
62
|
-
return
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Fallback chain: Try multiple options to ensure location is ALWAYS set
|
|
66
|
-
Location.current ||= begin
|
|
67
|
-
Location.current_health_center
|
|
68
|
-
rescue StandardError
|
|
69
|
-
nil
|
|
70
|
-
end
|
|
71
|
-
Location.current ||= Location.first
|
|
72
|
-
|
|
73
|
-
if Location.current
|
|
74
|
-
Rails.logger.info("Location set to fallback: #{Location.current.name} (ID: #{Location.current.location_id})")
|
|
75
|
-
else
|
|
76
|
-
Rails.logger.error('CRITICAL: Could not set Location.current - no locations found in database!')
|
|
77
|
-
raise 'No locations available in database'
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
31
|
end
|
|
81
32
|
end
|
|
@@ -8,14 +8,10 @@ module Lab
|
|
|
8
8
|
Rails.logger.info("Voiding order ##{order_id} in LIMS")
|
|
9
9
|
|
|
10
10
|
User.current = Lab::Lims::Utils.lab_user
|
|
11
|
-
|
|
12
|
-
order = Lab::LabOrder.unscoped.find(order_id)
|
|
13
|
-
encounter = Encounter.unscoped.find_by(encounter_id: order.encounter_id)
|
|
14
|
-
Location.current = Location.find(encounter.location_id) if encounter&.location_id
|
|
15
|
-
Location.current ||= Location.find_by_name('ART clinic')
|
|
11
|
+
Location.current = Location.find_by_name('ART clinic')
|
|
16
12
|
|
|
17
13
|
worker = Lab::Lims::PushWorker.new(Lab::Lims::ApiFactory.create_api)
|
|
18
|
-
worker.push_order(
|
|
14
|
+
worker.push_order(Lab::LabOrder.unscoped.find(order_id))
|
|
19
15
|
end
|
|
20
16
|
end
|
|
21
17
|
end
|
data/app/models/lab/lab_order.rb
CHANGED
|
@@ -8,6 +8,11 @@ module Lab
|
|
|
8
8
|
|
|
9
9
|
-> { where(concept:) }
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
# Cache the concept ID to avoid lookups in association scopes
|
|
13
|
+
def order_status_concept_id
|
|
14
|
+
@order_status_concept_id ||= ConceptName.find_by(name: 'Lab Order Status')&.concept_id
|
|
15
|
+
end
|
|
11
16
|
end
|
|
12
17
|
|
|
13
18
|
has_many :tests,
|
|
@@ -44,12 +49,20 @@ module Lab
|
|
|
44
49
|
class_name: '::Lab::LimsOrderMapping',
|
|
45
50
|
foreign_key: :order_id
|
|
46
51
|
|
|
52
|
+
# Status trails are stored as observations with concept 'Lab Order Status'
|
|
53
|
+
has_many :status_trail_observations,
|
|
54
|
+
lambda {
|
|
55
|
+
unscoped.where(voided: 0, concept_id: Lab::LabOrder.order_status_concept_id).order(obs_datetime: :asc)
|
|
56
|
+
},
|
|
57
|
+
class_name: 'Observation',
|
|
58
|
+
foreign_key: :order_id
|
|
59
|
+
|
|
47
60
|
default_scope do
|
|
48
61
|
joins(:order_type)
|
|
49
62
|
.merge(OrderType.where(name: [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
Lab::Metadata::ORDER_TYPE_NAME,
|
|
64
|
+
Lab::Metadata::HTS_ORDER_TYPE_NAME
|
|
65
|
+
]))
|
|
53
66
|
.where.not(concept_id: ConceptName.where(name: 'Tests ordered').select(:concept_id))
|
|
54
67
|
end
|
|
55
68
|
|
|
@@ -57,11 +70,13 @@ module Lab
|
|
|
57
70
|
scope :not_drawn, -> { where(concept_id: ConceptName.where(name: 'Unknown').select(:concept_id)) }
|
|
58
71
|
|
|
59
72
|
def self.prefetch_relationships
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
73
|
+
# NOTE: status_trail_observations and test results are not preloaded due to
|
|
74
|
+
# Rails limitations with eager loading unscoped associations. They load on-demand instead.
|
|
75
|
+
preload(:reason_for_test,
|
|
76
|
+
:requesting_clinician,
|
|
77
|
+
:target_lab,
|
|
78
|
+
:comment_to_fulfiller,
|
|
79
|
+
:tests)
|
|
65
80
|
end
|
|
66
81
|
end
|
|
67
82
|
end
|
data/app/models/lab/lab_test.rb
CHANGED
|
@@ -6,14 +6,33 @@ module Lab
|
|
|
6
6
|
where(concept: ConceptName.where(name: Lab::Metadata::TEST_TYPE_CONCEPT_NAME))
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
# Cache the concept IDs as class methods to avoid lookups in association scopes
|
|
10
|
+
def self.test_status_concept_id
|
|
11
|
+
@test_status_concept_id ||= ConceptName.find_by(name: 'Lab Test Status')&.concept_id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.test_result_concept_id
|
|
15
|
+
@test_result_concept_id ||= ConceptName.find_by(name: Lab::Metadata::TEST_RESULT_CONCEPT_NAME)&.concept_id
|
|
16
|
+
end
|
|
17
|
+
|
|
9
18
|
has_one :result,
|
|
10
|
-
-> { where(
|
|
19
|
+
-> { unscoped.where(voided: 0, concept_id: Lab::LabTest.test_result_concept_id) },
|
|
11
20
|
class_name: 'Lab::LabResult',
|
|
12
21
|
foreign_key: :obs_group_id
|
|
13
22
|
|
|
23
|
+
# Status trails are stored as observations with concept 'Lab Test Status'
|
|
24
|
+
# They are linked via obs_group_id (this test obs is the parent)
|
|
25
|
+
has_many :status_trail_observations,
|
|
26
|
+
lambda {
|
|
27
|
+
unscoped.where(voided: 0, concept_id: Lab::LabTest.test_status_concept_id).order(obs_datetime: :asc)
|
|
28
|
+
},
|
|
29
|
+
class_name: 'Observation',
|
|
30
|
+
foreign_key: :obs_group_id,
|
|
31
|
+
primary_key: :obs_id
|
|
32
|
+
|
|
14
33
|
def void(reason)
|
|
15
34
|
result&.void(reason)
|
|
16
|
-
super
|
|
35
|
+
super
|
|
17
36
|
end
|
|
18
37
|
end
|
|
19
38
|
end
|
|
@@ -9,9 +9,8 @@ module Lab
|
|
|
9
9
|
reason_for_test ||= order.reason_for_test
|
|
10
10
|
target_lab = target_lab&.value_text || order.target_lab&.value_text || Location.current_health_center&.name
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
program = Program.find_by_program_id(encounter.program_id)
|
|
12
|
+
encounter = Encounter.find_by_encounter_id(order.encounter_id)
|
|
13
|
+
program = Program.find_by_program_id(encounter&.program_id)
|
|
15
14
|
|
|
16
15
|
ActiveSupport::HashWithIndifferentAccess.new(
|
|
17
16
|
{
|
|
@@ -20,8 +19,8 @@ module Lab
|
|
|
20
19
|
order_id: order.order_id, # Deprecated: Link to :id
|
|
21
20
|
encounter_id: order.encounter_id,
|
|
22
21
|
order_date: order.start_date,
|
|
23
|
-
location_id: encounter
|
|
24
|
-
program_id: encounter
|
|
22
|
+
location_id: encounter&.location_id,
|
|
23
|
+
program_id: encounter&.program_id,
|
|
25
24
|
program_name: program&.name,
|
|
26
25
|
patient_id: order.patient_id,
|
|
27
26
|
accession_number: order.accession_number,
|
|
@@ -37,8 +36,10 @@ module Lab
|
|
|
37
36
|
name: concept_name(reason_for_test&.value_coded)
|
|
38
37
|
},
|
|
39
38
|
delivery_mode: order&.lims_acknowledgement_status&.acknowledgement_type,
|
|
39
|
+
order_status: latest_order_status(order),
|
|
40
|
+
order_status_trail: serialize_order_status_trail(order),
|
|
40
41
|
tests: tests.map do |test|
|
|
41
|
-
result_obs = test.
|
|
42
|
+
result_obs = test.result
|
|
42
43
|
|
|
43
44
|
{
|
|
44
45
|
id: test.obs_id,
|
|
@@ -46,7 +47,9 @@ module Lab
|
|
|
46
47
|
uuid: test.uuid,
|
|
47
48
|
name: concept_name(test.value_coded),
|
|
48
49
|
test_method: test_method(order, test.value_coded),
|
|
49
|
-
result: result_obs && ResultSerializer.serialize(result_obs)
|
|
50
|
+
result: result_obs && ResultSerializer.serialize(result_obs),
|
|
51
|
+
test_status: latest_test_status(test),
|
|
52
|
+
test_status_trail: serialize_test_status_trail(test)
|
|
50
53
|
}
|
|
51
54
|
end
|
|
52
55
|
}
|
|
@@ -75,5 +78,72 @@ module Lab
|
|
|
75
78
|
.select(:concept_id)
|
|
76
79
|
LabTest.unscoped.where(concept:, order:, voided: true)
|
|
77
80
|
end
|
|
81
|
+
|
|
82
|
+
def self.latest_order_status(order)
|
|
83
|
+
# Query obs table for latest order status
|
|
84
|
+
latest_obs = order.status_trail_observations.last
|
|
85
|
+
return nil unless latest_obs
|
|
86
|
+
|
|
87
|
+
updated_by = parse_comments_json(latest_obs.comments)
|
|
88
|
+
|
|
89
|
+
{
|
|
90
|
+
status_id: 0, # status_id not used with text values
|
|
91
|
+
status: latest_obs.value_text,
|
|
92
|
+
timestamp: latest_obs.obs_datetime,
|
|
93
|
+
updated_by: updated_by
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.serialize_order_status_trail(order)
|
|
98
|
+
# Query obs table for order status trail
|
|
99
|
+
order.status_trail_observations.map do |obs|
|
|
100
|
+
updated_by = parse_comments_json(obs.comments)
|
|
101
|
+
|
|
102
|
+
{
|
|
103
|
+
status_id: 0, # status_id not used with text values
|
|
104
|
+
status: obs.value_text,
|
|
105
|
+
timestamp: obs.obs_datetime,
|
|
106
|
+
updated_by: updated_by
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.latest_test_status(test)
|
|
112
|
+
# Query obs table for latest test status
|
|
113
|
+
latest_obs = test.status_trail_observations.last
|
|
114
|
+
return nil unless latest_obs
|
|
115
|
+
|
|
116
|
+
updated_by = parse_comments_json(latest_obs.comments)
|
|
117
|
+
|
|
118
|
+
{
|
|
119
|
+
status_id: 0, # status_id not used with text values
|
|
120
|
+
status: latest_obs.value_text,
|
|
121
|
+
timestamp: latest_obs.obs_datetime,
|
|
122
|
+
updated_by: updated_by
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def self.serialize_test_status_trail(test)
|
|
127
|
+
# Query obs table for test status trail
|
|
128
|
+
test.status_trail_observations.map do |obs|
|
|
129
|
+
updated_by = parse_comments_json(obs.comments)
|
|
130
|
+
|
|
131
|
+
{
|
|
132
|
+
status_id: 0, # status_id not used with text values
|
|
133
|
+
status: obs.value_text,
|
|
134
|
+
timestamp: obs.obs_datetime,
|
|
135
|
+
updated_by: updated_by
|
|
136
|
+
}
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Helper to parse updated_by from obs comments field
|
|
141
|
+
def self.parse_comments_json(comments)
|
|
142
|
+
return {} if comments.blank?
|
|
143
|
+
|
|
144
|
+
JSON.parse(comments)
|
|
145
|
+
rescue JSON::ParserError
|
|
146
|
+
{}
|
|
147
|
+
end
|
|
78
148
|
end
|
|
79
149
|
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
|
-
|
|
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',
|
|
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
|
|
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|
|