his_emr_api_lab 2.1.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa0a902d0f6f1159525e92598deb3ee77684c17c12a52078fa20d44cf2cafec1
4
- data.tar.gz: a0b8c8d773c498dc77b4beaeb460b491695785cca91245bf62149d434e1e4841
3
+ metadata.gz: 1c80aacd232547335da6ecc016e3dd846f4f10f5490653db6ad877c21fc4eb3e
4
+ data.tar.gz: 4ddb8bf35b0c011f9e85c7167c1b3f6e551933d0f697123771ce007ea728a74e
5
5
  SHA512:
6
- metadata.gz: f24e327db48725b4ddffb24e12dcd09e02c1a0965ecdeb6aae08ab547305de6053a2d93d07154ed7750639b376b51bbedaeee54ec6cd44eeeb992f6d46dd5e8e
7
- data.tar.gz: beca813e59561a368b4ad8252f82364b19c801adcead63d8c4b3f1562ebe1066b94f4d09a3abb6c1f734728836de5b719bb3deb685598127220741fcb4f42541
6
+ metadata.gz: 414b6d9dbe2f808869ce6a2bc17818b8c8da6de35514dbc418aec03bdee86e934367569e15139ddc1d38a432a32a47c55955b276384203449e90ba99c2f84acc
7
+ data.tar.gz: bdbda16a58d3a67cf89aeeee958eb9975bf4d06af53b0cfda460f8b5fb31c09354695c7a26e8ee4c71dfcfa6c7910d2c864c56e35be6db0cfa74736b864933b8
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lab
4
+ ##
5
+ # Push an order to LIMS.
6
+ class ProcessLabResultJob < ApplicationJob
7
+ queue_as :default
8
+ def perform(results_obs_id, serializer, result_enter_by)
9
+ results_obs = Lab::LabResult.find(results_obs_id)
10
+ Lab::ResultsService.process_result_completion(results_obs, serializer, result_enter_by)
11
+ end
12
+ end
13
+ end
@@ -41,7 +41,10 @@ module Lab
41
41
 
42
42
  default_scope do
43
43
  joins(:order_type)
44
- .merge(OrderType.where(name: Lab::Metadata::ORDER_TYPE_NAME))
44
+ .merge(OrderType.where(name: [
45
+ Lab::Metadata::ORDER_TYPE_NAME,
46
+ Lab::Metadata::HTS_ORDER_TYPE_NAME
47
+ ]))
45
48
  .where.not(concept_id: ConceptName.where(name: 'Tests ordered').select(:concept_id))
46
49
  end
47
50
 
@@ -8,11 +8,18 @@ module Lab
8
8
  reason_for_test ||= order.reason_for_test
9
9
  target_lab = target_lab&.value_text || order.target_lab&.value_text || Location.current_health_center&.name
10
10
 
11
+ encounter = Encounter.find_by_encounter_id(order.encounter_id)
12
+ program = Program.find_by_program_id(encounter.program_id)
13
+
11
14
  ActiveSupport::HashWithIndifferentAccess.new(
12
15
  {
13
16
  id: order.order_id,
17
+ order_type_id: order.order_type_id,
14
18
  order_id: order.order_id, # Deprecated: Link to :id
15
19
  encounter_id: order.encounter_id,
20
+ location_id: encounter.location_id,
21
+ program_id: encounter.program_id,
22
+ program_name: program.name,
16
23
  order_date: order.start_date,
17
24
  patient_id: order.patient_id,
18
25
  accession_number: order.accession_number,
@@ -8,6 +8,13 @@ module Lab
8
8
  result.children.map do |measure|
9
9
  value, value_type = read_value(measure)
10
10
  concept_name = ConceptName.find_by_concept_id(measure.concept_id)
11
+
12
+ program_id = ""
13
+ if measure.obs_id.present?
14
+ obs = Observation.find(measure.obs_id)
15
+ encounter = Encounter.find(obs.encounter_id)
16
+ program_id = encounter.program_id
17
+ end
11
18
 
12
19
  {
13
20
  id: measure.obs_id,
@@ -18,7 +25,8 @@ module Lab
18
25
  date: measure.obs_datetime,
19
26
  value:,
20
27
  value_type:,
21
- value_modifier: measure.value_modifier
28
+ value_modifier: measure.value_modifier,
29
+ program_id: program_id
22
30
  }
23
31
  end
24
32
  end
@@ -41,8 +41,8 @@ module Lab
41
41
  year = format_year(date.year)
42
42
  month = format_month(date.month)
43
43
  day = format_day(date.day)
44
-
45
- "X#{site_code}#{year}#{month}#{day}#{counter}"
44
+ time_acc_generated = Time.now.strftime('%H%M')
45
+ "X#{site_code}#{year}#{month}#{day}#{counter}#{time_acc_generated}"
46
46
  end
47
47
 
48
48
  def format_year(year)
@@ -23,7 +23,7 @@ module Lab
23
23
  lims_api.consume_orders(from: last_seq, limit: batch_size, **) do |order_dto, context|
24
24
  logger.debug("Retrieved order ##{order_dto[:tracking_number]}: #{order_dto}")
25
25
 
26
- patient = find_patient_by_nhid(order_dto[:patient][:id])
26
+ patient = find_patient_by_nhid(order_dto[:patient][:id], order_dto[:tracking_number])
27
27
  unless patient
28
28
  logger.debug("Discarding order: Non local patient ##{order_dto[:patient][:id]} on order ##{order_dto[:tracking_number]}")
29
29
  order_rejected(order_dto, "Patient NPID, '#{order_dto[:patient][:id]}', didn't match any local NPIDs")
@@ -58,7 +58,7 @@ module Lab
58
58
  end
59
59
 
60
60
  def process_order(order_dto)
61
- patient = find_patient_by_nhid(order_dto[:patient][:id])
61
+ patient = find_patient_by_nhid(order_dto[:patient][:id], order_dto[:tracking_number])
62
62
  unless patient
63
63
  logger.debug("Discarding order: Non local patient ##{order_dto[:patient][:id]} on order ##{order_dto[:tracking_number]}")
64
64
  order_rejected(order_dto, "Patient NPID, '#{order_dto[:patient][:id]}', didn't match any local NPIDs")
@@ -107,7 +107,7 @@ module Lab
107
107
 
108
108
  private
109
109
 
110
- def find_patient_by_nhid(nhid)
110
+ def find_patient_by_nhid(nhid, accession_number)
111
111
  national_id_type = PatientIdentifierType.where(name: ['National id', 'Old Identification Number'])
112
112
  identifiers = PatientIdentifier.where(type: national_id_type, identifier: nhid)
113
113
  .joins('INNER JOIN person ON person.person_id = patient_identifier.patient_id AND person.voided = 0')
@@ -126,10 +126,10 @@ module Lab
126
126
  patients = Patient.where(patient_id: identifiers.select(:patient_id))
127
127
  .distinct(:patient_id)
128
128
  .all
129
+ order = Order.find_by(patient_id: patients.select(:patient_id), accession_number: accession_number)
130
+ raise Lab::Lims::LimsException, "Order #{accession_number} does not exists for patient #{nhid}" if order.nil?
129
131
 
130
- raise Lab::Lims::DuplicateNHID, "Duplicate National Health ID: #{nhid}" if patients.size > 1
131
-
132
- patients.first
132
+ order.patient
133
133
  end
134
134
 
135
135
  ##
@@ -13,7 +13,7 @@ module Lab
13
13
  User.current = Utils.lab_user
14
14
 
15
15
  fork(&method(:start_push_worker))
16
- # fork(&method(:start_pull_worker))
16
+ fork(&method(:start_pull_worker))
17
17
  fork(&method(:start_acknowledgement_worker))
18
18
  fork(&method(:start_realtime_pull_worker)) if realtime_updates_enabled?
19
19
 
@@ -18,6 +18,7 @@ module Lab
18
18
 
19
19
  # Order types
20
20
  ORDER_TYPE_NAME = 'Lab'
21
+ HTS_ORDER_TYPE_NAME = 'HTS Lab'
21
22
 
22
23
  # Programs
23
24
  LAB_PROGRAM_NAME = 'Laboratory Program'
@@ -160,6 +160,7 @@ module Lab
160
160
  def create_rejection_notification(order_params)
161
161
  order = find_order order_params['tracking_number']
162
162
  data = { 'type': 'LIMS',
163
+ 'specimen': ConceptName.find_by(concept_id: order.concept_id)&.name,
163
164
  'accession_number': order&.accession_number,
164
165
  'order_date': order&.start_date,
165
166
  'arv_number': find_arv_number(order.patient_id),
@@ -226,8 +227,12 @@ module Lab
226
227
  access_number = params[:accession_number] || next_accession_number(params[:date]&.to_date || Date.today)
227
228
  raise 'Accession Number cannot be blank' unless access_number.present?
228
229
  raise 'Accession cannot be this short' unless access_number.length > 6
230
+
231
+ order_type = nil
232
+ order_type = OrderType.find_by_order_type_id!(params[:order_type_id]) if params[:order_type_id].present?
233
+
229
234
  Lab::LabOrder.create!(
230
- order_type: OrderType.find_by_name!(Lab::Metadata::ORDER_TYPE_NAME),
235
+ order_type: order_type || OrderType.find_by_name!(Lab::Metadata::ORDER_TYPE_NAME),
231
236
  concept_id: params.dig(:specimen, :concept_id) || unknown_concept_id,
232
237
  encounter_id: encounter.encounter_id,
233
238
  patient_id: encounter.patient_id,
@@ -32,17 +32,24 @@ module Lab
32
32
 
33
33
  serializer = Lab::ResultSerializer.serialize(results_obs)
34
34
  end
35
- process_acknowledgement(results_obs, result_enter_by)
36
- precess_notification_message(results_obs, serializer, result_enter_by)
35
+
36
+ ProcessLabResultJob.perform_later(results_obs.id, serializer, result_enter_by)
37
+
37
38
  Rails.logger.info("Lab::ResultsService: Result created for test #{test_id} #{serializer}")
38
39
  serializer
39
40
  end
40
41
 
42
+ def process_result_completion(results_obs, serializer, result_enter_by)
43
+ process_acknowledgement(results_obs, result_enter_by)
44
+ precess_notification_message(results_obs, serializer, result_enter_by)
45
+ end
46
+
41
47
  private
42
48
 
43
49
  def precess_notification_message(result, values, result_enter_by)
44
50
  order = Order.find(result.order_id)
45
51
  data = { Type: result_enter_by,
52
+ Specimen: ConceptName.find_by(concept_id: order.concept_id)&.name,
46
53
  'Test type': ConceptName.find_by(concept_id: result.test.value_coded)&.name,
47
54
  'Accession number': order&.accession_number,
48
55
  'Orde date': order&.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.0'
4
+ VERSION = '2.1.1'
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.0
4
+ version: 2.1.1
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-01-08 00:00:00.000000000 Z
11
+ date: 2026-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: couchrest
@@ -243,6 +243,7 @@ files:
243
243
  - app/controllers/lab/tests_controller.rb
244
244
  - app/controllers/lab/users_controller.rb
245
245
  - app/jobs/lab/application_job.rb
246
+ - app/jobs/lab/process_lab_result_job.rb
246
247
  - app/jobs/lab/push_order_job.rb
247
248
  - app/jobs/lab/update_patient_orders_job.rb
248
249
  - app/jobs/lab/void_order_job.rb